am 9ce2d0bb: am 06e62ab2: am cc47075c: Merge "Remove uses of libcxx.mk."

* commit '9ce2d0bb3702f2854e612cb743f4c508dd590981':
  Remove uses of libcxx.mk.
diff --git a/Android.mk b/Android.mk
index aa86911..17eeba8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,5 +12,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-subdirs := native java tests tools
+subdirs := common native java tests tools
 include $(call all-named-subdir-makefiles, $(subdirs))
diff --git a/common/Android.mk b/common/Android.mk
new file mode 100644
index 0000000..132a223
--- /dev/null
+++ b/common/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE := latinime-common
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := jsr305
+LOCAL_SDK_VERSION := 21
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Also build a host side library
+include $(CLEAR_VARS)
+LOCAL_MODULE := latinime-common-host
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/java/src/com/android/inputmethod/annotations/ExternallyReferenced.java b/common/src/com/android/inputmethod/annotations/ExternallyReferenced.java
similarity index 100%
rename from java/src/com/android/inputmethod/annotations/ExternallyReferenced.java
rename to common/src/com/android/inputmethod/annotations/ExternallyReferenced.java
diff --git a/java/src/com/android/inputmethod/annotations/UsedForTesting.java b/common/src/com/android/inputmethod/annotations/UsedForTesting.java
similarity index 100%
rename from java/src/com/android/inputmethod/annotations/UsedForTesting.java
rename to common/src/com/android/inputmethod/annotations/UsedForTesting.java
diff --git a/common/src/com/android/inputmethod/latin/common/CodePointUtils.java b/common/src/com/android/inputmethod/latin/common/CodePointUtils.java
new file mode 100644
index 0000000..ec59de8
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/CodePointUtils.java
@@ -0,0 +1,117 @@
+/*
+ * 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.Random;
+
+import javax.annotation.Nonnull;
+
+// Utility methods related with code points used for tests.
+// TODO: Figure out where this class should be.
+@UsedForTesting
+public class CodePointUtils {
+    private CodePointUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public static final int[] LATIN_ALPHABETS_LOWER = {
+        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+        0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
+        0x00E1 /* LATIN SMALL LETTER A WITH ACUTE */,
+        0x00E2 /* LATIN SMALL LETTER A WITH CIRCUMFLEX */,
+        0x00E3 /* LATIN SMALL LETTER A WITH TILDE */,
+        0x00E4 /* LATIN SMALL LETTER A WITH DIAERESIS */,
+        0x00E5 /* LATIN SMALL LETTER A WITH RING ABOVE */,
+        0x00E6 /* LATIN SMALL LETTER AE */,
+        0x00E7 /* LATIN SMALL LETTER C WITH CEDILLA */,
+        0x00E8 /* LATIN SMALL LETTER E WITH GRAVE */,
+        0x00E9 /* LATIN SMALL LETTER E WITH ACUTE */,
+        0x00EA /* LATIN SMALL LETTER E WITH CIRCUMFLEX */,
+        0x00EB /* LATIN SMALL LETTER E WITH DIAERESIS */,
+        0x00EC /* LATIN SMALL LETTER I WITH GRAVE */,
+        0x00ED /* LATIN SMALL LETTER I WITH ACUTE */,
+        0x00EE /* LATIN SMALL LETTER I WITH CIRCUMFLEX */,
+        0x00EF /* LATIN SMALL LETTER I WITH DIAERESIS */,
+        0x00F0 /* LATIN SMALL LETTER ETH */,
+        0x00F1 /* LATIN SMALL LETTER N WITH TILDE */,
+        0x00F2 /* LATIN SMALL LETTER O WITH GRAVE */,
+        0x00F3 /* LATIN SMALL LETTER O WITH ACUTE */,
+        0x00F4 /* LATIN SMALL LETTER O WITH CIRCUMFLEX */,
+        0x00F5 /* LATIN SMALL LETTER O WITH TILDE */,
+        0x00F6 /* LATIN SMALL LETTER O WITH DIAERESIS */,
+        0x00F7 /* LATIN SMALL LETTER O WITH STROKE */,
+        0x00F9 /* LATIN SMALL LETTER U WITH GRAVE */,
+        0x00FA /* LATIN SMALL LETTER U WITH ACUTE */,
+        0x00FB /* LATIN SMALL LETTER U WITH CIRCUMFLEX */,
+        0x00FC /* LATIN SMALL LETTER U WITH DIAERESIS */,
+        0x00FD /* LATIN SMALL LETTER Y WITH ACUTE */,
+        0x00FE /* LATIN SMALL LETTER THORN */,
+        0x00FF /* LATIN SMALL LETTER Y WITH DIAERESIS */
+    };
+
+    @UsedForTesting
+    @Nonnull
+    public static int[] generateCodePointSet(final int codePointSetSize,
+            @Nonnull final Random random) {
+        final int[] codePointSet = new int[codePointSetSize];
+        for (int i = codePointSet.length - 1; i >= 0; ) {
+            final int r = Math.abs(random.nextInt());
+            if (r < 0) {
+                continue;
+            }
+            // Don't insert 0~0x20, but insert any other code point.
+            // Code points are in the range 0~0x10FFFF.
+            final int candidateCodePoint = 0x20 + r % (Character.MAX_CODE_POINT - 0x20);
+            // Code points between MIN_ and MAX_SURROGATE are not valid on their own.
+            if (candidateCodePoint >= Character.MIN_SURROGATE
+                    && candidateCodePoint <= Character.MAX_SURROGATE) {
+                continue;
+            }
+            codePointSet[i] = candidateCodePoint;
+            --i;
+        }
+        return codePointSet;
+    }
+
+    /**
+     * Generates a random word.
+     */
+    @UsedForTesting
+    @Nonnull
+    public static String generateWord(@Nonnull final Random random,
+            @Nonnull final int[] codePointSet) {
+        final StringBuilder builder = new StringBuilder();
+        // 8 * 4 = 32 chars max, but we do it the following way so as to bias the random toward
+        // longer words. This should be closer to natural language, and more importantly, it will
+        // exercise the algorithms in dicttool much more.
+        final int count = 1 + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5)
+                + (Math.abs(random.nextInt()) % 5);
+        while (builder.length() < count) {
+            builder.appendCodePoint(codePointSet[Math.abs(random.nextInt()) % codePointSet.length]);
+        }
+        return builder.toString();
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/CollectionUtils.java b/common/src/com/android/inputmethod/latin/common/CollectionUtils.java
new file mode 100644
index 0000000..48df413
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/CollectionUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for working with collections.
+ */
+public final class CollectionUtils {
+    private CollectionUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    /**
+     * Converts a sub-range of the given array to an ArrayList of the appropriate type.
+     * @param array Array to be converted.
+     * @param start First index inclusive to be converted.
+     * @param end Last index exclusive to be converted.
+     * @throws IllegalArgumentException if start or end are out of range or start &gt; end.
+     */
+    @Nonnull
+    public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start,
+            final int end) {
+        if (start < 0 || start > end || end > array.length) {
+            throw new IllegalArgumentException("Invalid start: " + start + " end: " + end
+                    + " with array.length: " + array.length);
+        }
+
+        final ArrayList<E> list = new ArrayList<>(end - start);
+        for (int i = start; i < end; i++) {
+            list.add(array[i]);
+        }
+        return list;
+    }
+
+    /**
+     * Tests whether c contains no elements, true if c is null or c is empty.
+     * @param c Collection to test.
+     * @return Whether c contains no elements.
+     */
+    @UsedForTesting
+    public static boolean isNullOrEmpty(@Nullable final Collection<?> c) {
+        return c == null || c.isEmpty();
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/ComposedData.java b/common/src/com/android/inputmethod/latin/common/ComposedData.java
new file mode 100644
index 0000000..7f09660
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/ComposedData.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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.common;
+
+import javax.annotation.Nonnull;
+
+/**
+ * An immutable class that encapsulates a snapshot of word composition data.
+ */
+public class ComposedData {
+    @Nonnull
+    public final InputPointers mInputPointers;
+    public final boolean mIsBatchMode;
+    @Nonnull
+    public final String mTypedWord;
+
+    public ComposedData(@Nonnull final InputPointers inputPointers, final boolean isBatchMode,
+            @Nonnull final String typedWord) {
+        mInputPointers = inputPointers;
+        mIsBatchMode = isBatchMode;
+        mTypedWord = typedWord;
+    }
+
+    /**
+     * Copy the code points in the typed word to a destination array of ints.
+     *
+     * If the array is too small to hold the code points in the typed word, nothing is copied and
+     * -1 is returned.
+     *
+     * @param destination the array of ints.
+     * @return the number of copied code points.
+     */
+    public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
+            @Nonnull final int[] destination) {
+        // lastIndex is exclusive
+        final int lastIndex = mTypedWord.length()
+                - StringUtils.getTrailingSingleQuotesCount(mTypedWord);
+        if (lastIndex <= 0) {
+            // The string is empty or contains only single quotes.
+            return 0;
+        }
+
+        // The following function counts the number of code points in the text range which begins
+        // at index 0 and extends to the character at lastIndex.
+        final int codePointSize = Character.codePointCount(mTypedWord, 0, lastIndex);
+        if (codePointSize > destination.length) {
+            return -1;
+        }
+        return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWord, 0,
+                lastIndex, true /* downCase */);
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/Constants.java b/common/src/com/android/inputmethod/latin/common/Constants.java
new file mode 100644
index 0000000..b491c8c
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/Constants.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import javax.annotation.Nonnull;
+
+public final class Constants {
+
+    public static final class Color {
+        /**
+         * The alpha value for fully opaque.
+         */
+        public final static int ALPHA_OPAQUE = 255;
+    }
+
+    public static final class ImeOption {
+        /**
+         * The private IME option used to indicate that no microphone should be shown for a given
+         * text field. For instance, this is specified by the search dialog when the dialog is
+         * already showing a voice search button.
+         *
+         * @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed.
+         */
+        @SuppressWarnings("dep-ann")
+        public static final String NO_MICROPHONE_COMPAT = "nm";
+
+        /**
+         * The private IME option used to indicate that no microphone should be shown for a given
+         * text field. For instance, this is specified by the search dialog when the dialog is
+         * already showing a voice search button.
+         */
+        public static final String NO_MICROPHONE = "noMicrophoneKey";
+
+        /**
+         * The private IME option used to indicate that no settings key should be shown for a given
+         * text field.
+         */
+        public static final String NO_SETTINGS_KEY = "noSettingsKey";
+
+        /**
+         * The private IME option used to indicate that the given text field needs ASCII code points
+         * input.
+         *
+         * @deprecated Use EditorInfo#IME_FLAG_FORCE_ASCII.
+         */
+        @SuppressWarnings("dep-ann")
+        public static final String FORCE_ASCII = "forceAscii";
+
+        /**
+         * The private IME option used to suppress the floating gesture preview for a given text
+         * field. This overrides the corresponding keyboard settings preference.
+         * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled}
+         */
+        public static final String NO_FLOATING_GESTURE_PREVIEW = "noGestureFloatingPreview";
+
+        private ImeOption() {
+            // This utility class is not publicly instantiable.
+        }
+    }
+
+    public static final class Subtype {
+        /**
+         * The subtype mode used to indicate that the subtype is a keyboard.
+         */
+        public static final String KEYBOARD_MODE = "keyboard";
+
+        public static final class ExtraValue {
+            /**
+             * The subtype extra value used to indicate that this subtype is capable of
+             * entering ASCII characters.
+             */
+            public static final String ASCII_CAPABLE = "AsciiCapable";
+
+            /**
+             * The subtype extra value used to indicate that this subtype is enabled
+             * when the default subtype is not marked as ascii capable.
+             */
+            public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
+                    "EnabledWhenDefaultIsNotAsciiCapable";
+
+            /**
+             * The subtype extra value used to indicate that this subtype is capable of
+             * entering emoji characters.
+             */
+            public static final String EMOJI_CAPABLE = "EmojiCapable";
+
+            /**
+             * The subtype extra value used to indicate that this subtype requires a network
+             * connection to work.
+             */
+            public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
+
+            /**
+             * The subtype extra value used to indicate that the display name of this subtype
+             * contains a "%s" for printf-like replacement and it should be replaced by
+             * this extra value.
+             * This extra value is supported on JellyBean and later.
+             */
+            public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
+                    "UntranslatableReplacementStringInSubtypeName";
+
+            /**
+             * The subtype extra value used to indicate this subtype keyboard layout set name.
+             * This extra value is private to LatinIME.
+             */
+            public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
+
+            /**
+             * The subtype extra value used to indicate that this subtype is an additional subtype
+             * that the user defined. This extra value is private to LatinIME.
+             */
+            public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
+
+            /**
+             * The subtype extra value used to specify the combining rules.
+             */
+            public static final String COMBINING_RULES = "CombiningRules";
+
+            private ExtraValue() {
+                // This utility class is not publicly instantiable.
+            }
+        }
+
+        private Subtype() {
+            // This utility class is not publicly instantiable.
+        }
+    }
+
+    public static final class TextUtils {
+        /**
+         * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
+         * characters.  This value may be used with
+         * {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
+         * {@link android.text.TextUtils#CAP_MODE_WORDS}, and
+         * {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
+         */
+        // TODO: Straighten this out. It's bizarre to have to use android.text.TextUtils.CAP_MODE_*
+        // except for OFF that is in Constants.TextUtils.
+        public static final int CAP_MODE_OFF = 0;
+
+        private TextUtils() {
+            // This utility class is not publicly instantiable.
+        }
+    }
+
+    public static final int NOT_A_CODE = -1;
+    public static final int NOT_A_CURSOR_POSITION = -1;
+    // TODO: replace the following constants with state in InputTransaction?
+    public static final int NOT_A_COORDINATE = -1;
+    public static final int SUGGESTION_STRIP_COORDINATE = -2;
+    public static final int EXTERNAL_KEYBOARD_COORDINATE = -4;
+
+    // A hint on how many characters to cache from the TextView. A good value of this is given by
+    // how many characters we need to be able to almost always find the caps mode.
+    public static final int EDITOR_CONTENTS_CACHE_SIZE = 1024;
+    // How many characters we accept for the recapitalization functionality. This needs to be
+    // large enough for all reasonable purposes, but avoid purposeful attacks. 100k sounds about
+    // right for this.
+    public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100;
+
+    // Key events coming any faster than this are long-presses.
+    public static final int LONG_PRESS_MILLISECONDS = 200;
+    // TODO: Set this value appropriately.
+    public static final int GET_SUGGESTED_WORDS_TIMEOUT = 200;
+    // How many continuous deletes at which to start deleting at a higher speed.
+    public static final int DELETE_ACCELERATE_AT = 20;
+
+    public static final String WORD_SEPARATOR = " ";
+
+    public static boolean isValidCoordinate(final int coordinate) {
+        // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
+        // and {@link SPELL_CHECKER_COORDINATE}.
+        return coordinate >= 0;
+    }
+
+    /**
+     * Custom request code used in
+     * {@link com.android.inputmethod.keyboard.KeyboardActionListener#onCustomRequest(int)}.
+     */
+    // The code to show input method picker.
+    public static final int CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER = 1;
+
+    /**
+     * Some common keys code. Must be positive.
+     */
+    public static final int CODE_ENTER = '\n';
+    public static final int CODE_TAB = '\t';
+    public static final int CODE_SPACE = ' ';
+    public static final int CODE_PERIOD = '.';
+    public static final int CODE_COMMA = ',';
+    public static final int CODE_DASH = '-';
+    public static final int CODE_SINGLE_QUOTE = '\'';
+    public static final int CODE_DOUBLE_QUOTE = '"';
+    public static final int CODE_SLASH = '/';
+    public static final int CODE_BACKSLASH = '\\';
+    public static final int CODE_VERTICAL_BAR = '|';
+    public static final int CODE_COMMERCIAL_AT = '@';
+    public static final int CODE_PLUS = '+';
+    public static final int CODE_PERCENT = '%';
+    public static final int CODE_CLOSING_PARENTHESIS = ')';
+    public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
+    public static final int CODE_CLOSING_CURLY_BRACKET = '}';
+    public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
+    public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿
+    public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡
+    public static final int CODE_GRAVE_ACCENT = '`';
+    public static final int CODE_CIRCUMFLEX_ACCENT = '^';
+    public static final int CODE_TILDE = '~';
+
+    public static final String REGEXP_PERIOD = "\\.";
+    public static final String STRING_SPACE = " ";
+
+    /**
+     * Special keys code. Must be negative.
+     * These should be aligned with constants in
+     * {@link com.android.inputmethod.keyboard.internal.KeyboardCodesSet}.
+     */
+    public static final int CODE_SHIFT = -1;
+    public static final int CODE_CAPSLOCK = -2;
+    public static final int CODE_SWITCH_ALPHA_SYMBOL = -3;
+    public static final int CODE_OUTPUT_TEXT = -4;
+    public static final int CODE_DELETE = -5;
+    public static final int CODE_SETTINGS = -6;
+    public static final int CODE_SHORTCUT = -7;
+    public static final int CODE_ACTION_NEXT = -8;
+    public static final int CODE_ACTION_PREVIOUS = -9;
+    public static final int CODE_LANGUAGE_SWITCH = -10;
+    public static final int CODE_EMOJI = -11;
+    public static final int CODE_SHIFT_ENTER = -12;
+    public static final int CODE_SYMBOL_SHIFT = -13;
+    public static final int CODE_ALPHA_FROM_EMOJI = -14;
+    // Code value representing the code is not specified.
+    public static final int CODE_UNSPECIFIED = -15;
+
+    public static boolean isLetterCode(final int code) {
+        return code >= CODE_SPACE;
+    }
+
+    @Nonnull
+    public static String printableCode(final int code) {
+        switch (code) {
+        case CODE_SHIFT: return "shift";
+        case CODE_CAPSLOCK: return "capslock";
+        case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
+        case CODE_OUTPUT_TEXT: return "text";
+        case CODE_DELETE: return "delete";
+        case CODE_SETTINGS: return "settings";
+        case CODE_SHORTCUT: return "shortcut";
+        case CODE_ACTION_NEXT: return "actionNext";
+        case CODE_ACTION_PREVIOUS: return "actionPrevious";
+        case CODE_LANGUAGE_SWITCH: return "languageSwitch";
+        case CODE_EMOJI: return "emoji";
+        case CODE_SHIFT_ENTER: return "shiftEnter";
+        case CODE_ALPHA_FROM_EMOJI: return "alpha";
+        case CODE_UNSPECIFIED: return "unspec";
+        case CODE_TAB: return "tab";
+        case CODE_ENTER: return "enter";
+        case CODE_SPACE: return "space";
+        default:
+            if (code < CODE_SPACE) return String.format("\\u%02X", code);
+            if (code < 0x100) return String.format("%c", code);
+            if (code < 0x10000) return String.format("\\u%04X", code);
+            return String.format("\\U%05X", code);
+        }
+    }
+
+    @Nonnull
+    public static String printableCodes(@Nonnull final int[] codes) {
+        final StringBuilder sb = new StringBuilder();
+        boolean addDelimiter = false;
+        for (final int code : codes) {
+            if (code == NOT_A_CODE) break;
+            if (addDelimiter) sb.append(", ");
+            sb.append(printableCode(code));
+            addDelimiter = true;
+        }
+        return "[" + sb + "]";
+    }
+
+    /**
+     * Screen metrics (a.k.a. Device form factor) constants of
+     * {@link com.android.inputmethod.latin.R.integer#config_screen_metrics}.
+     */
+    public static final int SCREEN_METRICS_SMALL_PHONE = 0;
+    public static final int SCREEN_METRICS_LARGE_PHONE = 1;
+    public static final int SCREEN_METRICS_LARGE_TABLET = 2;
+    public static final int SCREEN_METRICS_SMALL_TABLET = 3;
+
+    @UsedForTesting
+    public static boolean isPhone(final int screenMetrics) {
+        return screenMetrics == SCREEN_METRICS_SMALL_PHONE
+                || screenMetrics == SCREEN_METRICS_LARGE_PHONE;
+    }
+
+    @UsedForTesting
+    public static boolean isTablet(final int screenMetrics) {
+        return screenMetrics == SCREEN_METRICS_SMALL_TABLET
+                || screenMetrics == SCREEN_METRICS_LARGE_TABLET;
+    }
+
+    /**
+     * Default capacity of gesture points container.
+     * This constant is used by {@link com.android.inputmethod.keyboard.internal.BatchInputArbiter}
+     * and etc. to preallocate regions that contain gesture event points.
+     */
+    public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
+
+    public static final int MAX_IME_DECODER_RESULTS = 20;
+    public static final int DECODER_SCORE_SCALAR = 1000000;
+    public static final int DECODER_MAX_SCORE = 1000000000;
+
+    public static final int EVENT_BACKSPACE = 1;
+    public static final int EVENT_REJECTION = 2;
+    public static final int EVENT_REVERT = 3;
+
+    private Constants() {
+        // This utility class is not publicly instantiable.
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java b/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java
new file mode 100644
index 0000000..0316624
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/CoordinateUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import javax.annotation.Nonnull;
+
+public final class CoordinateUtils {
+    private static final int INDEX_X = 0;
+    private static final int INDEX_Y = 1;
+    private static final int ELEMENT_SIZE = INDEX_Y + 1;
+
+    private CoordinateUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    @Nonnull
+    public static int[] newInstance() {
+        return new int[ELEMENT_SIZE];
+    }
+
+    public static int x(@Nonnull final int[] coords) {
+        return coords[INDEX_X];
+    }
+
+    public static int y(@Nonnull final int[] coords) {
+        return coords[INDEX_Y];
+    }
+
+    public static void set(@Nonnull final int[] coords, final int x, final int y) {
+        coords[INDEX_X] = x;
+        coords[INDEX_Y] = y;
+    }
+
+    public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) {
+        destination[INDEX_X] = source[INDEX_X];
+        destination[INDEX_Y] = source[INDEX_Y];
+    }
+
+    @Nonnull
+    public static int[] newCoordinateArray(final int arraySize) {
+        return new int[ELEMENT_SIZE * arraySize];
+    }
+
+    @Nonnull
+    public static int[] newCoordinateArray(final int arraySize,
+            final int defaultX, final int defaultY) {
+        final int[] result = new int[ELEMENT_SIZE * arraySize];
+        for (int i = 0; i < arraySize; ++i) {
+            setXYInArray(result, i, defaultX, defaultY);
+        }
+        return result;
+    }
+
+    public static int xFromArray(@Nonnull final int[] coordsArray, final int index) {
+        return coordsArray[ELEMENT_SIZE * index + INDEX_X];
+    }
+
+    public static int yFromArray(@Nonnull final int[] coordsArray, final int index) {
+        return coordsArray[ELEMENT_SIZE * index + INDEX_Y];
+    }
+
+    @Nonnull
+    public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) {
+        final int[] coords = newInstance();
+        set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index));
+        return coords;
+    }
+
+    public static void setXYInArray(@Nonnull final int[] coordsArray, final int index,
+            final int x, final int y) {
+        final int baseIndex = ELEMENT_SIZE * index;
+        coordsArray[baseIndex + INDEX_X] = x;
+        coordsArray[baseIndex + INDEX_Y] = y;
+    }
+
+    public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index,
+            @Nonnull final int[] coords) {
+        setXYInArray(coordsArray, index, x(coords), y(coords));
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/FileUtils.java b/common/src/com/android/inputmethod/latin/common/FileUtils.java
new file mode 100644
index 0000000..6768458
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/FileUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.common;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * A simple class to help with removing directories recursively.
+ */
+public class FileUtils {
+    public static boolean deleteRecursively(final File path) {
+        if (path.isDirectory()) {
+            final File[] files = path.listFiles();
+            if (files != null) {
+                for (final File child : files) {
+                    deleteRecursively(child);
+                }
+            }
+        }
+        return path.delete();
+    }
+
+    public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) {
+        if (!dir.isDirectory()) {
+            return false;
+        }
+        final File[] files = dir.listFiles(fileNameFilter);
+        if (files == null) {
+            return false;
+        }
+        boolean hasDeletedAllFiles = true;
+        for (final File file : files) {
+            if (!deleteRecursively(file)) {
+                hasDeletedAllFiles = false;
+            }
+        }
+        return hasDeletedAllFiles;
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/InputPointers.java b/common/src/com/android/inputmethod/latin/common/InputPointers.java
new file mode 100644
index 0000000..4b2ae7e
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/InputPointers.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import javax.annotation.Nonnull;
+
+// TODO: This class is not thread-safe.
+public final class InputPointers {
+    private static final boolean DEBUG_TIME = false;
+
+    private final int mDefaultCapacity;
+    private final ResizableIntArray mXCoordinates;
+    private final ResizableIntArray mYCoordinates;
+    private final ResizableIntArray mPointerIds;
+    private final ResizableIntArray mTimes;
+
+    public InputPointers(final int defaultCapacity) {
+        mDefaultCapacity = defaultCapacity;
+        mXCoordinates = new ResizableIntArray(defaultCapacity);
+        mYCoordinates = new ResizableIntArray(defaultCapacity);
+        mPointerIds = new ResizableIntArray(defaultCapacity);
+        mTimes = new ResizableIntArray(defaultCapacity);
+    }
+
+    private void fillWithLastTimeUntil(final int index) {
+        final int fromIndex = mTimes.getLength();
+        // Fill the gap with the latest time.
+        // See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
+        if (fromIndex <= 0) {
+            return;
+        }
+        final int fillLength = index - fromIndex + 1;
+        if (fillLength <= 0) {
+            return;
+        }
+        final int lastTime = mTimes.get(fromIndex - 1);
+        mTimes.fill(lastTime, fromIndex, fillLength);
+    }
+
+    public void addPointerAt(final int index, final int x, final int y, final int pointerId,
+            final int time) {
+        mXCoordinates.addAt(index, x);
+        mYCoordinates.addAt(index, y);
+        mPointerIds.addAt(index, pointerId);
+        if (DEBUG_TIME) {
+            fillWithLastTimeUntil(index);
+        }
+        mTimes.addAt(index, time);
+    }
+
+    @UsedForTesting
+    public void addPointer(final int x, final int y, final int pointerId, final int time) {
+        mXCoordinates.add(x);
+        mYCoordinates.add(y);
+        mPointerIds.add(pointerId);
+        mTimes.add(time);
+    }
+
+    public void set(@Nonnull final InputPointers ip) {
+        mXCoordinates.set(ip.mXCoordinates);
+        mYCoordinates.set(ip.mYCoordinates);
+        mPointerIds.set(ip.mPointerIds);
+        mTimes.set(ip.mTimes);
+    }
+
+    public void copy(@Nonnull final InputPointers ip) {
+        mXCoordinates.copy(ip.mXCoordinates);
+        mYCoordinates.copy(ip.mYCoordinates);
+        mPointerIds.copy(ip.mPointerIds);
+        mTimes.copy(ip.mTimes);
+    }
+
+    /**
+     * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
+     * to the end of this.
+     * @param pointerId the pointer id of the source.
+     * @param times the source {@link ResizableIntArray} to read the event times from.
+     * @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from.
+     * @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from.
+     * @param startPos the starting index of the data in {@code times} and etc.
+     * @param length the number of data to be appended.
+     */
+    public void append(final int pointerId, @Nonnull final ResizableIntArray times,
+            @Nonnull final ResizableIntArray xCoordinates,
+            @Nonnull final ResizableIntArray yCoordinates, final int startPos, final int length) {
+        if (length == 0) {
+            return;
+        }
+        mXCoordinates.append(xCoordinates, startPos, length);
+        mYCoordinates.append(yCoordinates, startPos, length);
+        mPointerIds.fill(pointerId, mPointerIds.getLength(), length);
+        mTimes.append(times, startPos, length);
+    }
+
+    /**
+     * Shift to the left by elementCount, discarding elementCount pointers at the start.
+     * @param elementCount how many elements to shift.
+     */
+    @UsedForTesting
+    public void shift(final int elementCount) {
+        mXCoordinates.shift(elementCount);
+        mYCoordinates.shift(elementCount);
+        mPointerIds.shift(elementCount);
+        mTimes.shift(elementCount);
+    }
+
+    public void reset() {
+        final int defaultCapacity = mDefaultCapacity;
+        mXCoordinates.reset(defaultCapacity);
+        mYCoordinates.reset(defaultCapacity);
+        mPointerIds.reset(defaultCapacity);
+        mTimes.reset(defaultCapacity);
+    }
+
+    public int getPointerSize() {
+        return mXCoordinates.getLength();
+    }
+
+    @Nonnull
+    public int[] getXCoordinates() {
+        return mXCoordinates.getPrimitiveArray();
+    }
+
+    @Nonnull
+    public int[] getYCoordinates() {
+        return mYCoordinates.getPrimitiveArray();
+    }
+
+    @Nonnull
+    public int[] getPointerIds() {
+        return mPointerIds.getPrimitiveArray();
+    }
+
+    /**
+     * Gets the time each point was registered, in milliseconds, relative to the first event in the
+     * sequence.
+     * @return The time each point was registered, in milliseconds, relative to the first event in
+     * the sequence.
+     */
+    @Nonnull
+    public int[] getTimes() {
+        return mTimes.getPrimitiveArray();
+    }
+
+    @Override
+    public String toString() {
+        return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes
+                + " x=" + mXCoordinates + " y=" + mYCoordinates;
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/LocaleUtils.java b/common/src/com/android/inputmethod/latin/common/LocaleUtils.java
new file mode 100644
index 0000000..d5878c0
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/LocaleUtils.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2011 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.common;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * A class to help with handling Locales in string form.
+ *
+ * This file has the same meaning and features (and shares all of its code) with the one with the
+ * same name in Latin IME. They need to be kept synchronized; for any update/bugfix to
+ * this file, consider also updating/fixing the version in Latin IME.
+ */
+public final class LocaleUtils {
+    private LocaleUtils() {
+        // Intentional empty constructor for utility class.
+    }
+
+    // Locale match level constants.
+    // A higher level of match is guaranteed to have a higher numerical value.
+    // Some room is left within constants to add match cases that may arise necessary
+    // in the future, for example differentiating between the case where the countries
+    // are both present and different, and the case where one of the locales does not
+    // specify the countries. This difference is not needed now.
+
+    // Nothing matches.
+    public static final int LOCALE_NO_MATCH = 0;
+    // The languages matches, but the country are different. Or, the reference locale requires a
+    // country and the tested locale does not have one.
+    public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
+    // The languages and country match, but the variants are different. Or, the reference locale
+    // requires a variant and the tested locale does not have one.
+    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
+    // The required locale is null or empty so it will accept anything, and the tested locale
+    // is non-null and non-empty.
+    public static final int LOCALE_ANY_MATCH = 10;
+    // The language matches, and the tested locale specifies a country but the reference locale
+    // does not require one.
+    public static final int LOCALE_LANGUAGE_MATCH = 15;
+    // The language and the country match, and the tested locale specifies a variant but the
+    // reference locale does not require one.
+    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
+    // The compared locales are fully identical. This is the best match level.
+    public static final int LOCALE_FULL_MATCH = 30;
+
+    // The level at which a match is "normally" considered a locale match with standard algorithms.
+    // Don't use this directly, use #isMatch to test.
+    private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
+
+    // Make this match the maximum match level. If this evolves to have more than 2 digits
+    // when written in base 10, also adjust the getMatchLevelSortedString method.
+    private static final int MATCH_LEVEL_MAX = 30;
+
+    /**
+     * Return how well a tested locale matches a reference locale.
+     *
+     * This will check the tested locale against the reference locale and return a measure of how
+     * a well it matches the reference. The general idea is that the tested locale has to match
+     * every specified part of the required locale. A full match occur when they are equal, a
+     * partial match when the tested locale agrees with the reference locale but is more specific,
+     * and a difference when the tested locale does not comply with all requirements from the
+     * reference locale.
+     * In more detail, if the reference locale specifies at least a language and the testedLocale
+     * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
+     * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
+     * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
+     * tested locale agree on the language, but not on the country,
+     * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
+     * and LOCALE_LANGUAGE_MATCH otherwise.
+     * If they agree on both the language and the country, but not on the variant,
+     * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
+     * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
+     * LOCALE_FULL_MATCH is returned.
+     * Examples:
+     * en <=> en_US  => LOCALE_LANGUAGE_MATCH
+     * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
+     * en_US_POSIX <=> en_US_Android  =>  LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
+     * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
+     * sp_US <=> en_US  =>  LOCALE_NO_MATCH
+     * de <=> de  => LOCALE_FULL_MATCH
+     * en_US <=> en_US => LOCALE_FULL_MATCH
+     * "" <=> en_US => LOCALE_ANY_MATCH
+     *
+     * @param referenceLocale the reference locale to test against.
+     * @param testedLocale the locale to test.
+     * @return a constant that measures how well the tested locale matches the reference locale.
+     */
+    public static int getMatchLevel(@Nullable final String referenceLocale,
+            @Nullable final String testedLocale) {
+        if (StringUtils.isEmpty(referenceLocale)) {
+            return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
+        }
+        if (null == testedLocale) return LOCALE_NO_MATCH;
+        final String[] referenceParams = referenceLocale.split("_", 3);
+        final String[] testedParams = testedLocale.split("_", 3);
+        // By spec of String#split, [0] cannot be null and length cannot be 0.
+        if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
+        switch (referenceParams.length) {
+        case 1:
+            return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
+        case 2:
+            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+            if (!referenceParams[1].equals(testedParams[1]))
+                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+            if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
+            return LOCALE_FULL_MATCH;
+        case 3:
+            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+            if (!referenceParams[1].equals(testedParams[1]))
+                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
+            if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+            if (!referenceParams[2].equals(testedParams[2]))
+                return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
+            return LOCALE_FULL_MATCH;
+        }
+        // It should be impossible to come here
+        return LOCALE_NO_MATCH;
+    }
+
+    /**
+     * Return a string that represents this match level, with better matches first.
+     *
+     * The strings are sorted in lexicographic order: a better match will always be less than
+     * a worse match when compared together.
+     */
+    public static String getMatchLevelSortedString(final int matchLevel) {
+        // This works because the match levels are 0~99 (actually 0~30)
+        // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
+        return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
+    }
+
+    /**
+     * Find out whether a match level should be considered a match.
+     *
+     * This method takes a match level as returned by the #getMatchLevel method, and returns whether
+     * it should be considered a match in the usual sense with standard Locale functions.
+     *
+     * @param level the match level, as returned by getMatchLevel.
+     * @return whether this is a match or not.
+     */
+    public static boolean isMatch(final int level) {
+        return LOCALE_MATCH <= level;
+    }
+
+    private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
+
+    /**
+     * Creates a locale from a string specification.
+     * @param localeString a string specification of a locale, in a format of "ll_cc_variant" where
+     * "ll" is a language code, "cc" is a country code.
+     */
+    @Nonnull
+    public static Locale constructLocaleFromString(@Nonnull final String localeString) {
+        synchronized (sLocaleCache) {
+            if (sLocaleCache.containsKey(localeString)) {
+                return sLocaleCache.get(localeString);
+            }
+            final String[] elements = localeString.split("_", 3);
+            final Locale locale;
+            if (elements.length == 1) {
+                locale = new Locale(elements[0] /* language */);
+            } else if (elements.length == 2) {
+                locale = new Locale(elements[0] /* language */, elements[1] /* country */);
+            } else { // localeParams.length == 3
+                locale = new Locale(elements[0] /* language */, elements[1] /* country */,
+                        elements[2] /* variant */);
+            }
+            sLocaleCache.put(localeString, locale);
+            return locale;
+        }
+    }
+
+    // TODO: Get this information from the framework instead of maintaining here by ourselves.
+    private static final HashSet<String> sRtlLanguageCodes = new HashSet<>();
+    static {
+        // List of known Right-To-Left language codes.
+        sRtlLanguageCodes.add("ar"); // Arabic
+        sRtlLanguageCodes.add("fa"); // Persian
+        sRtlLanguageCodes.add("iw"); // Hebrew
+        sRtlLanguageCodes.add("ku"); // Kurdish
+        sRtlLanguageCodes.add("ps"); // Pashto
+        sRtlLanguageCodes.add("sd"); // Sindhi
+        sRtlLanguageCodes.add("ug"); // Uyghur
+        sRtlLanguageCodes.add("ur"); // Urdu
+        sRtlLanguageCodes.add("yi"); // Yiddish
+    }
+
+    public static boolean isRtlLanguage(@Nonnull final Locale locale) {
+        return sRtlLanguageCodes.contains(locale.getLanguage());
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java b/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java
new file mode 100644
index 0000000..d673442
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/NativeSuggestOptions.java
@@ -0,0 +1,63 @@
+/*
+ * 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.common;
+
+public class NativeSuggestOptions {
+    // Need to update suggest_options.h when you add, remove or reorder options.
+    private static final int IS_GESTURE = 0;
+    private static final int USE_FULL_EDIT_DISTANCE = 1;
+    private static final int BLOCK_OFFENSIVE_WORDS = 2;
+    private static final int SPACE_AWARE_GESTURE_ENABLED = 3;
+    private static final int WEIGHT_FOR_LOCALE_IN_THOUSANDS = 4;
+    private static final int OPTIONS_SIZE = 5;
+
+    private final int[] mOptions;
+
+    public NativeSuggestOptions() {
+        mOptions = new int[OPTIONS_SIZE];
+    }
+
+    public void setIsGesture(final boolean value) {
+        setBooleanOption(IS_GESTURE, value);
+    }
+
+    public void setUseFullEditDistance(final boolean value) {
+        setBooleanOption(USE_FULL_EDIT_DISTANCE, value);
+    }
+
+    public void setBlockOffensiveWords(final boolean value) {
+        setBooleanOption(BLOCK_OFFENSIVE_WORDS, value);
+    }
+
+    public void setWeightForLocale(final float value) {
+        // We're passing this option as a fixed point value, in thousands. This is decoded in
+        // native code by SuggestOptions#weightForLocale().
+        setIntegerOption(WEIGHT_FOR_LOCALE_IN_THOUSANDS, (int) (value * 1000));
+    }
+
+    public int[] getOptions() {
+        return mOptions;
+    }
+
+    private void setBooleanOption(final int key, final boolean value) {
+        mOptions[key] = value ? 1 : 0;
+    }
+
+    private void setIntegerOption(final int key, final int value) {
+        mOptions[key] = value;
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java b/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java
new file mode 100644
index 0000000..77f5c4c
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/ResizableIntArray.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+// TODO: This class is not thread-safe.
+public final class ResizableIntArray {
+    @Nonnull
+    private int[] mArray;
+    private int mLength;
+
+    public ResizableIntArray(final int capacity) {
+        reset(capacity);
+    }
+
+    public int get(final int index) {
+        if (index < mLength) {
+            return mArray[index];
+        }
+        throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
+    }
+
+    public void addAt(final int index, final int val) {
+        if (index < mLength) {
+            mArray[index] = val;
+        } else {
+            mLength = index;
+            add(val);
+        }
+    }
+
+    public void add(final int val) {
+        final int currentLength = mLength;
+        ensureCapacity(currentLength + 1);
+        mArray[currentLength] = val;
+        mLength = currentLength + 1;
+    }
+
+    /**
+     * Calculate the new capacity of {@code mArray}.
+     * @param minimumCapacity the minimum capacity that the {@code mArray} should have.
+     * @return the new capacity that the {@code mArray} should have. Returns zero when there is no
+     * need to expand {@code mArray}.
+     */
+    private int calculateCapacity(final int minimumCapacity) {
+        final int currentCapcity = mArray.length;
+        if (currentCapcity < minimumCapacity) {
+            final int nextCapacity = currentCapcity * 2;
+            // The following is the same as return Math.max(minimumCapacity, nextCapacity);
+            return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity;
+        }
+        return 0;
+    }
+
+    private void ensureCapacity(final int minimumCapacity) {
+        final int newCapacity = calculateCapacity(minimumCapacity);
+        if (newCapacity > 0) {
+            // TODO: Implement primitive array pool.
+            mArray = Arrays.copyOf(mArray, newCapacity);
+        }
+    }
+
+    public int getLength() {
+        return mLength;
+    }
+
+    public void setLength(final int newLength) {
+        ensureCapacity(newLength);
+        mLength = newLength;
+    }
+
+    public void reset(final int capacity) {
+        // TODO: Implement primitive array pool.
+        mArray = new int[capacity];
+        mLength = 0;
+    }
+
+    @Nonnull
+    public int[] getPrimitiveArray() {
+        return mArray;
+    }
+
+    public void set(@Nonnull final ResizableIntArray ip) {
+        // TODO: Implement primitive array pool.
+        mArray = ip.mArray;
+        mLength = ip.mLength;
+    }
+
+    public void copy(@Nonnull final ResizableIntArray ip) {
+        final int newCapacity = calculateCapacity(ip.mLength);
+        if (newCapacity > 0) {
+            // TODO: Implement primitive array pool.
+            mArray = new int[newCapacity];
+        }
+        System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength);
+        mLength = ip.mLength;
+    }
+
+    public void append(@Nonnull final ResizableIntArray src, final int startPos, final int length) {
+        if (length == 0) {
+            return;
+        }
+        final int currentLength = mLength;
+        final int newLength = currentLength + length;
+        ensureCapacity(newLength);
+        System.arraycopy(src.mArray, startPos, mArray, currentLength, length);
+        mLength = newLength;
+    }
+
+    public void fill(final int value, final int startPos, final int length) {
+        if (startPos < 0 || length < 0) {
+            throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length);
+        }
+        final int endPos = startPos + length;
+        ensureCapacity(endPos);
+        Arrays.fill(mArray, startPos, endPos, value);
+        if (mLength < endPos) {
+            mLength = endPos;
+        }
+    }
+
+    /**
+     * Shift to the left by elementCount, discarding elementCount pointers at the start.
+     * @param elementCount how many elements to shift.
+     */
+    @UsedForTesting
+    public void shift(final int elementCount) {
+        System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount);
+        mLength -= elementCount;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < mLength; i++) {
+            if (i != 0) {
+                sb.append(",");
+            }
+            sb.append(mArray[i]);
+        }
+        return "[" + sb + "]";
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/StringUtils.java b/common/src/com/android/inputmethod/latin/common/StringUtils.java
new file mode 100644
index 0000000..572f0cd
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/StringUtils.java
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public final class StringUtils {
+    public static final int CAPITALIZE_NONE = 0;  // No caps, or mixed case
+    public static final int CAPITALIZE_FIRST = 1; // First only
+    public static final int CAPITALIZE_ALL = 2;   // All caps
+
+    @Nonnull
+    private static final String EMPTY_STRING = "";
+
+    private static final char CHAR_LINE_FEED = 0X000A;
+    private static final char CHAR_VERTICAL_TAB = 0X000B;
+    private static final char CHAR_FORM_FEED = 0X000C;
+    private static final char CHAR_CARRIAGE_RETURN = 0X000D;
+    private static final char CHAR_NEXT_LINE = 0X0085;
+    private static final char CHAR_LINE_SEPARATOR = 0X2028;
+    private static final char CHAR_PARAGRAPH_SEPARATOR = 0X2029;
+
+    private StringUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    // Taken from android.text.TextUtils. We are extensively using this method in many places,
+    // some of which don't have the android libraries available.
+    /**
+     * Returns true if the string is null or 0-length.
+     * @param str the string to be examined
+     * @return true if str is null or zero length
+     */
+    public static boolean isEmpty(@Nullable final CharSequence str) {
+        return (str == null || str.length() == 0);
+    }
+
+    // Taken from android.text.TextUtils to cut the dependency to the Android framework.
+    /**
+     * Returns a string containing the tokens joined by delimiters.
+     * @param delimiter the delimiter
+     * @param tokens an array objects to be joined. Strings will be formed from
+     *     the objects by calling object.toString().
+     */
+    @Nonnull
+    public static String join(@Nonnull final CharSequence delimiter,
+            @Nonnull final Iterable<?> tokens) {
+        final StringBuilder sb = new StringBuilder();
+        boolean firstTime = true;
+        for (final Object token: tokens) {
+            if (firstTime) {
+                firstTime = false;
+            } else {
+                sb.append(delimiter);
+            }
+            sb.append(token);
+        }
+        return sb.toString();
+    }
+
+    // Taken from android.text.TextUtils to cut the dependency to the Android framework.
+    /**
+     * Returns true if a and b are equal, including if they are both null.
+     * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
+     * both the arguments were instances of String.</i></p>
+     * @param a first CharSequence to check
+     * @param b second CharSequence to check
+     * @return true if a and b are equal
+     */
+    public static boolean equals(@Nullable final CharSequence a, @Nullable final CharSequence b) {
+        if (a == b) {
+            return true;
+        }
+        final int length;
+        if (a != null && b != null && (length = a.length()) == b.length()) {
+            if (a instanceof String && b instanceof String) {
+                return a.equals(b);
+            }
+            for (int i = 0; i < length; i++) {
+                if (a.charAt(i) != b.charAt(i)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public static int codePointCount(@Nullable final CharSequence text) {
+        if (isEmpty(text)) {
+            return 0;
+        }
+        return Character.codePointCount(text, 0, text.length());
+    }
+
+    @Nonnull
+    public static String newSingleCodePointString(final int codePoint) {
+        if (Character.charCount(codePoint) == 1) {
+            // Optimization: avoid creating a temporary array for characters that are
+            // represented by a single char value
+            return String.valueOf((char) codePoint);
+        }
+        // For surrogate pair
+        return new String(Character.toChars(codePoint));
+    }
+
+    public static boolean containsInArray(@Nonnull final String text,
+            @Nonnull final String[] array) {
+        for (final String element : array) {
+            if (text.equals(element)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Comma-Splittable Text is similar to Comma-Separated Values (CSV) but has much simpler syntax.
+     * Unlike CSV, Comma-Splittable Text has no escaping mechanism, so that the text can't contain
+     * a comma character in it.
+     */
+    @Nonnull
+    private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ",";
+
+    public static boolean containsInCommaSplittableText(@Nonnull final String text,
+            @Nullable final String extraValues) {
+        if (isEmpty(extraValues)) {
+            return false;
+        }
+        return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT));
+    }
+
+    @Nonnull
+    public static String removeFromCommaSplittableTextIfExists(@Nonnull final String text,
+            @Nullable final String extraValues) {
+        if (isEmpty(extraValues)) {
+            return EMPTY_STRING;
+        }
+        final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT);
+        if (!containsInArray(text, elements)) {
+            return extraValues;
+        }
+        final ArrayList<String> result = new ArrayList<>(elements.length - 1);
+        for (final String element : elements) {
+            if (!text.equals(element)) {
+                result.add(element);
+            }
+        }
+        return join(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT, result);
+    }
+
+    /**
+     * Remove duplicates from an array of strings.
+     *
+     * This method will always keep the first occurrence of all strings at their position
+     * in the array, removing the subsequent ones.
+     */
+    public static void removeDupes(@Nonnull final ArrayList<String> suggestions) {
+        if (suggestions.size() < 2) {
+            return;
+        }
+        int i = 1;
+        // Don't cache suggestions.size(), since we may be removing items
+        while (i < suggestions.size()) {
+            final String cur = suggestions.get(i);
+            // Compare each suggestion with each previous suggestion
+            for (int j = 0; j < i; j++) {
+                final String previous = suggestions.get(j);
+                if (equals(cur, previous)) {
+                    suggestions.remove(i);
+                    i--;
+                    break;
+                }
+            }
+            i++;
+        }
+    }
+
+    @Nonnull
+    public static String capitalizeFirstCodePoint(@Nonnull final String s,
+            @Nonnull final Locale locale) {
+        if (s.length() <= 1) {
+            return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
+        }
+        // Please refer to the comment below in
+        // {@link #capitalizeFirstAndDowncaseRest(String,Locale)} as this has the same shortcomings
+        final int cutoff = s.offsetByCodePoints(0, 1);
+        return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale))
+                + s.substring(cutoff);
+    }
+
+    @Nonnull
+    public static String capitalizeFirstAndDowncaseRest(@Nonnull final String s,
+            @Nonnull final Locale locale) {
+        if (s.length() <= 1) {
+            return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
+        }
+        // TODO: fix the bugs below
+        // - It does not work for Serbian, because it fails to account for the "lj" character,
+        // which should be "Lj" in title case and "LJ" in upper case.
+        // - It does not work for Dutch, because it fails to account for the "ij" digraph when it's
+        // written as two separate code points. They are two different characters but both should
+        // be capitalized as "IJ" as if they were a single letter in most words (not all). If the
+        // unicode char for the ligature is used however, it works.
+        final int cutoff = s.offsetByCodePoints(0, 1);
+        return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale))
+                + s.substring(cutoff).toLowerCase(locale);
+    }
+
+    @Nonnull
+    public static int[] toCodePointArray(@Nonnull final CharSequence charSequence) {
+        return toCodePointArray(charSequence, 0, charSequence.length());
+    }
+
+    @Nonnull
+    private static final int[] EMPTY_CODEPOINTS = {};
+
+    /**
+     * Converts a range of a string to an array of code points.
+     * @param charSequence the source string.
+     * @param startIndex the start index inside the string in java chars, inclusive.
+     * @param endIndex the end index inside the string in java chars, exclusive.
+     * @return a new array of code points. At most endIndex - startIndex, but possibly less.
+     */
+    @Nonnull
+    public static int[] toCodePointArray(@Nonnull final CharSequence charSequence,
+            final int startIndex, final int endIndex) {
+        final int length = charSequence.length();
+        if (length <= 0) {
+            return EMPTY_CODEPOINTS;
+        }
+        final int[] codePoints =
+                new int[Character.codePointCount(charSequence, startIndex, endIndex)];
+        copyCodePointsAndReturnCodePointCount(codePoints, charSequence, startIndex, endIndex,
+                false /* downCase */);
+        return codePoints;
+    }
+
+    /**
+     * Copies the codepoints in a CharSequence to an int array.
+     *
+     * This method assumes there is enough space in the array to store the code points. The size
+     * can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
+     * method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
+     * Also, this method makes no effort to be thread-safe. Do not modify the CharSequence while
+     * this method is running, or the behavior is undefined.
+     * This method can optionally downcase code points before copying them, but it pays no attention
+     * to locale while doing so.
+     *
+     * @param destination the int array.
+     * @param charSequence the CharSequence.
+     * @param startIndex the start index inside the string in java chars, inclusive.
+     * @param endIndex the end index inside the string in java chars, exclusive.
+     * @param downCase if this is true, code points will be downcased before being copied.
+     * @return the number of copied code points.
+     */
+    public static int copyCodePointsAndReturnCodePointCount(@Nonnull final int[] destination,
+            @Nonnull final CharSequence charSequence, final int startIndex, final int endIndex,
+            final boolean downCase) {
+        int destIndex = 0;
+        for (int index = startIndex; index < endIndex;
+                index = Character.offsetByCodePoints(charSequence, index, 1)) {
+            final int codePoint = Character.codePointAt(charSequence, index);
+            // TODO: stop using this, as it's not aware of the locale and does not always do
+            // the right thing.
+            destination[destIndex] = downCase ? Character.toLowerCase(codePoint) : codePoint;
+            destIndex++;
+        }
+        return destIndex;
+    }
+
+    @Nonnull
+    public static int[] toSortedCodePointArray(@Nonnull final String string) {
+        final int[] codePoints = toCodePointArray(string);
+        Arrays.sort(codePoints);
+        return codePoints;
+    }
+
+    /**
+     * Construct a String from a code point array
+     *
+     * @param codePoints a code point array that is null terminated when its logical length is
+     * shorter than the array length.
+     * @return a string constructed from the code point array.
+     */
+    @Nonnull
+    public static String getStringFromNullTerminatedCodePointArray(
+            @Nonnull final int[] codePoints) {
+        int stringLength = codePoints.length;
+        for (int i = 0; i < codePoints.length; i++) {
+            if (codePoints[i] == 0) {
+                stringLength = i;
+                break;
+            }
+        }
+        return new String(codePoints, 0 /* offset */, stringLength);
+    }
+
+    // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
+    public static int getCapitalizationType(@Nonnull final String text) {
+        // If the first char is not uppercase, then the word is either all lower case or
+        // camel case, and in either case we return CAPITALIZE_NONE.
+        final int len = text.length();
+        int index = 0;
+        for (; index < len; index = text.offsetByCodePoints(index, 1)) {
+            if (Character.isLetter(text.codePointAt(index))) {
+                break;
+            }
+        }
+        if (index == len) return CAPITALIZE_NONE;
+        if (!Character.isUpperCase(text.codePointAt(index))) {
+            return CAPITALIZE_NONE;
+        }
+        int capsCount = 1;
+        int letterCount = 1;
+        for (index = text.offsetByCodePoints(index, 1); index < len;
+                index = text.offsetByCodePoints(index, 1)) {
+            if (1 != capsCount && letterCount != capsCount) break;
+            final int codePoint = text.codePointAt(index);
+            if (Character.isUpperCase(codePoint)) {
+                ++capsCount;
+                ++letterCount;
+            } else if (Character.isLetter(codePoint)) {
+                // We need to discount non-letters since they may not be upper-case, but may
+                // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
+                ++letterCount;
+            }
+        }
+        // We know the first char is upper case. So we want to test if either every letter other
+        // than the first is lower case, or if they are all upper case. If the string is exactly
+        // one char long, then we will arrive here with letterCount 1, and this is correct, too.
+        if (1 == capsCount) return CAPITALIZE_FIRST;
+        return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
+    }
+
+    public static boolean isIdenticalAfterUpcase(@Nonnull final String text) {
+        final int length = text.length();
+        int i = 0;
+        while (i < length) {
+            final int codePoint = text.codePointAt(i);
+            if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) {
+                return false;
+            }
+            i += Character.charCount(codePoint);
+        }
+        return true;
+    }
+
+    public static boolean isIdenticalAfterDowncase(@Nonnull final String text) {
+        final int length = text.length();
+        int i = 0;
+        while (i < length) {
+            final int codePoint = text.codePointAt(i);
+            if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) {
+                return false;
+            }
+            i += Character.charCount(codePoint);
+        }
+        return true;
+    }
+
+    public static boolean isIdenticalAfterCapitalizeEachWord(@Nonnull final String text,
+            @Nonnull final int[] sortedSeparators) {
+        boolean needsCapsNext = true;
+        final int len = text.length();
+        for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
+            final int codePoint = text.codePointAt(i);
+            if (Character.isLetter(codePoint)) {
+                if ((needsCapsNext && !Character.isUpperCase(codePoint))
+                        || (!needsCapsNext && !Character.isLowerCase(codePoint))) {
+                    return false;
+                }
+            }
+            // We need a capital letter next if this is a separator.
+            needsCapsNext = (Arrays.binarySearch(sortedSeparators, codePoint) >= 0);
+        }
+        return true;
+    }
+
+    // TODO: like capitalizeFirst*, this does not work perfectly for Dutch because of the IJ digraph
+    // which should be capitalized together in *some* cases.
+    @Nonnull
+    public static String capitalizeEachWord(@Nonnull final String text,
+            @Nonnull final int[] sortedSeparators, @Nonnull final Locale locale) {
+        final StringBuilder builder = new StringBuilder();
+        boolean needsCapsNext = true;
+        final int len = text.length();
+        for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
+            final String nextChar = text.substring(i, text.offsetByCodePoints(i, 1));
+            if (needsCapsNext) {
+                builder.append(nextChar.toUpperCase(locale));
+            } else {
+                builder.append(nextChar.toLowerCase(locale));
+            }
+            // We need a capital letter next if this is a separator.
+            needsCapsNext = (Arrays.binarySearch(sortedSeparators, nextChar.codePointAt(0)) >= 0);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Approximates whether the text before the cursor looks like a URL.
+     *
+     * This is not foolproof, but it should work well in the practice.
+     * Essentially it walks backward from the cursor until it finds something that's not a letter,
+     * digit, or common URL symbol like underscore. If it hasn't found a period yet, then it
+     * does not look like a URL.
+     * If the text:
+     * - starts with www and contains a period
+     * - starts with a slash preceded by either a slash, whitespace, or start-of-string
+     * Then it looks like a URL and we return true. Otherwise, we return false.
+     *
+     * Note: this method is called quite often, and should be fast.
+     *
+     * TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the
+     * code complexity, but ideally it should not. It's acceptable for now.
+     */
+    public static boolean lastPartLooksLikeURL(@Nonnull final CharSequence text) {
+        int i = text.length();
+        if (0 == i) {
+            return false;
+        }
+        int wCount = 0;
+        int slashCount = 0;
+        boolean hasSlash = false;
+        boolean hasPeriod = false;
+        int codePoint = 0;
+        while (i > 0) {
+            codePoint = Character.codePointBefore(text, i);
+            if (codePoint < Constants.CODE_PERIOD || codePoint > 'z') {
+                // Handwavy heuristic to see if that's a URL character. Anything between period
+                // and z. This includes all lower- and upper-case ascii letters, period,
+                // underscore, arrobase, question mark, equal sign. It excludes spaces, exclamation
+                // marks, double quotes...
+                // Anything that's not a URL-like character causes us to break from here and
+                // evaluate normally.
+                break;
+            }
+            if (Constants.CODE_PERIOD == codePoint) {
+                hasPeriod = true;
+            }
+            if (Constants.CODE_SLASH == codePoint) {
+                hasSlash = true;
+                if (2 == ++slashCount) {
+                    return true;
+                }
+            } else {
+                slashCount = 0;
+            }
+            if ('w' == codePoint) {
+                ++wCount;
+            } else {
+                wCount = 0;
+            }
+            i = Character.offsetByCodePoints(text, i, -1);
+        }
+        // End of the text run.
+        // If it starts with www and includes a period, then it looks like a URL.
+        if (wCount >= 3 && hasPeriod) {
+            return true;
+        }
+        // If it starts with a slash, and the code point before is whitespace, it looks like an URL.
+        if (1 == slashCount && (0 == i || Character.isWhitespace(codePoint))) {
+            return true;
+        }
+        // If it has both a period and a slash, it looks like an URL.
+        if (hasPeriod && hasSlash) {
+            return true;
+        }
+        // Otherwise, it doesn't look like an URL.
+        return false;
+    }
+
+    /**
+     * Examines the string and returns whether we're inside a double quote.
+     *
+     * This is used to decide whether we should put an automatic space before or after a double
+     * quote character. If we're inside a quotation, then we want to close it, so we want a space
+     * after and not before. Otherwise, we want to open the quotation, so we want a space before
+     * and not after. Exception: after a digit, we never want a space because the "inch" or
+     * "minutes" use cases is dominant after digits.
+     * In the practice, we determine whether we are in a quotation or not by finding the previous
+     * double quote character, and looking at whether it's followed by whitespace. If so, that
+     * was a closing quotation mark, so we're not inside a double quote. If it's not followed
+     * by whitespace, then it was an opening quotation mark, and we're inside a quotation.
+     *
+     * @param text the text to examine.
+     * @return whether we're inside a double quote.
+     */
+    public static boolean isInsideDoubleQuoteOrAfterDigit(@Nonnull final CharSequence text) {
+        int i = text.length();
+        if (0 == i) {
+            return false;
+        }
+        int codePoint = Character.codePointBefore(text, i);
+        if (Character.isDigit(codePoint)) {
+            return true;
+        }
+        int prevCodePoint = 0;
+        while (i > 0) {
+            codePoint = Character.codePointBefore(text, i);
+            if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
+                // If we see a double quote followed by whitespace, then that
+                // was a closing quote.
+                if (Character.isWhitespace(prevCodePoint)) {
+                    return false;
+                }
+            }
+            if (Character.isWhitespace(codePoint) && Constants.CODE_DOUBLE_QUOTE == prevCodePoint) {
+                // If we see a double quote preceded by whitespace, then that
+                // was an opening quote. No need to continue seeking.
+                return true;
+            }
+            i -= Character.charCount(codePoint);
+            prevCodePoint = codePoint;
+        }
+        // We reached the start of text. If the first char is a double quote, then we're inside
+        // a double quote. Otherwise we're not.
+        return Constants.CODE_DOUBLE_QUOTE == codePoint;
+    }
+
+    public static boolean isEmptyStringOrWhiteSpaces(@Nonnull final String s) {
+        final int N = codePointCount(s);
+        for (int i = 0; i < N; ++i) {
+            if (!Character.isWhitespace(s.codePointAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @UsedForTesting
+    @Nonnull
+    public static String byteArrayToHexString(@Nullable final byte[] bytes) {
+        if (bytes == null || bytes.length == 0) {
+            return EMPTY_STRING;
+        }
+        final StringBuilder sb = new StringBuilder();
+        for (final byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Convert hex string to byte array. The string length must be an even number.
+     */
+    @UsedForTesting
+    @Nullable
+    public static byte[] hexStringToByteArray(@Nullable final String hexString) {
+        if (isEmpty(hexString)) {
+            return null;
+        }
+        final int N = hexString.length();
+        if (N % 2 != 0) {
+            throw new NumberFormatException("Input hex string length must be an even number."
+                    + " Length = " + N);
+        }
+        final byte[] bytes = new byte[N / 2];
+        for (int i = 0; i < N; i += 2) {
+            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+                    + Character.digit(hexString.charAt(i + 1), 16));
+        }
+        return bytes;
+    }
+
+    private static final String LANGUAGE_GREEK = "el";
+
+    @Nonnull
+    private static Locale getLocaleUsedForToTitleCase(@Nonnull final Locale locale) {
+        // In Greek locale {@link String#toUpperCase(Locale)} eliminates accents from its result.
+        // In order to get accented upper case letter, {@link Locale#ROOT} should be used.
+        if (LANGUAGE_GREEK.equals(locale.getLanguage())) {
+            return Locale.ROOT;
+        }
+        return locale;
+    }
+
+    @Nullable
+    public static String toTitleCaseOfKeyLabel(@Nullable final String label,
+            @Nonnull final Locale locale) {
+        if (label == null) {
+            return label;
+        }
+        return label.toUpperCase(getLocaleUsedForToTitleCase(locale));
+    }
+
+    public static int toTitleCaseOfKeyCode(final int code, @Nonnull final Locale locale) {
+        if (!Constants.isLetterCode(code)) {
+            return code;
+        }
+        final String label = newSingleCodePointString(code);
+        final String titleCaseLabel = toTitleCaseOfKeyLabel(label, locale);
+        return codePointCount(titleCaseLabel) == 1
+                ? titleCaseLabel.codePointAt(0) : Constants.CODE_UNSPECIFIED;
+    }
+
+    public static int getTrailingSingleQuotesCount(@Nonnull final CharSequence charSequence) {
+        final int lastIndex = charSequence.length() - 1;
+        int i = lastIndex;
+        while (i >= 0 && charSequence.charAt(i) == Constants.CODE_SINGLE_QUOTE) {
+            --i;
+        }
+        return lastIndex - i;
+    }
+
+    @UsedForTesting
+    public static class Stringizer<E> {
+        @Nonnull
+        private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+        @UsedForTesting
+        @Nonnull
+        public String stringize(@Nullable final E element) {
+            if (element == null) {
+                return "null";
+            }
+            return element.toString();
+        }
+
+        @UsedForTesting
+        @Nonnull
+        public final String join(@Nullable final E[] array) {
+            return joinStringArray(toStringArray(array), null /* delimiter */);
+        }
+
+        @UsedForTesting
+        public final String join(@Nullable final E[] array, @Nullable final String delimiter) {
+            return joinStringArray(toStringArray(array), delimiter);
+        }
+
+        @Nonnull
+        protected String[] toStringArray(@Nullable final E[] array) {
+            if (array == null) {
+                return EMPTY_STRING_ARRAY;
+            }
+            final String[] stringArray = new String[array.length];
+            for (int index = 0; index < array.length; index++) {
+                stringArray[index] = stringize(array[index]);
+            }
+            return stringArray;
+        }
+
+        @Nonnull
+        protected String joinStringArray(@Nonnull final String[] stringArray,
+                @Nullable final String delimiter) {
+            if (delimiter == null) {
+                return Arrays.toString(stringArray);
+            }
+            final StringBuilder sb = new StringBuilder();
+            for (int index = 0; index < stringArray.length; index++) {
+                sb.append(index == 0 ? "[" : delimiter);
+                sb.append(stringArray[index]);
+            }
+            return sb + "]";
+        }
+    }
+
+    /**
+     * Returns whether the last composed word contains line-breaking character (e.g. CR or LF).
+     * @param text the text to be examined.
+     * @return {@code true} if the last composed word contains line-breaking separator.
+     */
+    public static boolean hasLineBreakCharacter(@Nullable final String text) {
+        if (isEmpty(text)) {
+            return false;
+        }
+        for (int i = text.length() - 1; i >= 0; --i) {
+            final char c = text.charAt(i);
+            switch (c) {
+                case CHAR_LINE_FEED:
+                case CHAR_VERTICAL_TAB:
+                case CHAR_FORM_FEED:
+                case CHAR_CARRIAGE_RETURN:
+                case CHAR_NEXT_LINE:
+                case CHAR_LINE_SEPARATOR:
+                case CHAR_PARAGRAPH_SEPARATOR:
+                    return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java b/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java
new file mode 100644
index 0000000..1097463
--- /dev/null
+++ b/common/src/com/android/inputmethod/latin/common/UnicodeSurrogate.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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.common;
+
+/**
+ * Emojis are supplementary characters expressed as a low+high pair. For instance,
+ * the emoji U+1F625 is encoded as "\uD83D\uDE25" in UTF-16, where '\uD83D' is in
+ * the range of [0xd800, 0xdbff] and '\uDE25' is in the range of [0xdc00, 0xdfff].
+ * {@see http://docs.oracle.com/javase/6/docs/api/java/lang/Character.html#unicode}
+ */
+public final class UnicodeSurrogate {
+    private static final char LOW_SURROGATE_MIN = '\uD800';
+    private static final char LOW_SURROGATE_MAX = '\uDBFF';
+    private static final char HIGH_SURROGATE_MIN = '\uDC00';
+    private static final char HIGH_SURROGATE_MAX = '\uDFFF';
+
+    public static boolean isLowSurrogate(final char c) {
+        return c >= LOW_SURROGATE_MIN && c <= LOW_SURROGATE_MAX;
+    }
+
+    public static boolean isHighSurrogate(final char c) {
+        return c >= HIGH_SURROGATE_MIN && c <= HIGH_SURROGATE_MAX;
+    }
+}
diff --git a/dictionaries/de_wordlist.combined.gz b/dictionaries/de_wordlist.combined.gz
index 400718d..92c9554 100644
--- a/dictionaries/de_wordlist.combined.gz
+++ b/dictionaries/de_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/en_GB_wordlist.combined.gz b/dictionaries/en_GB_wordlist.combined.gz
index bf637e9..217660f 100644
--- a/dictionaries/en_GB_wordlist.combined.gz
+++ b/dictionaries/en_GB_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/en_US_wordlist.combined.gz b/dictionaries/en_US_wordlist.combined.gz
index 9ea04b1..8aed9c5 100644
--- a/dictionaries/en_US_wordlist.combined.gz
+++ b/dictionaries/en_US_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/en_wordlist.combined.gz b/dictionaries/en_wordlist.combined.gz
index 87a8633..7fe6618 100644
--- a/dictionaries/en_wordlist.combined.gz
+++ b/dictionaries/en_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/es_wordlist.combined.gz b/dictionaries/es_wordlist.combined.gz
index 8bb2102..71e7309 100644
--- a/dictionaries/es_wordlist.combined.gz
+++ b/dictionaries/es_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/fr_wordlist.combined.gz b/dictionaries/fr_wordlist.combined.gz
index 1b9fd73..afe44a6 100644
--- a/dictionaries/fr_wordlist.combined.gz
+++ b/dictionaries/fr_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/it_wordlist.combined.gz b/dictionaries/it_wordlist.combined.gz
index 5a5cbdc..ed58a12 100644
--- a/dictionaries/it_wordlist.combined.gz
+++ b/dictionaries/it_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/nl_wordlist.combined.gz b/dictionaries/nl_wordlist.combined.gz
index 37ba8ab..19c3a7e 100644
--- a/dictionaries/nl_wordlist.combined.gz
+++ b/dictionaries/nl_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/pl_wordlist.combined.gz b/dictionaries/pl_wordlist.combined.gz
index ba71a55..2b84eec 100644
--- a/dictionaries/pl_wordlist.combined.gz
+++ b/dictionaries/pl_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/pt_BR_wordlist.combined.gz b/dictionaries/pt_BR_wordlist.combined.gz
index 02df1c1..7aac61e 100644
--- a/dictionaries/pt_BR_wordlist.combined.gz
+++ b/dictionaries/pt_BR_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/pt_PT_wordlist.combined.gz b/dictionaries/pt_PT_wordlist.combined.gz
index bcd50ab..5bf9a60 100644
--- a/dictionaries/pt_PT_wordlist.combined.gz
+++ b/dictionaries/pt_PT_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/ro_wordlist.combined.gz b/dictionaries/ro_wordlist.combined.gz
index 829abd9..5307855 100644
--- a/dictionaries/ro_wordlist.combined.gz
+++ b/dictionaries/ro_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/ru_wordlist.combined.gz b/dictionaries/ru_wordlist.combined.gz
index 7794f7b..5e92662 100644
--- a/dictionaries/ru_wordlist.combined.gz
+++ b/dictionaries/ru_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/sv_wordlist.combined.gz b/dictionaries/sv_wordlist.combined.gz
index b6ebab3..db44ae4 100644
--- a/dictionaries/sv_wordlist.combined.gz
+++ b/dictionaries/sv_wordlist.combined.gz
Binary files differ
diff --git a/dictionaries/tr_wordlist.combined.gz b/dictionaries/tr_wordlist.combined.gz
index 306cea1..d3c8825 100644
--- a/dictionaries/tr_wordlist.combined.gz
+++ b/dictionaries/tr_wordlist.combined.gz
Binary files differ
diff --git a/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
index 21535e4..f5e56eb 100644
--- a/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
+++ b/java-overridable/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
@@ -18,6 +18,7 @@
 
 import android.content.pm.PackageInfo;
 
+@SuppressWarnings("unused")
 public class AppWorkaroundsHelper {
     private AppWorkaroundsHelper() {
         // This helper class is not publicly instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
index df0e3f0..13caea4 100644
--- a/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
+++ b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
@@ -62,4 +62,11 @@
      */
     public static final String UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
             + ".UPDATE_NOW";
+
+    /**
+     * The intent action to inform the dictionary provider to initialize the db
+     * and update now.
+     */
+    public static final String INIT_AND_UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
+            + ".INIT_AND_UPDATE_NOW";
 }
diff --git a/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
index ed81765..d8951df 100644
--- a/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
+++ b/java-overridable/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
@@ -21,6 +21,7 @@
 /**
  * Helper to get the metadata URI from its base URI and the additional ID, if any.
  */
+@SuppressWarnings("unused")
 public class MetadataUriGetter {
     private MetadataUriGetter() {
         // This helper class is not instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java b/java-overridable/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java
new file mode 100644
index 0000000..a48b41f
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/DictionaryFacilitatorProvider.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * Factory for instantiating DictionaryFacilitator objects.
+ */
+public class DictionaryFacilitatorProvider {
+    public static DictionaryFacilitator getDictionaryFacilitator(boolean isNeededForSpellChecking) {
+        return new DictionaryFacilitatorImpl();
+    }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/SpecialKeyDetector.java b/java-overridable/src/com/android/inputmethod/latin/SpecialKeyDetector.java
deleted file mode 100644
index 27b2f50..0000000
--- a/java-overridable/src/com/android/inputmethod/latin/SpecialKeyDetector.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014, 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;
-
-import android.content.Context;
-import android.view.KeyEvent;
-
-final class SpecialKeyDetector {
-    /**
-     * Special physical key detector
-     * @param context a context of this detector.
-     */
-    public SpecialKeyDetector(final Context context) {
-    }
-
-    /**
-     * Record a down key event.
-     * @param keyEvent a down key event.
-     */
-    public void onKeyDown(final KeyEvent keyEvent) {
-    }
-
-    /**
-     * Record an up key event.
-     * @param keyEvent an up key event.
-     */
-    public void onKeyUp(final KeyEvent keyEvent) {
-    }
-}
diff --git a/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java b/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java
new file mode 100644
index 0000000..60d420f
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/accounts/AccountStateChangedListener.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.support.annotation.NonNull;
+
+import javax.annotation.Nullable;
+
+/**
+ * Handles changes to account used to sign in to the keyboard.
+ * e.g. account switching/sign-in/sign-out from the keyboard
+ * user toggling the sync preference.
+ */
+public class AccountStateChangedListener {
+
+    /**
+     * Called when the current account being used in keyboard is signed out.
+     *
+     * @param oldAccount the account that was signed out of.
+     */
+    public static void onAccountSignedOut(@NonNull String oldAccount) {
+    }
+
+    /**
+     * Called when the user signs-in to the keyboard.
+     * This may be called when the user switches accounts to sign in with a different account.
+     *
+     * @param oldAccount the previous account that was being used for sign-in.
+     *        May be null for a fresh sign-in.
+     * @param newAccount the account being used for sign-in.
+     */
+    public static void onAccountSignedIn(@Nullable String oldAccount, @NonNull String newAccount) {
+    }
+
+    /**
+     * Called when the user toggles the sync preference.
+     *
+     * @param account the account being used for sync.
+     * @param syncEnabled indicates whether sync has been enabled or not.
+     */
+    public static void onSyncPreferenceChanged(@Nullable String account, boolean syncEnabled) {
+    }
+
+    /**
+     * Forces an immediate sync to happen.
+     * This should only be used for debugging purposes.
+     *
+     * @param account the account to use for sync.
+     */
+    public static void forceSync(@Nullable String account) {
+    }
+
+    /**
+     * Forces an immediate deletion of user's data.
+     * This should only be used for debugging purposes.
+     *
+     * @param account the account to use for sync.
+     */
+    public static void forceDelete(@Nullable String account) {
+    }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
new file mode 100644
index 0000000..dcc64a2
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/accounts/LoginAccountUtils.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.content.Context;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Utility class for retrieving accounts that may be used for login.
+ */
+public class LoginAccountUtils {
+    /**
+     * This defines the type of account this class deals with.
+     * This account type is used when listing the accounts available on the device for login.
+     */
+    public static final String ACCOUNT_TYPE = "";
+
+    private LoginAccountUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    /**
+     * Get the accounts available for login.
+     *
+     * @return an array of accounts. Empty (never null) if no accounts are available for login.
+     */
+    @Nonnull
+    @SuppressWarnings("unused")
+    public static String[] getAccountsForLogin(final Context context) {
+        return new String[0];
+    }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java b/java-overridable/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java
new file mode 100644
index 0000000..7f57ce8
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/define/DecoderSpecificConstants.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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.define;
+
+/**
+ * Decoder specific constants for LatinIme.
+ */
+public class DecoderSpecificConstants {
+
+    // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
+    public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
+
+    // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify
+    // MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions.
+    public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 3;
+
+    public static final String DECODER_DICT_SUFFIX = "";
+
+    public static final boolean SHOULD_VERIFY_MAGIC_NUMBER = true;
+    public static final boolean SHOULD_VERIFY_CHECKSUM = true;
+    public static final boolean SHOULD_USE_DICT_VERSION = true;
+    public static final boolean SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION = false;
+    public static final boolean SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION = true;
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
index 5ab1264..f31c208 100644
--- a/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
+++ b/java-overridable/src/com/android/inputmethod/latin/define/ProductionFlags.java
@@ -24,15 +24,8 @@
     public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
 
     /**
-     * When true, enable {@link InputMethodService#onUpdateCursorAnchorInfo} callback via
-     * {@link InputConnection#requestUpdateCursorAnchorInfo}. This flag has no effect in API
-     * Level 20 and prior. In general, this callback provides detailed positional information,
-     * even though an explicit support is required by the editor.
-     */
-    public static final boolean ENABLE_CURSOR_ANCHOR_INFO_CALLBACK = true;
-
-    /**
-     * Include all suggestions from all dictionaries in {@link SuggestedWords#mRawSuggestions}.
+     * Include all suggestions from all dictionaries in
+     * {@link com.android.inputmethod.latin.SuggestedWords#mRawSuggestions}.
      */
     public static final boolean INCLUDE_RAW_SUGGESTIONS = false;
 
@@ -40,4 +33,26 @@
      * When false, the metrics logging is not yet ready to be enabled.
      */
     public static final boolean IS_METRICS_LOGGING_SUPPORTED = false;
+
+    /**
+     * When {@code false}, the split keyboard is not yet ready to be enabled.
+     */
+    public static final boolean IS_SPLIT_KEYBOARD_SUPPORTED = true;
+
+    /**
+     * When {@code false}, account sign-in in keyboard is not yet ready to be enabled.
+     */
+    public static final boolean ENABLE_ACCOUNT_SIGN_IN = false;
+
+    /**
+     * When {@code true}, user history dictionary sync feature is ready to be enabled.
+     */
+    public static final boolean ENABLE_USER_HISTORY_DICTIONARY_SYNC =
+            ENABLE_ACCOUNT_SIGN_IN && false;
+
+    /**
+     * When {@code true}, the IME maintains per account {@link UserHistoryDictionary}.
+     */
+    public static final boolean ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY =
+            ENABLE_ACCOUNT_SIGN_IN && false;
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java
deleted file mode 100644
index 7dc120e..0000000
--- a/java-overridable/src/com/android/inputmethod/latin/personalization/ContextualDictionaryUpdater.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.content.Context;
-
-import com.android.inputmethod.latin.DictionaryFacilitator;
-
-public class ContextualDictionaryUpdater {
-    public ContextualDictionaryUpdater(final Context context,
-            final DictionaryFacilitator dictionaryFacilitator,
-            final Runnable onUpdateRunnable) {
-    }
-
-    public void onLoadSettings(final boolean usePersonalizedDicts) {
-    }
-
-    public void onStartInputView(final String  packageName) {
-    }
-
-    public void onDestroy() {
-    }
-}
diff --git a/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java b/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java
deleted file mode 100644
index c97a0d2..0000000
--- a/java-overridable/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdater.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.util.Locale;
-
-import android.content.Context;
-
-import com.android.inputmethod.latin.DictionaryFacilitator;
-
-public class PersonalizationDictionaryUpdater {
-    final Context mContext;
-    final DictionaryFacilitator mDictionaryFacilitator;
-    boolean mDictCleared = false;
-
-    public PersonalizationDictionaryUpdater(final Context context,
-            final DictionaryFacilitator dictionaryFacilitator) {
-        mContext = context;
-        mDictionaryFacilitator = dictionaryFacilitator;
-    }
-
-    public Locale getLocale() {
-        return null;
-    }
-
-    public void onLoadSettings(final boolean usePersonalizedDicts,
-            final boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes) {
-        if (!mDictCleared) {
-            // Clear and never update the personalization dictionary.
-            PersonalizationHelper.removeAllPersonalizationDictionaries(mContext);
-            mDictionaryFacilitator.clearPersonalizationDictionary();
-            mDictCleared = true;
-        }
-    }
-
-    public void onDestroy() {
-    }
-}
diff --git a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
index 6543003..4e8a10b 100644
--- a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
@@ -18,12 +18,18 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.preference.PreferenceFragment;
+import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethodcommon.InputMethodSettingsFragment;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.RichInputMethodManager;
+
+import javax.annotation.Nonnull;
 
 /**
  * Utility class for managing additional features settings.
  */
+@SuppressWarnings("unused")
 public class AdditionalFeaturesSettingUtils {
     public static final int ADDITIONAL_FEATURES_SETTINGS_SIZE = 0;
 
@@ -32,12 +38,20 @@
     }
 
     public static void addAdditionalFeaturesPreferences(
-            final Context context, final InputMethodSettingsFragment settingsFragment) {
+            final Context context, final PreferenceFragment settingsFragment) {
         // do nothing.
     }
 
-    public static void readAdditionalFeaturesPreferencesIntoArray(
+    public static void readAdditionalFeaturesPreferencesIntoArray(final Context context,
             final SharedPreferences prefs, final int[] additionalFeaturesPreferences) {
         // do nothing.
     }
+
+    @Nonnull
+    public static RichInputMethodSubtype createRichInputMethodSubtype(
+            @Nonnull final RichInputMethodManager imm,
+            @Nonnull final InputMethodSubtype subtype,
+            final Context context) {
+        return new RichInputMethodSubtype(subtype);
+    }
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java b/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java
new file mode 100644
index 0000000..8291b4f
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/touchinputconsumer/GestureConsumer.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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.touchinputconsumer;
+
+import android.view.inputmethod.EditorInfo;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.DictionaryFacilitator;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer;
+
+import java.util.Locale;
+
+/**
+ * Stub for GestureConsumer.
+ * <br>
+ * The methods of this class should only be called from a single thread, e.g.,
+ * the UI Thread.
+ */
+@SuppressWarnings("unused")
+public class GestureConsumer {
+    public static final GestureConsumer NULL_GESTURE_CONSUMER =
+            new GestureConsumer();
+
+    public static GestureConsumer newInstance(
+            final EditorInfo editorInfo, final PrivateCommandPerformer commandPerformer,
+            final Locale locale, final Keyboard keyboard) {
+        return GestureConsumer.NULL_GESTURE_CONSUMER;
+    }
+
+    private GestureConsumer() {
+    }
+
+    public boolean willConsume() {
+        return false;
+    }
+
+    public void onInit(final Locale locale, final Keyboard keyboard) {
+    }
+
+    public void onGestureStarted(final Locale locale, final Keyboard keyboard) {
+    }
+
+    public void onGestureCanceled() {
+    }
+
+    public void onGestureCompleted(final InputPointers inputPointers) {
+    }
+
+    public void onImeSuggestionsProcessed(final SuggestedWords suggestedWords,
+            final int composingStart, final int composingLength,
+            final DictionaryFacilitator dictionaryFacilitator) {
+    }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java
new file mode 100644
index 0000000..5eb613c
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/DictionaryHeaderUtils.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 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.utils;
+
+import com.android.inputmethod.latin.AssetFileAddress;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
+
+import java.io.File;
+
+public class DictionaryHeaderUtils {
+
+    public static int getContentVersion(AssetFileAddress fileAddress) {
+        final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(
+                new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength);
+        return Integer.parseInt(header.mVersionString);
+    }
+}
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
index 0aed41e..67de8ba 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/FeedbackUtils.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 
+@SuppressWarnings("unused")
 public class FeedbackUtils {
     public static boolean isHelpAndFeedbackFormSupported() {
         return false;
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
new file mode 100644
index 0000000..ef1872b
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.content.Context;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+public class ManagedProfileUtils {
+    private static ManagedProfileUtils INSTANCE = new ManagedProfileUtils();
+    private static ManagedProfileUtils sTestInstance;
+
+    private ManagedProfileUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    @UsedForTesting
+    public static void setTestInstance(final ManagedProfileUtils testInstance) {
+        sTestInstance = testInstance;
+    }
+
+    public static ManagedProfileUtils getInstance() {
+        return sTestInstance == null ? INSTANCE : sTestInstance;
+    }
+
+    public boolean hasWorkProfile(final Context context) {
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
index 9ad319d..97fb17d 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/MetadataFileUriGetter.java
@@ -23,6 +23,7 @@
 /**
  * Helper class to get the metadata URI and the additional ID.
  */
+@SuppressWarnings("unused")
 public class MetadataFileUriGetter {
     private MetadataFileUriGetter() {
         // This helper class is not instantiable.
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
index 79c19d0..c069a0f 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
@@ -16,19 +16,89 @@
 
 package com.android.inputmethod.latin.utils;
 
-import android.content.Context;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.DictionaryFacilitator;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.settings.SettingsValues;
 
+import javax.annotation.Nullable;
+
+@SuppressWarnings("unused")
 public final class StatsUtils {
-    public static void init(final Context context) {
+
+    private StatsUtils() {
+        // Intentional empty constructor.
     }
 
-    public static void onCreate(final SettingsValues settingsValues) {
+    public static void onCreate(final SettingsValues settingsValues,
+            RichInputMethodManager richImm) {
     }
 
-    public static void onLoadSettings(final SettingsValues settingsValues) {
+    public static void onPickSuggestionManually(final SuggestedWords suggestedWords,
+            final SuggestedWords.SuggestedWordInfo suggestionInfo,
+            final DictionaryFacilitator dictionaryFacilitator) {
     }
 
-    public static void onDestroy() {
+    public static void onBackspaceWordDelete(int wordLength) {
+    }
+
+    public static void onBackspacePressed(int lengthToDelete) {
+    }
+
+    public static void onBackspaceSelectedText(int selectedTextLength) {
+    }
+
+    public static void onDeleteMultiCharInput(int multiCharLength) {
+    }
+
+    public static void onRevertAutoCorrect() {
+    }
+
+    public static void onRevertDoubleSpacePeriod() {
+    }
+
+    public static void onRevertSwapPunctuation() {
+    }
+
+    public static void onFinishInputView() {
+    }
+
+    public static void onCreateInputView() {
+    }
+
+    public static void onStartInputView(int inputType, int displayOrientation, boolean restarting) {
+    }
+
+    public static void onAutoCorrection(final String typedWord, final String autoCorrectionWord,
+            final boolean isBatchInput, final DictionaryFacilitator dictionaryFacilitator,
+            final String prevWordsContext) {
+    }
+
+    public static void onWordCommitUserTyped(final String commitWord, final boolean isBatchMode) {
+    }
+
+    public static void onWordCommitAutoCorrect(final String commitWord, final boolean isBatchMode) {
+    }
+
+    public static void onWordCommitSuggestionPickedManually(
+            final String commitWord, final boolean isBatchMode) {
+    }
+
+    public static void onDoubleSpacePeriod() {
+    }
+
+    public static void onLoadSettings(SettingsValues settingsValues) {
+    }
+
+    public static void onInvalidWordIdentification(final String invalidWord) {
+    }
+
+    public static void onSubtypeChanged(final InputMethodSubtype oldSubtype,
+            final InputMethodSubtype newSubtype) {
+    }
+
+    public static void onSettingsActivity(final String entryPoint) {
     }
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
new file mode 100644
index 0000000..cd42f50
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtilsManager.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.content.Context;
+
+import com.android.inputmethod.latin.DictionaryFacilitator;
+import com.android.inputmethod.latin.settings.SettingsValues;
+
+@SuppressWarnings("unused")
+public class StatsUtilsManager {
+
+    private static final StatsUtilsManager sInstance = new StatsUtilsManager();
+    private static StatsUtilsManager sTestInstance = null;
+
+    /**
+     * @return the singleton instance of {@link StatsUtilsManager}.
+     */
+    public static StatsUtilsManager getInstance() {
+        return sTestInstance != null ? sTestInstance : sInstance;
+    }
+
+    public static void setTestInstance(final StatsUtilsManager testInstance) {
+        sTestInstance = testInstance;
+    }
+
+    public void onCreate(final Context context, final DictionaryFacilitator dictionaryFacilitator) {
+    }
+
+    public void onLoadSettings(final Context context, final SettingsValues settingsValues) {
+    }
+
+    public void onStartInputView() {
+    }
+
+    public void onFinishInputView() {
+    }
+
+    public void onDestroy(final Context context) {
+    }
+}
diff --git a/java/Android.mk b/java/Android.mk
index 0d12c45..b84b347 100644
--- a/java/Android.mk
+++ b/java/Android.mk
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
@@ -25,7 +25,8 @@
 
 LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-common inputmethod-common android-support-v4 jsr305
+LOCAL_STATIC_JAVA_LIBRARIES := \
+        android-common inputmethod-common android-support-v4 jsr305 latinime-common
 
 # Do not compress dictionary files to mmap dict data runtime
 LOCAL_AAPT_FLAGS := -0 .dict
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 1797dc9..f58c401 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -18,17 +18,21 @@
         coreApp="true"
         package="com.android.inputmethod.latin">
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
+    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
 
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.READ_PROFILE" />
+    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_SYNC_STATS" />
     <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
 
     <application android:label="@string/english_ime_name"
@@ -36,6 +40,7 @@
             android:supportsRtl="true"
             android:allowBackup="true">
 
+        <!-- Services -->
         <service android:name="LatinIME"
                 android:label="@string/english_ime_name"
                 android:permission="android.permission.BIND_INPUT_METHOD">
@@ -55,6 +60,11 @@
                     android:resource="@xml/spellchecker" />
         </service>
 
+        <service android:name="com.android.inputmethod.dictionarypack.DictionaryService"
+                android:label="@string/dictionary_service_name">
+        </service>
+
+        <!-- Activities -->
         <activity android:name=".setup.SetupActivity"
                 android:theme="@style/platformActivityTheme"
                 android:label="@string/english_ime_name"
@@ -76,19 +86,9 @@
             </intent-filter>
         </activity>
 
-        <receiver android:name="SystemBroadcastReceiver">
-            <intent-filter>
-                <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
-                <action android:name="android.intent.action.BOOT_COMPLETED" />
-                <action android:name="android.intent.action.USER_INITIALIZE" />
-                <action android:name="android.intent.action.LOCALE_CHANGED" />
-            </intent-filter>
-        </receiver>
-
         <activity android:name=".settings.SettingsActivity"
                 android:theme="@style/platformSettingsTheme"
-                android:label="@string/english_ime_settings"
-                android:uiOptions="splitActionBarWhenNarrow">
+                android:label="@string/english_ime_settings">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
@@ -102,45 +102,6 @@
             </intent-filter>
         </activity>
 
-        <receiver android:name="SuggestionSpanPickedNotificationReceiver" android:enabled="true">
-            <intent-filter>
-                <action android:name="android.text.style.SUGGESTION_PICKED" />
-            </intent-filter>
-        </receiver>
-
-        <receiver android:name=".personalization.DictionaryDecayBroadcastReciever"
-            android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.inputmethod.latin.personalization.DICT_DECAY" />
-            </intent-filter>
-        </receiver>
-
-        <receiver android:name=".DictionaryPackInstallBroadcastReceiver" android:exported="false">
-            <intent-filter>
-                <action android:name="com.android.inputmethod.dictionarypack.aosp.UNKNOWN_CLIENT" />
-            </intent-filter>
-        </receiver>
-
-        <provider android:name="com.android.inputmethod.dictionarypack.DictionaryProvider"
-                android:grantUriPermissions="true"
-                android:exported="false"
-                android:authorities="@string/authority"
-                android:multiprocess="false"
-                android:label="@string/dictionary_provider_name">
-        </provider>
-
-        <service android:name="com.android.inputmethod.dictionarypack.DictionaryService"
-                android:label="@string/dictionary_service_name">
-        </service>
-
-        <receiver android:name="com.android.inputmethod.dictionarypack.EventHandler">
-            <intent-filter>
-                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
-                <action android:name="android.intent.action.DATE_CHANGED" />
-                <action android:name="com.android.inputmethod.dictionarypack.aosp.UPDATE_NOW" />
-            </intent-filter>
-        </receiver>
-
         <activity android:name="com.android.inputmethod.dictionarypack.DictionarySettingsActivity"
                 android:theme="@style/platformSettingsTheme"
                 android:label="@string/dictionary_settings_title"
@@ -157,5 +118,50 @@
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
         </activity>
+
+        <!-- Unexported activity used for tests. -->
+        <activity android:name=".settings.TestFragmentActivity"
+                android:exported="false" />
+
+        <!-- Broadcast receivers -->
+        <receiver android:name="SystemBroadcastReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+                <action android:name="android.intent.action.USER_INITIALIZE" />
+                <action android:name="android.intent.action.LOCALE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="DictionaryPackInstallBroadcastReceiver" android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.inputmethod.dictionarypack.aosp.UNKNOWN_CLIENT" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.inputmethod.dictionarypack.EventHandler">
+            <intent-filter>
+                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
+                <action android:name="android.intent.action.DATE_CHANGED" />
+                <action android:name="com.android.inputmethod.dictionarypack.aosp.UPDATE_NOW" />
+                <action android:name="com.android.inputmethod.dictionarypack.aosp.INIT_AND_UPDATE_NOW" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Broadcast receiver for AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION. -->
+        <receiver android:name=".accounts.AccountsChangedReceiver">
+            <intent-filter>
+                <action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Content providers -->
+        <provider android:name="com.android.inputmethod.dictionarypack.DictionaryProvider"
+                android:grantUriPermissions="true"
+                android:exported="false"
+                android:authorities="@string/authority"
+                android:multiprocess="false"
+                android:label="@string/dictionary_provider_name">
+        </provider>
     </application>
 </manifest>
diff --git a/java/proguard.flags b/java/proguard.flags
index 35b3ac3..c832a88 100644
--- a/java/proguard.flags
+++ b/java/proguard.flags
@@ -19,6 +19,10 @@
 # to preserve changing those methods' signature.
 -keep class com.android.inputmethod.latin.AssetFileAddress
 -keep class com.android.inputmethod.latin.Dictionary
--keep class com.android.inputmethod.latin.PrevWordsInfo
+-keep class com.android.inputmethod.latin.NgramContext
 -keep class com.android.inputmethod.latin.makedict.ProbabilityInfo
 -keep class com.android.inputmethod.latin.utils.LanguageModelParam
+
+# TODO: remove once used in code.
+-keep class com.android.inputmethod.keyboard.KeyboardLayout { *; }
+
diff --git a/java/res/drawable-hdpi/ic_add_circle_wht_24dp.png b/java/res/drawable-hdpi/ic_add_circle_white_24dp.png
similarity index 100%
rename from java/res/drawable-hdpi/ic_add_circle_wht_24dp.png
rename to java/res/drawable-hdpi/ic_add_circle_white_24dp.png
Binary files differ
diff --git a/java/res/drawable-mdpi/ic_add_circle_wht_24dp.png b/java/res/drawable-mdpi/ic_add_circle_white_24dp.png
similarity index 100%
rename from java/res/drawable-mdpi/ic_add_circle_wht_24dp.png
rename to java/res/drawable-mdpi/ic_add_circle_white_24dp.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/ic_add_circle_wht_24dp.png b/java/res/drawable-xhdpi/ic_add_circle_white_24dp.png
similarity index 100%
rename from java/res/drawable-xhdpi/ic_add_circle_wht_24dp.png
rename to java/res/drawable-xhdpi/ic_add_circle_white_24dp.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/ic_add_circle_wht_24dp.png b/java/res/drawable-xxhdpi/ic_add_circle_white_24dp.png
similarity index 100%
rename from java/res/drawable-xxhdpi/ic_add_circle_wht_24dp.png
rename to java/res/drawable-xxhdpi/ic_add_circle_white_24dp.png
Binary files differ
diff --git a/java/res/drawable/btn_keyboard_key_ics.xml b/java/res/drawable/btn_keyboard_key_ics.xml
index 0bb098d..bacd5d7 100644
--- a/java/res/drawable/btn_keyboard_key_ics.xml
+++ b/java/res/drawable/btn_keyboard_key_ics.xml
@@ -32,6 +32,8 @@
           android:drawable="@drawable/btn_keyboard_key_normal_off_holo_dark" />
 
     <!-- Empty background keys. -->
+    <item android:state_empty="true" android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_pressed_ics_light" />
     <item android:state_empty="true"
           android:drawable="@android:color/transparent" />
 
diff --git a/java/res/drawable/btn_keyboard_key_klp.xml b/java/res/drawable/btn_keyboard_key_klp.xml
index 2a202a1..e2f2085 100644
--- a/java/res/drawable/btn_keyboard_key_klp.xml
+++ b/java/res/drawable/btn_keyboard_key_klp.xml
@@ -32,6 +32,8 @@
           android:drawable="@drawable/btn_keyboard_key_normal_off_holo_dark" />
 
     <!-- Empty background keys. -->
+    <item android:state_empty="true" android:state_pressed="true"
+          android:drawable="@drawable/btn_keyboard_key_pressed_klp_light" />
     <item android:state_empty="true"
           android:drawable="@android:color/transparent" />
 
diff --git a/java/res/drawable/btn_keyboard_key_lxx_dark.xml b/java/res/drawable/btn_keyboard_key_lxx_dark.xml
index bb1789a..161592d 100644
--- a/java/res/drawable/btn_keyboard_key_lxx_dark.xml
+++ b/java/res/drawable/btn_keyboard_key_lxx_dark.xml
@@ -32,8 +32,10 @@
           android:drawable="@drawable/btn_keyboard_key_normal_off_lxx_dark" />
 
     <!-- Empty background keys. -->
+    <item android:state_empty="true" android:state_pressed="true"
+          android:drawable="@color/key_background_pressed_lxx_dark" />
     <item android:state_empty="true"
-          android:drawable="@color/key_background_lxx_dark" />
+          android:drawable="@android:color/transparent" />
 
     <!-- Normal keys. -->
     <item android:state_pressed="true"
diff --git a/java/res/drawable/btn_keyboard_key_lxx_light.xml b/java/res/drawable/btn_keyboard_key_lxx_light.xml
index 60fe02d..0154d75 100644
--- a/java/res/drawable/btn_keyboard_key_lxx_light.xml
+++ b/java/res/drawable/btn_keyboard_key_lxx_light.xml
@@ -32,8 +32,10 @@
           android:drawable="@drawable/btn_keyboard_key_normal_off_lxx_light" />
 
     <!-- Empty background keys. -->
+    <item android:state_empty="true" android:state_pressed="true"
+          android:drawable="@color/key_background_pressed_lxx_light" />
     <item android:state_empty="true"
-          android:drawable="@color/key_background_lxx_light" />
+          android:drawable="@android:color/transparent" />
 
     <!-- Normal keys. -->
     <item android:state_pressed="true"
diff --git a/java/res/layout/additional_subtype_dialog.xml b/java/res/layout/additional_subtype_dialog.xml
index b7804f5..2de7d07 100644
--- a/java/res/layout/additional_subtype_dialog.xml
+++ b/java/res/layout/additional_subtype_dialog.xml
@@ -38,7 +38,6 @@
             android:text="@string/subtype_locale" />
         <Spinner
             android:id="@+id/subtype_locale_spinner"
-            android:spinnerMode="dialog"
             android:layout_width="0dp"
             android:layout_weight="70"
             android:layout_height="wrap_content"
@@ -47,7 +46,8 @@
             android:layout_marginTop="8dip"
             android:layout_gravity="fill_horizontal|center_vertical"
             android:gravity="start|left"
-            android:prompt="@string/subtype_locale" />
+            android:prompt="@string/subtype_locale"
+            style="@style/additionalSubtypeSpinnerStyle" />
         </LinearLayout>
     <LinearLayout
         android:orientation="horizontal"
@@ -63,7 +63,6 @@
             android:text="@string/keyboard_layout_set" />
         <Spinner
             android:id="@+id/keyboard_layout_set_spinner"
-            android:spinnerMode="dialog"
             android:layout_width="0dp"
             android:layout_weight="70"
             android:layout_height="wrap_content"
@@ -72,6 +71,7 @@
             android:layout_marginTop="8dip"
             android:layout_gravity="fill_horizontal|center_vertical"
             android:gravity="start|left"
-            android:prompt="@string/keyboard_layout_set" />
+            android:prompt="@string/keyboard_layout_set"
+            style="@style/additionalSubtypeSpinnerStyle" />
     </LinearLayout>
 </LinearLayout>
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index 46551f6..ae3c19d 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -21,7 +21,8 @@
 <com.android.inputmethod.latin.InputView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    style="?attr/inputViewStyle">
     <include
         android:id="@+id/main_keyboard_frame"
         layout="@layout/main_keyboard_frame" />
diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml
index aefdb8ca..47e9a91 100644
--- a/java/res/layout/suggestions_strip.xml
+++ b/java/res/layout/suggestions_strip.xml
@@ -33,30 +33,6 @@
         android:soundEffectsEnabled="false" />
     <!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
          We just need to ignore the system's audio and haptic feedback settings. -->
-    <LinearLayout
-        android:id="@+id/add_to_dictionary_strip"
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginLeft="@dimen/config_suggestions_strip_horizontal_margin"
-        android:layout_marginRight="@dimen/config_suggestions_strip_horizontal_margin"
-        android:hapticFeedbackEnabled="false"
-        android:soundEffectsEnabled="false">
-        <TextView
-            android:id="@+id/word_to_save"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            style="?attr/suggestionWordStyle" />
-        <include
-            android:id="@+id/word_to_save_divider"
-            layout="@layout/suggestion_divider" />
-        <TextView
-            android:id="@+id/hint_add_to_dictionary"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center_vertical|start"
-            style="?attr/suggestionWordStyle" />
-    </LinearLayout>
     <!-- Provide audio and haptic feedback by ourselves based on the keyboard settings.
          We just need to ignore the system's audio and haptic feedback settings. -->
     <LinearLayout
diff --git a/java/res/layout/user_dictionary_add_word_fullscreen.xml b/java/res/layout/user_dictionary_add_word_fullscreen.xml
index 9bcb189..cbdfba6 100644
--- a/java/res/layout/user_dictionary_add_word_fullscreen.xml
+++ b/java/res/layout/user_dictionary_add_word_fullscreen.xml
@@ -44,26 +44,6 @@
         android:columnCount="2" >
 
         <TextView
-            android:id="@+id/user_dictionary_add_shortcut_label"
-            style="?android:attr/textAppearanceSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start|center_vertical"
-            android:text="@string/user_dict_settings_add_shortcut_option_name" />
-
-        <EditText
-            android:id="@+id/user_dictionary_add_shortcut"
-            android:layout_width="wrap_content"
-            android:layout_gravity="fill_horizontal|center_vertical"
-            android:layout_marginBottom="8dip"
-            android:layout_marginStart="8dip"
-            android:layout_marginTop="8dip"
-            android:hint="@string/user_dict_settings_add_shortcut_hint"
-            android:imeOptions="flagNoFullscreen"
-            android:inputType="textNoSuggestions"
-            android:maxLength="@integer/config_user_dictionary_max_word_length" />
-
-        <TextView
             android:id="@+id/user_dictionary_add_locale_label"
             style="?android:attr/textAppearanceSmall"
             android:layout_width="wrap_content"
diff --git a/java/res/menu/add_style.xml b/java/res/menu/add_style.xml
index d1cab4b..befa3f2 100644
--- a/java/res/menu/add_style.xml
+++ b/java/res/menu/add_style.xml
@@ -20,7 +20,7 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item
         android:id="@+id/action_add_style"
-        android:icon="@drawable/ic_add_circle_wht_24dp"
+        android:icon="@drawable/ic_add_circle_white_24dp"
         android:title="@string/add_style"
         android:showAsAction="always" />
-</menu>
\ No newline at end of file
+</menu>
diff --git a/java/res/raw/main_de.dict b/java/res/raw/main_de.dict
index 3cbf710..c3c2cbe 100644
--- a/java/res/raw/main_de.dict
+++ b/java/res/raw/main_de.dict
Binary files differ
diff --git a/java/res/raw/main_en.dict b/java/res/raw/main_en.dict
index d631d6f..b9e5bc7 100644
--- a/java/res/raw/main_en.dict
+++ b/java/res/raw/main_en.dict
Binary files differ
diff --git a/java/res/raw/main_es.dict b/java/res/raw/main_es.dict
index 8c42fda..076d5aa 100644
--- a/java/res/raw/main_es.dict
+++ b/java/res/raw/main_es.dict
Binary files differ
diff --git a/java/res/raw/main_fr.dict b/java/res/raw/main_fr.dict
index 19532d9..0e86860 100644
--- a/java/res/raw/main_fr.dict
+++ b/java/res/raw/main_fr.dict
Binary files differ
diff --git a/java/res/raw/main_it.dict b/java/res/raw/main_it.dict
index ff11b97..609ef13 100644
--- a/java/res/raw/main_it.dict
+++ b/java/res/raw/main_it.dict
Binary files differ
diff --git a/java/res/raw/main_pt_br.dict b/java/res/raw/main_pt_br.dict
index 9fa5044..c338651 100644
--- a/java/res/raw/main_pt_br.dict
+++ b/java/res/raw/main_pt_br.dict
Binary files differ
diff --git a/java/res/raw/main_ru.dict b/java/res/raw/main_ru.dict
index 9fdaf31..d0af707 100644
--- a/java/res/raw/main_ru.dict
+++ b/java/res/raw/main_ru.dict
Binary files differ
diff --git a/java/res/raw/setup_welcome_image.png b/java/res/raw/setup_welcome_image.png
index 98e7313..b726181 100644
--- a/java/res/raw/setup_welcome_image.png
+++ b/java/res/raw/setup_welcome_image.png
Binary files differ
diff --git a/java/res/raw/setup_welcome_video.mp4 b/java/res/raw/setup_welcome_video.mp4
index 224bf25..09be565 100644
--- a/java/res/raw/setup_welcome_video.mp4
+++ b/java/res/raw/setup_welcome_video.mp4
Binary files differ
diff --git a/java/res/values-af/strings-emoji-descriptions.xml b/java/res/values-af/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..5ed066a
--- /dev/null
+++ b/java/res/values-af/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Kopieregteken"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Geregistreerdteken"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dubbele uitroepteken"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Uitroep-vraagteken"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Handelsmerkteken"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Inligtingsbron"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Links-regs-pyl"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Op-af-pyl"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Noordwes-pyl"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Noordoos-pyl"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Suidoos-pyl"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Suidwes-pyl"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Pyl na links met haak"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Pyl na regs met haak"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Horlosie"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Uurglas"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Swart dubbeldriehoek wat regs wys"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Swart dubbeldriehoek wat links wys"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Swart dubbeldriehoek wat boontoe wys"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Swart dubbeldriehoek wat ondertoe wys"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Wekker"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Uurglas met vloeiende sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Omkringde latynse hoofletter-m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Klein swart vierkant"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Klein wit vierkant"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Swart driehoek wat regs wys"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Swart driehoek wat links wys"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Wit mediumvierkant"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Swart mediumvierkant"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Wit mediumklein vierkant"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Swart mediumklein vierkant"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Swart son met strale"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Wolk"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Swart telefoon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Stembus met regmerk"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Sambreel met reëndruppels"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Warm drankie"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Wit wysvinger wat boontoe wys"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Glimlaggende wit gesig"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Ram"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Bul"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Tweeling"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Kreef"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leeu"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Maagd"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Weegskaal"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skerpioen"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Boogskutter"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Steenbok"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Waterdraer"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Vis"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Swart skoppens"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Swart klawers"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Swart hartens"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Swart ruite"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Warmbad"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Swart universele herwinningsimbool"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Rolstoelsimbool"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anker"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Waarskuwingteken"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Hoëspanning-teken"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Wit mediumsirkel"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Swart mediumsirkel"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Sokkerbal"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bofbal"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Sneeuman sonder sneeu"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Son agter wolk"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Slangdraer"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Geen toegang nie"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kerk"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontein"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Vlag in gat"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Seilboot"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tent"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Brandstofpomp"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Swart skêr"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Dik wit regmerk"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Vliegtuig"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Koevert"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Vuis omhoog"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Hand omhoog"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Oorwinninghand"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Potlood"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Swart penpunt"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Dik regmerk"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Dik vermenigvuldiging-x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Vonke"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisk met agt speke"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Swart agtpuntster"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Sneeuvlokkie"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Vonk"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kruismerk"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negatiewe kruismerk in vierkant"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Swart vraagtekenornament"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Wit vraagtekenornament"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Wit uitroeptekenornament"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Dik uitroeptekensimbool"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Dik swart hart"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Dik plusteken"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Dik minusteken"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Dik deelteken"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Swart pyl na regs"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Krullus"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dubbelkrullus"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pyl wat na regs wys en dan opwaarts krul"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pyl wat na regs wys en dan afwaarts krul"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Swart pyl na links"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Swart pyl na bo"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Swart pyl na onder"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Groot swart vierkant"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Groot wit vierkant"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Wit mediumster"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Dik groot sirkel"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Golfstrepie"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Deelwisselingteken"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Omkringde ideogram gelukwensing"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Omkringde ideogram geheim"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong-teël rooi draak"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Speelkaart swart Piet"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Bloedgroep A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Bloedgroep B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Bloedgroep O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkeerterrein"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Bloedgroep AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL in vierkant"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Koel in vierkant"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Vry in vierkant"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID in vierkant"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Nuut in vierkant"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"N G in vierkant"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK in vierkant"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS in vierkant"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Op met uitroepteken in vierkant"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"vs in vierkant"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana hier in vierkant"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Katakana diens in vierkant"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogram kosteloos in vierkant"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogram gereserveerde sitplek in vierkant"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogram prohibisie in vierkant"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogram vakature in vierkant"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogram aanvaarding in vierkant"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogram volle okkupasie in vierkant"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogram betaal in vierkant"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogram maandeliks in vierkant"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogram aansoek in vierkant"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogram afslag in vierkant"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogram sakedoenend in vierkant"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Omkringde ideogram voordeel"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Omkringde ideogram aanvaar"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Sikloon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Mistig"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Toe sambreel"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Nag met sterre"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sonsopkoms oor berge"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sonsopkoms"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Stadsgesig teen skemer"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Sonsondergang oor geboue"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Reënboog"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Brug in die nag"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Watergolf"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkaan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Melkweg"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Aardbol europa-afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Aardbol amerikas"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Aardbol asië-australië"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Aardbol met meridiane"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbool vir nuwemaan"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbool vir wassende sekelmaan"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbool vir eerstekwartier-maan"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbool vir wassende bolmaan"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbool vir volmaan"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbool vir afnemende bolmaan"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbool vir laastekwartier-maan"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbool vir afnemende sekelmaan"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Sekelmaan"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nuwemaan met gesig"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Eerstekwartier-maan met gesig"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Laastekwartier-maan met gesig"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Volmaan met gesig"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Son met gesig"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Gloeiende ster"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Verskietende ster"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastaiing"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Saailing"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Immergroen boom"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Bladwisselende boom"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmboom"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulp"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kersiebloeisel"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Roos"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sonneblom"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Bloeisel"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Mieliekop"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Rysaar"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Krui"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Vierklawer"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Esdoringblaar"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Gevalde blaar"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blaar wat in die wind fladder"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Sampioen"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tamatie"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Eiervrug"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Druiwe"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Spanspek"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Waatlemoen"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Nartjie"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Suurlemoen"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Piesang"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Pynappel"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rooi appel"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Groen appel"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Peer"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Perske"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kersies"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Aarbei"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Stuk pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Vleis op been"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Pluimveeboudjie"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rysbeskuitjie"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rysbal"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Gekookte rys"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Kerrie en rys"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Stomende bak"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Brood"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Aartappelskyfies"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Geroosterde patat"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Soesji"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Gebraaide garnaal"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Viskoekie met draaikolkpatroon"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Sagte roomys"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Ysskaafsels"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Roomys"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Oliebol"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Koekie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Staaf sjokolade"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Lekkergoed"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vla"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Heuningpot"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Broskoek"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento-bak"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Pot kos"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Kokery"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Mes en vurk"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Teekoppie sonder handvatsel"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake-bottel en -koppie"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wynglas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Skemerkelkieglas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropiese drankie"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Bierbeker"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Klinkende bierbekers"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Bababottel"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Strikkie"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Toegedraaide geskenk"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Verjaardagkoek"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Chinese lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Kersboom"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Kersvader"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Vuurwerk"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Vonkstok"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Partytjieklapper"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettibal"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata-boom"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Gekruisde vlae"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Denneversiering"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japannese poppe"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Karpwindkous"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Windklokkie"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Maankykseremonie"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Skoolsak"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Gradeplegtigheidmus"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Mallemeuleperd"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ferriswiel"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Tuimeltrein"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Visstok en vis"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofoon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Rolprentkamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Bioskoop"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Oorfoon"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Skilderpalet"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Pluiskeil"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Sirkustent"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Kaartjie"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klapbord"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Uitvoerende kunste"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videospeletjie"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Kolskoot"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Muntoutomaat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljart"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dobbelsteen"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Kegelspel"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Blomspeelkaarte"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musieknoot"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Verskeie musieknote"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofoon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Kitaar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klawerbord"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Viool"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partituur"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Drafhemp met lyfband"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisraket en bal"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski en ski-stewel"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbal en ring"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Geruite vlag"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Sneeuplankryer"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Hardloper"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Branderplankryer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofee"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Perdewedrenne"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikaanse voetbal"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugbyvoetbal"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Swemmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Huisbou"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Huis met tuin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kantoorgebou"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japannese poskantoor"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europese poskantoor"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospitaal"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Kitsbank"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Liefdeshotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Geriefswinkel"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Skool"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Afdelingswinkel"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabriek"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaja-lantern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japannese kasteel"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europese kasteel"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rot"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Muis"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Os"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Waterbuffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Koei"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Luiperd"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Haas"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Draak"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Walvis"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Slak"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Slang"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Perd"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ram"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Bok"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Skaap"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Aap"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Haan"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Hoender"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hond"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Vark"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Varkbeer"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Olifant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Seekat"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiraalskulp"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Gogga"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mier"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Heuningby"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Skilpadbesie"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Vis"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropiese vis"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Blaasoppie"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Skilpad"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kuiken wat uitbroei"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Babakuiken"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Babakuiken wat vorentoe kyk"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Voël"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pikkewyn"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poedel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedaris"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Tweebultkameel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dolfyn"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Muisgesig"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Koeigesig"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tiergesig"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Haasgesig"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Katgesig"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Draakgesig"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Spuitende walvis"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Perdgesig"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Aapgesig"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hondgesig"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Varkgesig"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Paddagesig"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamstergesig"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wolfgesig"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Beergesig"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandagesig"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Varksnoet"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pootafdrukke"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oë"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Oor"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Neus"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mond"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tong"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Wit handrugkant met wysvinger wat boontoe wys"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Wit handrugkant met wysvinger wat ondertoe wys"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Wit handrugkant met wysvinger wat na links wys"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Wit handrugkant met wysvinger wat na regs wys"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Vuishandteken"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Teken van wuifende hand"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK-handteken"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Teken van duime op"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Teken van duime af"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Teken van klappende hande"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Teken van oop hande"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Kroon"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Vrouehoed"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Bril"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Das"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-hemp"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Rok"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Vroueklere"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Beursie"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handsak"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Sakkie"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Manskoen"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Hardloopskoen"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Hoëhakskoen"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Vrouesandaal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Vrouestewel"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Voetspore"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhoeët van borsbeeld"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhoeët van borsbeelde"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Seun"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Meisie"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Man"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Vrou"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Gesin"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Man en vrou wat hande vashou"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Twee mans wat hande vashou"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Twee vroue wat hande vashou"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polisiebeampte"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Vrou met haasore"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Bruid met sluier"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persoon met blonde hare"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Man met gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Man met tulband"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Ouer man"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Ouer vrou"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baba"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Konstruksiewerker"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinses"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japannese mensvreter"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japannese gnoom"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spook"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Baba-engel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Buiteruimtelike wese"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Ruimtemonster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Duiwel"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Skedel"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Inligtingtoonbankpersoon"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardesoldaat"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danser"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lipstiffie"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Naelpolitoer"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Gesigmassering"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Haarsny"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barbierpaal"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Inspuiting"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pil"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Soenmerk"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Liefdesbrief"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Edelsteen"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Soen"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bos blomme"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Paartjie met hart"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Troue"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Kloppende hart"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Gebroke hart"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Twee harte"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Sprankelende hart"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Groeiende hart"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hart met pyl"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blou hart"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Groen hart"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Geel hart"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Pers hart"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hart met strik"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Draaiende harte"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Hartversiering"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamantvorm met kol in"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektriese gloeilamp"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Woedesimbool"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bom"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Slaapsimbool"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Botsingsimbool"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Simbool vir sweet wat spat"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Druppeltjie"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Hardloopsimbool"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Hoop poef"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Gebulte boarmspier"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Duiseligsimbool"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Praatborrel"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Dinkborrel"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Wit blom"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbool van honderd punte"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Geldsak"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valutaomskakeling"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dik dollarteken"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredietkaart"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknoot met jenteken"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknoot met dollarteken"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknoot met euroteken"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknoot met pondteken"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Geld met vlerke"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Grafiek met stygtendens en jenteken"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sitplek"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Persoonlike rekenaar"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktetas"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Miniskyf"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disket"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optiese skyf"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Lêergids"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Oop lêergids"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Bladsy met krul"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Bladsy met die regte kant na bo"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Afskeurkalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kaartindeks"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Grafiek met stygtendens"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Grafiek met daaltendens"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Staafgrafiek"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Knyperbord"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Duimspyker"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Ronde duimspyker"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Skuifspeld"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Reguit liniaal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Driekantliniaal"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Boekmerkoortjies"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Lêer"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notaboek"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notaboek met dekoratiewe omslag"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Geslote boek"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Oop boek"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Groen boek"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blou boek"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranje boek"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Boeke"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Naambalkie"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Boekrol"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefoonhoorstuk"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Roepradio"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faksmasjien"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellietantenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Afkondigingluidspreker"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Juigende megafoon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Uitkassielaai"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Inkassielaai"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakkie"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-possimbool"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Inkomende koevert"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Koevert met pyl na onder bo-op"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Geslote posbus met vlag wat laat sak is"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Geslote posbus met geligte vlag"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Oop posbus met geligte vlag"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Oop posbus met vlag wat laat sak is"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Posbus"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Poshoring"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Koerant"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Selfoon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Selfoon met pyl na regs aan die linkerkant"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrasiemodus"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Selfoon af"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Geen selfone nie"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna met stawe"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisie"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokasset"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Gevlegte pyle na regs"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Kloksgewyse oopsirkel-pyle na regs en na links"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Kloksgewyse oopsirkel-pyle na regs en na links met omkringde een bo-oor"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Kloksgewyse oopsirkel-pyle na onder en na bo"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Teenkloksgewyse oopsirkel-pyle na onder en na bo"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbool vir min helderheid"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbool vir baie helderheid"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Luidspreker met kanselleerstrook"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Luidspreker"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Luidspreker met een klankgolf"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Luidspreker met drie klankgolwe"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Battery"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektriese prop"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Vergrootglas wat na links wys"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Vergrootglas wat na regs wys"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Slot met vulpen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Geslote slot met sleutel"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Sleutel"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Slot"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Oop slot"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Klok"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Klok met kanselleerstrook"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Boekmerk"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Skakelsimbool"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Klinkknoppie"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Terug met pyl na links bo-op"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Einde met pyl na links bo-op"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Aan met uitroepteken met links-regs-pyl bo-op"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Binnekort met pyl na regs bo-op"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Bokant met pyl na bo bo-op"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbool vir niemand onder agtien"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Sleuteldoppie tien"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Invoersimbool vir latynse hoofletters"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Invoersimbool vir latynse kleinletters"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Invoersimbool vir syfers"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Invoersimbool vir simbole"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Invoersimbool vir latynse letters"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Brand"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elektriese flitslig"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Moersleutel"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hamer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Bout en moer"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hotsjo"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistool"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskoop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskoop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristalbal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sespuntster met middelkol"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japannese simbool vir beginner"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Drietandvurkembleem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Swartvierkant-knoppie"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Witvierkant-knoppie"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Groot rooi sirkel"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Groot blou sirkel"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Groot oranje diamant"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Groot blou diamant"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Klein oranje diamant"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Klein blou diamant"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Rooi driehoek wat na bo wys"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Rooi driehoek wat na onder wys"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Klein rooi driehoek wat na bo wys"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Klein rooi driehoek wat na onder wys"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Wyserplaat eenuur"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Wyserplaat twee-uur"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Wyserplaat drie-uur"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Wyserplaat vieruur"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Wyserplaat vyfuur"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Wyserplaat sesuur"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Wyserplaat sewe-uur"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Wyserplaat agtuur"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Wyserplaat nege-uur"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Wyserplaat tienuur"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Wyserplaat elfuur"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Wyserplaat twaalfuur"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Wyserplaat halftwee"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Wyserplaat halfdrie"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Wyserplaat halfvier"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Wyserplaat halfvyf"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Wyserplaat halfses"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Wyserplaat halfsewe"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Wyserplaat halfagt"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Wyserplaat halfnege"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Wyserplaat halftien"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Wyserplaat halfelf"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Wyserplaat halftwaalf"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Wyserplaat halfeen"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Foedjiberg"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokio-toring"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Vryheidstandbeeld"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhoeët van japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Grinnikende gesig"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Grinnikende gesig met glimlaggende oë"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Gesig met trane van vreugde"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Glimlaggende gesig met oop mond"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Glimlaggende gesig met oop mond en glimlaggende oë"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Glimlaggende gesig met oop mond en koue sweet"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Glimlaggende gesig met oop mond en oë styf toe"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Glimlaggende gesig met stralekrans"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Glimlaggende gesig met horings"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Knipooggesig"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Glimlaggende gesig met glimlaggende oë"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Gesig wat heerlike kos geniet"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Verligte gesig"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Glimlaggende gesig met hartvormige oë"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Glimlaggende gesig met sonbril"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Grynslaggesig"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutrale gesig"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Uitdrukkinglose gesig"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Ontevrede gesig"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Gesig met koue sweet"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Peinsende gesig"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Verwarde gesig"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Oorblufte gesig"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Soenende gesig"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Gesig wat \'n soentjie stuur"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Soenende gesig met glimlaggende oë"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Soenende gesig met geslote oë"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Gesig met uitsteektong"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Gesig met uitsteektong en knipoog"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Gesig met uitsteektong en oë styf toe"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Teleurgestelde gesig"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Bekommerde gesig"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Woedende gesig"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Pruilende gesig"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Huilende gesig"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Volhardende gesig"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Gesig met triomfantelike voorkoms"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Teleurgestelde maar verligte gesig"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Fronsende gesig met oop mond"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Beangste gesig"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Vreesbevange gesig"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Vermoeide gesig"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Vaak gesig"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Moeë gesig"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Skewebekgesig"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Gesig wat hard huil"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Gesig met oop mond"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Stil gesig"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Gesig met oop mond en koue sweet"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Gesig wat vreesbevange skree"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Verstomde gesig"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Blosende gesig"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Slapende gesig"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Dronk gesig"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Gesig met oop mond"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Gesig met mediese masker"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Grinnikende katgesig met glimlaggende oë"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Katgesig met trane van vreugde"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Glimlaggende katgesig met oop mond"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Glimlaggende katgesig met hartvormige oë"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Katgesig met wrange glimlag"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Soenende katgesig met geslote oë"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Pruilende katgesig"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Huilende katgesig"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Vermoeide katgesig"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Gesig met nikswerdgebaar"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Gesig met OK-gebaar"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persoon wat diep buig"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Niks-verkeerd-sien-aap"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Niks-verkeerd-hoor-aap"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Niks-verkeerd-sê-aap"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Gelukkige persoon wat een hand lig"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persoon wat albei hande ter viering omhoog hou"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persoon wat frons"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persoon met pruilende gesig"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persoon met gevoude hande"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Vuurpyl"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Stoomlokomotief"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Treintrok"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Hoëspoedtrein"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Hoëspoedtrein met koeëlneus"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Trein"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Moltrein"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Smalspoor"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stasie"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Trem"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tremwa"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Aankomende bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Spoorlose trem"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bushalte"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulans"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Brandweerwa"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Polisiemotor"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Aankomende polisiemotor"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Aankomende taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Motor"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Aankomende motor"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Ontspanningsvoertuig"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Afleweringswa"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Gelede vragmotor"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Trekker"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Eenspoor"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Bergtreinspoor"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Hangspoor"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Bergkabelspoor"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Kabelkar"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Skip"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Roeiboot"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Snelboot"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horisontale verkeerslig"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikale verkeerslig"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Konstruksieteken"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Polisiemotor se draailig"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Driehoekige vlag op paal"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Deur"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Geen-toegang-teken"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Rooksimbool"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Simbool vir moenie rook nie"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Simbool vir sit rommel op sy plek"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbool vir moenie mors nie"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbool vir drinkbare water"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbool vir ondrinkbare water"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Fiets"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Geen fietse nie"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Fietsryer"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Bergfietsryer"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Voetganger"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Geen voetgangers nie"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Kinders stap oor"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Mansimbool"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Vrousimbool"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Openbare toilet"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Babasimbool"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Waterkloset"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Stort"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bad"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badkuip"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Paspoortbeheer"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Doeane"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagasieband"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Bagasiedepot"</string>
+</resources>
diff --git a/java/res/values-af/strings-talkback-descriptions.xml b/java/res/values-af/strings-talkback-descriptions.xml
index 3b6ba0a..c938996 100644
--- a/java/res/values-af/strings-talkback-descriptions.xml
+++ b/java/res/values-af/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Geen teks is ingevoer nie"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> korrigeer <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> voer outokorrigering uit"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Geen voorstel nie"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Onbekende karakter"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Meer simbole"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Hoofletter-I, kol bo"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Onbekende simbool"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Onbekende emosiekoon"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Verveelde gesig"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Verleë gesig"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gesig met sonbrille"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Verbaasde gesig"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Soenende gesig"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Fronsende gesig"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatiewe karakters is beskikbaar"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatiewe karakters is toegemaak"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatiewe voorstelle is beskikbaar"</string>
diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml
index b7a27eb..bc45714 100644
--- a/java/res/values-af/strings.xml
+++ b/java/res/values-af/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreer met sleuteldruk"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Klank met sleuteldruk"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Opspring met sleuteldruk"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Voorkeure"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Rekeninge en privaatheid"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Voorkoms en uitlegte"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Gebaarinvoer"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Tekskorrigering"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Gevorderd"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktiveer verdeelde sleutelbord"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-sleutelbordsinkronisering"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinkronisering is aangeskakel"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sinkroniseer jou persoonlike woordeboek oor toestelle heen"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinkroniseer nou"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Vee wolkdata uit"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Vee jou gesinkroniseerde data van Google af uit"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Jou gesinkroniseerde data sal uit die wolk uitgevee word. Seker?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Vee uit"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Kanselleer"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Jou persoonlike woordeboek sal gesinkroniseer en in Google-bedieners gerugsteun word. Die statistiese inligting van woordfrekwensie sal dalk ingesamel word om ons produkte te help verbeter. Die insameling en gebruik van al die inligting sal voldoen aan "<a href="https://www.google.com/policies/privacy">"Google se privaatheidsbeleid"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Voeg \'n Google-rekening by die toestel om hierdie kenmerk te aktiveer"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skakel oor na die ander invoermetodes"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Taal-wisselsleutel dek ook ander invoermetodes"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Taal-wisselsleutel"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Wys wanneer meervoudige invoertale geaktiveer is"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Wys glyverklikker"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Vertoon visuele aanduiding terwyl gly van Shift- of Symbol-sleutels af"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Sleutelopspringer-wagperiode"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen wagperiode nie"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Verstek"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hoofwoordeboek"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Wys voorstelle vir korrigering"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Wys voorgestelde woorde terwyl jy tik"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Wys altyd"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Wys in portretmodus"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Versteek altyd"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokkeer aanstootlike woorde"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Moenie potensieel aanstootlike woorde voorstel nie"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Outokorrigering"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Steminvoerinstellings"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Geen steminvoermetodes geaktiveer nie. Gaan taal- en invoerinstellings na."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Stuur terugvoer"</string>
-    <string name="select_language" msgid="3693815588777926848">"Invoertale"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Tale"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hulp en terugvoering"</string>
+    <string name="select_language" msgid="5709487854987078367">"Tale"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Raak hier om te stoor"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Sleutelbordtema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Wissel rekeninge"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Geen rekeninge gekies nie"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Gebruik tans <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Kanselleer"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Meld af"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Kies \'n rekening om te gebruik"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (VK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spaans (VS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serwies (Latyns)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engels (VK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engels (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaans (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serwies (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisioneel)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillies)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latyns)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kompak)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Geen taal nie (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emosiekone"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Sleutelbordtema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Gepasmaakte invoerstyle"</string>
     <string name="add_style" msgid="6163126614514489951">"Voeg styl by"</string>
     <string name="add" msgid="8299699805688017798">"Voeg by"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktiveer"</string>
     <string name="not_now" msgid="6172462888202790482">"Nie nou nie"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dieselfde invoerstyl bestaan ​​reeds: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Vertraging van sleutellangdruk"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Sleuteldruk se vibrasie-tydsduur"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Sleuteldruk se klankvolume"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lees eksterne woordeboeklêer"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Geen woordeboeklêers in die aflaaiselsvouer nie"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Kies \'n woordeboeklêer om te installeer"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Moet hierdie lêer regtig vir <xliff:g id="LANGUAGE_NAME">%s</xliff:g> geïnstalleer word?"</string>
-    <string name="error" msgid="8940763624668513648">"Daar was \'n fout"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Vertraging van sleutellangdruk"</string>
     <string name="button_default" msgid="3988017840431881491">"Verstek"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Welkom by <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"met Gebaar-tik"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nou kan jy in al jou gunstelingprogramme tik met <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Stel bykomende tale op"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Klaar"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Wys program-ikoon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Wys program-ikoon in die lanseerpoort"</string>
     <string name="app_name" msgid="6320102637491234792">"Woordeboekverskaffer"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Woordeboekverskaffer"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Woordeboek-diens"</string>
diff --git a/java/res/values-am/strings-emoji-descriptions.xml b/java/res/values-am/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..c6a6db8
--- /dev/null
+++ b/java/res/values-am/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyright sign"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registered sign"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Double exclamation mark"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Exclamation question mark"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Trade mark sign"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Information source"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Left right arrow"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Up down arrow"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"North west arrow"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"North east arrow"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"South east arrow"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"South west arrow"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Leftwards arrow with hook"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Rightwards arrow with hook"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Watch"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Hourglass"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Black right-pointing double triangle"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Black left-pointing double triangle"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Black up-pointing double triangle"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Black down-pointing double triangle"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Alarm clock"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Hourglass with flowing sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Circled latin capital letter m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Black small square"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"White small square"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Black right-pointing triangle"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Black left-pointing triangle"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"White medium square"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Black medium square"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"White medium small square"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Black medium small square"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Black sun with rays"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Cloud"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Black telephone"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Ballot box with check"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Umbrella with rain drops"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Hot beverage"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"White up pointing index"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"White smiling face"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taurus"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gemini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpius"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittarius"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquarius"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Pisces"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Black spade suit"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Black club suit"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Black heart suit"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Black diamond suit"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Hot springs"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Black universal recycling symbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Wheelchair symbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anchor"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Warning sign"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"High voltage sign"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Medium white circle"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Medium black circle"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Soccer ball"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snowman without snow"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sun behind cloud"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"No entry"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Church"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fountain"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Flag in hole"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Sailboat"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tent"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Fuel pump"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Black scissors"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"White heavy check mark"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Airplane"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Envelope"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Raised fist"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Raised hand"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Victory hand"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Pencil"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Black nib"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Heavy check mark"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Heavy multiplication x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Sparkles"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Eight spoked asterisk"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Eight pointed black star"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snowflake"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Sparkle"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Cross mark"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negative squared cross mark"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Black question mark ornament"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"White question mark ornament"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"White exclamation mark ornament"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Heavy exclamation mark symbol"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Heavy black heart"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Heavy plus sign"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Heavy minus sign"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Heavy division sign"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Black rightwards arrow"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Curly loop"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Double curly loop"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Arrow pointing rightwards then curving upwards"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Arrow pointing rightwards then curving downwards"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Leftwards black arrow"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Upwards black arrow"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Downwards black arrow"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Black large square"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"White large square"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"White medium star"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Heavy large circle"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Wavy dash"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Part alternation mark"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Circled ideograph congratulation"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Circled ideograph secret"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong tile red dragon"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Playing card black joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blood type A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blood type B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blood type O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parking lot"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blood type AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Squared CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Squared cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Squared free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Squared ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Squared new"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Squared N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Squared OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Squared SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Squared up with exclamation mark"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Squared vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Squared katakana here"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Squared katakana service"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Squared ideograph charge-free"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Squared ideograph reserved-seat"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Squared ideograph prohibitation"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Squared ideograph vacancy"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Squared ideograph acceptance"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Squared ideograph full occupancy"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Squared ideograph paid"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Squared ideograph monthly"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Squared ideograph application"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Squared ideograph discount"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Squared ideograph in business"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Circled ideograph advantage"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Circled ideograph accept"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Foggy"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Closed umbrella"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Night with stars"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sunrise over mountains"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sunrise"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Cityscape at dusk"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Sunset over buildings"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Rainbow"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Bridge at night"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Water wave"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcano"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Milky way"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Earth globe europe-africa"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Earth globe americas"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Earth globe asia-australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globe with meridians"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"New moon symbol"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Waxing crescent moon symbol"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"First quarter moon symbol"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Waxing gibbous moon symbol"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Full moon symbol"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Waning gibbous moon symbol"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Last quarter moon symbol"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Waning crescent moon symbol"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Crescent moon"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"New moon with face"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"First quarter moon with face"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Last quarter moon with face"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Full moon with face"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sun with face"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Glowing star"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Shooting star"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Chestnut"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Seedling"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Evergreen tree"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Deciduous tree"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palm tree"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Cherry blossom"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sunflower"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blossom"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Ear of maize"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Ear of rice"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herb"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Four leaf clover"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Maple leaf"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Fallen leaf"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Leaf fluttering in wind"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Mushroom"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomato"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Grapes"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Watermelon"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tangerine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Lemon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Pineapple"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Red apple"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Green apple"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pear"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Peach"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cherries"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Strawberry"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Slice of pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Meat on bone"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Poultry leg"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rice cracker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rice ball"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Cooked rice"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry and rice"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Steaming bowl"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Bread"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"French fries"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Roasted sweet potato"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Fried shrimp"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fish cake with swirl design"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Soft ice cream"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Shaved ice"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Ice cream"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Doughnut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chocolate bar"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Candy"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Custard"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honey pot"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Shortcake"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento box"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Pot of food"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Cooking"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Fork and knife"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Teacup without handle"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake bottle and cup"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wine glass"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktail glass"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropical drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Beer mug"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Clinking beer mugs"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Baby bottle"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Ribbon"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Wrapped present"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Birthday cake"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Jack-o-lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Christmas tree"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Father christmas"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fireworks"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Firework sparkler"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balloon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Party popper"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Confetti ball"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata tree"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Crossed flags"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Pine decoration"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanese dolls"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Carp streamer"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Wind chime"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Moon viewing ceremony"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"School satchel"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Graduation cap"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Carousel horse"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ferris wheel"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Roller coaster"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Fishing pole and fish"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microphone"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Movie camera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Headphone"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Artist palette"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Top hat"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Circus tent"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ticket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Clapper board"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Performing arts"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video game"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Direct hit"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Slot machine"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billiards"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Game die"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Flower playing cards"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musical note"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Multiple musical notes"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Musical keyboard"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trumpet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violin"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Musical score"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Running shirt with sash"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennis racquet and ball"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski and ski boot"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball and hoop"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Chequered flag"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Runner"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trophy"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Horse racing"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"American football"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby football"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Swimmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"House building"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"House with garden"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Office building"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japanese post office"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"European post office"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Automated teller machine"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Convenience store"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"School"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Department store"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Factory"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya lantern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japanese castle"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"European castle"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rat"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mouse"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Ox"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Water buffalo"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Cow"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Rabbit"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Cat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodile"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Whale"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Snail"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Snake"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Horse"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ram"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Goat"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Sheep"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Monkey"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Rooster"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Chicken"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Dog"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Pig"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Boar"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elephant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Octopus"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiral shell"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Bug"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Ant"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Honeybee"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Lady beetle"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fish"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropical fish"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Blowfish"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Turtle"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Hatching chick"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Baby chick"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Front-facing baby chick"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Bird"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Penguin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poodle"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedary camel"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Bactrian camel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dolphin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mouse face"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cow face"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tiger face"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Rabbit face"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cat face"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Dragon face"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Spouting whale"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Horse face"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Monkey face"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Dog face"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Pig face"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Frog face"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamster face"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wolf face"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Bear face"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda face"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Pig nose"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Paw prints"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Eyes"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ear"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nose"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mouth"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tongue"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"White up pointing backhand index"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"White down pointing backhand index"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"White left pointing backhand index"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"White right pointing backhand index"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Fisted hand sign"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Waving hand sign"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Ok hand sign"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Thumbs up sign"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Thumbs down sign"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Clapping hands sign"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Open hands sign"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Crown"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Womans hat"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Eyeglasses"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Necktie"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Dress"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Womans clothes"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Purse"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handbag"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pouch"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Mans shoe"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Athletic shoe"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"High-heeled shoe"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Womans sandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Womans boots"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Footprints"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Bust in silhouette"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Busts in silhouette"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Boy"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Girl"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Man"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Woman"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Family"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Man and woman holding hands"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Two men holding hands"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Two women holding hands"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Police officer"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Woman with bunny ears"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Bride with veil"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Person with blond hair"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Man with gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Man with turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Older man"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Older woman"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Construction worker"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princess"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanese ogre"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanese goblin"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Ghost"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Baby angel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestrial alien"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Alien monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Imp"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Skull"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Information desk person"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardsman"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dancer"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lipstick"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nail polish"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Face massage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Haircut"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barber pole"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Syringe"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pill"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kiss mark"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Love letter"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Gem stone"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kiss"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Couple with heart"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Wedding"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Beating heart"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Broken heart"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Two hearts"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Sparkling heart"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Growing heart"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Heart with arrow"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blue heart"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Green heart"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Yellow heart"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Purple heart"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Heart with ribbon"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Revolving hearts"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Heart decoration"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamond shape with a dot inside"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Electric light bulb"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Anger symbol"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomb"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Sleeping symbol"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Collision symbol"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Splashing sweat symbol"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Droplet"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Dash symbol"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Pile of poo"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Flexed biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Dizzy symbol"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Speech balloon"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Thought balloon"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"White flower"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Hundred points symbol"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Money bag"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Currency exchange"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Heavy dollar sign"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Credit card"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknote with yen sign"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknote with dollar sign"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknote with euro sign"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknote with pound sign"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Money with wings"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Chart with upwards trend and yen sign"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Seat"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personal computer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Briefcase"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppy disk"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optical disc"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"File folder"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Open file folder"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Page with curl"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Page facing up"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendar"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Tear-off calendar"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Card index"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Chart with upwards trend"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Chart with downwards trend"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Bar chart"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Clipboard"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pushpin"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Round pushpin"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Paperclip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Straight ruler"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Triangular ruler"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Bookmark tabs"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ledger"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notebook"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notebook with decorative cover"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Closed book"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Open book"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Green book"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blue book"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Orange book"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Books"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Name badge"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Scroll"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telephone receiver"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax machine"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellite antenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Public address loudspeaker"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Cheering megaphone"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Outbox tray"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Inbox tray"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Package"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mail symbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Incoming envelope"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Envelope with downwards arrow above"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Closed mailbox with lowered flag"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Closed mailbox with raised flag"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Open mailbox with raised flag"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Open mailbox with lowered flag"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postbox"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Postal horn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Newspaper"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobile phone"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobile phone with rightwards arrow at left"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibration mode"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobile phone off"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"No mobile phones"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna with bars"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Camera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Video camera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Television"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Twisted rightwards arrows"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Clockwise rightwards and leftwards open circle arrows"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Clockwise rightwards and leftwards open circle arrows with circled one overlay"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Clockwise downwards and upwards open circle arrows"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Anticlockwise downwards and upwards open circle arrows"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Low brightness symbol"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"High brightness symbol"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Speaker with cancellation stroke"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Speaker"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Speaker with one sound wave"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Speaker with three sound waves"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Battery"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Electric plug"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Left-pointing magnifying glass"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Right-pointing magnifying glass"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lock with ink pen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Closed lock with key"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Key"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lock"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Open lock"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Bell"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Bell with cancellation stroke"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bookmark"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Link symbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radio button"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back with leftwards arrow above"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End with leftwards arrow above"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On with exclamation mark with left right arrow above"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon with rightwards arrow above"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top with upwards arrow above"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"No one under eighteen symbol"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Keycap ten"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Input symbol for latin capital letters"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Input symbol for latin small letters"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Input symbol for numbers"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Input symbol for symbols"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Input symbol for latin letters"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fire"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Electric torch"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Wrench"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Nut and bolt"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscope"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescope"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Crystal ball"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Six pointed star with middle dot"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japanese symbol for beginner"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trident emblem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Black square button"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"White square button"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Large red circle"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Large blue circle"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Large orange diamond"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Large blue diamond"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Small orange diamond"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Small blue diamond"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Up-pointing red triangle"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Down-pointing red triangle"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Up-pointing small red triangle"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Down-pointing small red triangle"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Clock face one oclock"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Clock face two oclock"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Clock face three oclock"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Clock face four oclock"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Clock face five oclock"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Clock face six oclock"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Clock face seven oclock"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Clock face eight oclock"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Clock face nine oclock"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Clock face ten oclock"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Clock face eleven oclock"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Clock face twelve oclock"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Clock face one-thirty"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Clock face two-thirty"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Clock face three-thirty"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Clock face four-thirty"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Clock face five-thirty"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Clock face six-thirty"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Clock face seven-thirty"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Clock face eight-thirty"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Clock face nine-thirty"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Clock face ten-thirty"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Clock face eleven-thirty"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Clock face twelve-thirty"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mount fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statue of liberty"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhouette of japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Grinning face"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Grinning face with smiling eyes"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Face with tears of joy"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Smiling face with open mouth"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Smiling face with open mouth and smiling eyes"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Smiling face with open mouth and cold sweat"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Smiling face with open mouth and tightly-closed eyes"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Smiling face with halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Smiling face with horns"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Winking face"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Smiling face with smiling eyes"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Face savouring delicious food"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Relieved face"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Smiling face with heart-shaped eyes"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Smiling face with sunglasses"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Smirking face"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutral face"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Expressionless face"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Unamused face"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Face with cold sweat"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Pensive face"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Confused face"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Confounded face"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kissing face"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Face throwing a kiss"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kissing face with smiling eyes"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kissing face with closed eyes"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Face with stuck-out tongue"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Face with stuck-out tongue and winking eye"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Face with stuck-out tongue and tightly-closed eyes"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Disappointed face"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Worried face"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Angry face"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Pouting face"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Crying face"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Persevering face"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Face with look of triumph"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Disappointed but relieved face"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Frowning face with open mouth"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Anguished face"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Fearful face"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Weary face"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Sleepy face"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Tired face"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimacing face"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Loudly crying face"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Face with open mouth"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Hushed face"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Face with open mouth and cold sweat"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Face screaming in fear"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Astonished face"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Flushed face"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Sleeping face"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Dizzy face"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Face without mouth"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Face with medical mask"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Grinning cat face with smiling eyes"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cat face with tears of joy"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Smiling cat face with open mouth"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Smiling cat face with heart-shaped eyes"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cat face with wry smile"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kissing cat face with closed eyes"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Pouting cat face"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Crying cat face"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Weary cat face"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Face with no good gesture"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Face with ok gesture"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Person bowing deeply"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"See-no-evil monkey"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Hear-no-evil monkey"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Speak-no-evil monkey"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Happy person raising one hand"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person raising both hands in celebration"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Person frowning"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Person with pouting face"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person with folded hands"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rocket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Steam locomotive"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Railway car"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"High-speed train"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"High-speed train with bullet nose"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Train"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Light rail"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Station"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tram"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tram car"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Oncoming bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleybus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bus stop"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Fire engine"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Police car"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Oncoming police car"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Oncoming taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobile"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Oncoming automobile"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Recreational vehicle"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Delivery truck"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Articulated lorry"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Mountain railway"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Suspension railway"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Mountain cableway"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Aerial tramway"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Ship"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Rowboat"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedboat"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontal traffic light"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertical traffic light"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Construction sign"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Police cars revolving light"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Triangular flag on post"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Door"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"No entry sign"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Smoking symbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"No smoking symbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Put litter in its place symbol"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Do not litter symbol"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Potable water symbol"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Non-potable water symbol"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicycle"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"No bicycles"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Bicyclist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountain bicyclist"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pedestrian"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"No pedestrians"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Children crossing"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Mens symbol"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Womens symbol"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Restroom"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Baby symbol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Water closet"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Shower"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bath"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bathtub"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Passport control"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Customs"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Baggage claim"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Left luggage"</string>
+</resources>
diff --git a/java/res/values-am/strings-talkback-descriptions.xml b/java/res/values-am/strings-talkback-descriptions.xml
index 84c3cb0..38377e7 100644
--- a/java/res/values-am/strings-talkback-descriptions.xml
+++ b/java/res/values-am/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"ምንም ፅሁፍ አልገባም"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>ን ወደ <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> ያርመዋል"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> የራስ ሰር እርማት ያከናውናል"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"ጥቆማ ሃሳብ የለም"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"ያልታወቀ ቁምፊ"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"ቀይር"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"ተጨማሪ ምልክቶች"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"አቢይ ሆሄ አይ፣ ነጥብ ከላይ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"ያልታወቀ ምልክት"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"ያልታወቀ ስሜት ገላጭ ምስል"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"የደበረው ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"ያፈረ ፊት"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"የጸሐይ መነጽር የሚለብስ ፊት"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"የደነቀው ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"የሚስም ፊት"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"የሚኮሳተር ፊት"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ተለዋጭ ቁምፊዎች ይገኛሉ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ተለዋጭ ቁምፊዎች ተሰናብተዋል"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ተለዋጭ የአስተያየት ጥቆማዎች ይገኛሉ"</string>
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 7f5b322..48507e0 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"በቁልፍመጫንጊዜ አንዝር"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"በቁልፍ መጫን ላይ የሚወጣ ድምፅ"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"ቁልፍ ጫን ላይ ብቅ ባይ"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ምርጫዎች"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"መለያዎች እና ግላዊነት"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"መልክ እና አቀማመጦች"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"በጣት ምልክት መተየብ"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"ፅሁፍ ማስተካከያ"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"የላቀ"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"ገፅታ"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"የተከፈለ ቁልፍ ሰሌዳ አንቃ"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google ቁልፍ ሰሌዳ አመሳስል"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"አመሳስል በርቷል"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"የግል መዝገበ-ቃላትዎን በሁሉም መሣሪያዎች ላይ ያመሳስሉ"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"አሁን አመሳስል"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"የደመና ውሂብ ይሰርዙ"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"ከGoogle የእርስዎን የተመሳሰለ ውሂብ ይሰርዛል"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"የተመሳሰለው ውሂብዎ ከደመናው ይሰረዛል። እርግጠኛ ነዎት?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ሰርዝ"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ይቅር"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"የግል መዝገበ-ቃላትዎ ይመሳሰልና ምትኬው በGoogle አገልጋዮች ላይ ይቀመጣል። ምርቶቻችንን ለማሻሻል የቃላት ተደጋጋሚነት ስታቲስቲካዊ መረጃ ሊሰበሰብ ይችላል። የመረጃው አሰባሰብ እና አጠቃቀም በ"<a href="https://www.google.com/policies/privacy">"Google ግላዊነት መመሪያ"</a>" መሠረት የሚካሄድ ነው።"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ይህን ባህሪ ለማንቃት እባክዎ የGoogle መለያ ወደዚህ መሣሪያ ያክሉ"</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">"የቋንቋ መቀየሪያ ቁልፍ ሌሎች የግቤት ስልቶችንም ይሸፍናል"</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">"ተንሸራታች አመልካች አሳይ"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"ከShift ወይም የምልክት ቁልፎች በማንሸራተት ላይ ሳለ ምስላዊ ምልክት አሳይ"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"የድምፅ ግቤት ቁልፍ"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ምንም የግቤት ስልቶች አልነቁም። የቋንቋ እና የግቤት ቅንብሮችን ይፈትሹ።"</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="language_selection_title" msgid="3666971864764478269">"ቋንቋዎች"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"እገዛ እና ግብረመልስ"</string>
+    <string name="select_language" msgid="5709487854987078367">"ቋንቋዎች"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማስቀመጥ እንደገና ንካ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ለማስቀመጥ እዚህ ይንኩ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"የቁልፍ ሰሌዳ ገጽታ"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"መለያዎችን ቀይር"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ምንም መለያዎች አልተመረጡም"</string>
+    <string name="account_selected" msgid="2846876462199625974">"በአሁኑ ጊዜ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>ን በመጠቀም ላይ"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"እሺ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"ይቅር"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ዘግተህ ውጣ"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"የሚጠቀሙበትን መለያ ይምረጡ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"እንግሊዘኛ (የታላቋ ብሪታንያ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"እንግሊዘኛ (ዩ.ኤስ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ስፓኒሽኛ (ዩኤስ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ሂንግሊሽ"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"ሰርብያኛ (ላቲን)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"እንግሊዝኛ (ዩኬ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"እንግሊዝኛ (አሜሪካ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ስፓኒሽ (አሜሪካ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ሂንግሊሽ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ሰርቢያኛ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ተለምዷዊ)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ሳይሪሊክ)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ላቲን)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (እስግ)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ምንም ቋንቋ (ፊደላት)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ፊደላት (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ፊደላት (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ፊደላት (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ፊደላት (ፒሲ)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ኢሞጂ"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"የቁልፍ ሰሌዳ ገጽታ"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"የተበጁ የግቤት ስታይሎች"</string>
     <string name="add_style" msgid="6163126614514489951">"ስታይል አክል"</string>
     <string name="add" msgid="8299699805688017798">"አክል"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"እውን ይሄ ፋይል ለ<xliff:g id="LANGUAGE_NAME">%s</xliff:g> ይጫን?"</string>
-    <string name="error" msgid="8940763624668513648">"ስህተት ተከስቶ ነበር"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"የሰሌዳ ቁልፍ ጠቅታ በመጫን መዘግየት"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"አሁን በሁሉም ተወዳጅ መተግበሪያዎችዎ ላይ በ<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">"የመተግበሪያ አዶውን በማስጀመሪያው ውስጥ አሳይ"</string>
     <string name="app_name" msgid="6320102637491234792">"የመዝገበ-ቃላት አቅራቢ"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"የመዝገበ-ቃላት አቅራቢ"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"የመዝገበ-ቃላት አገልግሎት"</string>
diff --git a/java/res/values-ar/strings-emoji-descriptions.xml b/java/res/values-ar/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..c1decd3
--- /dev/null
+++ b/java/res/values-ar/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"علامة حقوق طبع ونشر"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"علامة التسجيل"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"علامة تعجب مزدوجة"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"علامة استفهام وتعجب"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"رمز علامة تجارية"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"مصدر معلومات"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"سهم لليسار واليمين"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"سهم لأعلى وأسفل"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"سهم للشمال والغرب"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"سهم للشمال والشرق"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"سهم للجنوب والشرق"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"سهم للجنوب والغرب"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"سهم لليسار مع خطاف"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"سهم لليمين مع خطاف"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"ساعة"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"ساعة رملية"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"مثلث مزدوج أسود يشير لليمين"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"مثلث مزدوج أسود يشير لليسار"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"مثلث مزدوج أسود يشير لأعلى"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"مثلث مزدوج أسود يشير لأسفل"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"ساعة منبه"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"ساعة رملية مع رمال متدفقة"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"‏حرف m لاتيني كبير محاط بدائرة"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"مربع صغير أسود"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"مربع صغير أبيض"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"مثلث أسود يشير لليمين"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"مثلث أسود يشير لليسار"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"مربع متوسط أبيض"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"مربع متوسط أسود"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"مربع صغير ومتوسط أبيض"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"مربع صغير ومتوسط أسود"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"شمس سوداء وأشعة"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"سحابة"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"هاتف أسود"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"مربع اختيار عليه علامة"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"شمسية وقطرات مطر"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"شراب ساخن"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"سبابة بيضاء تشير لأعلى"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"وجه مبتسم أبيض"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"الحمل"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"الثور"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"الجوزاء"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"السرطان"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"الأسد"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"العذراء"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"الميزان"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"العقرب"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"القوس"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"الجدي"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"الدلو"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"الحوت"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"بستوني أسود"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"أسباتي أسود"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"قلب أسود"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"ديناري أسود"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"ينابيع حارة"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"رمز إعادة تدوير أسود عام"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"رمز كرسي متحرك"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"مرساة"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"إشارة تحذير"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"إشارة فولت عال"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"دائرة بيضاء متوسطة"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"دائرة سوداء متوسطة"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"كرة قدم"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"بيسبول"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"إنسان ثلج بدون ثلج"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"شمس خلف سحابة"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"نجمة شمالية"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"ممنوع الدخول"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"كنيسة"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"نافورة"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"علم على حفرة"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"مركب شراعي"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"خيمة"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"مضخة وقود"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"مقص أسود"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"علامة تحديد غامقة"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"طائرة"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"ظرف"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"قبضة مرفوعة"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"يد مرفوعة"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"يد انتصار"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"قلم رصاص"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"ريشة سوداء"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"علامة تحديد غامقة"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"‏علامة ضرب غامقة x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"وميض"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"علامة نجمية ثمانية"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"نجمة سوداء ثمانية"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"كتلة ثلج"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"ومضة"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"علامة صليب"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"علامة صليب سالبة"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"علامة استفهام سوداء مزخرفة"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"علامة استفهام بيضاء مزخرفة"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"علامة تعجب بيضاء مزخرفة"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"رمز علامة تعجب غامقة"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"قلب أسود غامق"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"علامة إضافة غامقة"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"علامة طرح غامقة"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"علامة قسمة غامقة"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"سهم أسود لليمين"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"عقدة مموجة"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"عقدة مموجة مزدوجة"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"سهم يشير لليمين مع الاتجاه لأعلى"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"سهم يشير لليمين مع الانحناء لأسفل"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"سهم أسود لليسار"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"سهم أسود لأعلى"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"سهم أسود لأسفل"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"مربع كبير أسود"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"مربع كبير أبيض"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"نجمة متوسطة بيضاء"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"دائرة كبيرة غامقة"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"شرطة مموجة"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"علامة تعاقب أجزاء"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"علامة تهنئة مستديرة"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"علامة سر مستديرة"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"ورقة تنين ما جونغ أحمر"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"جوكر أسود لورقة لعب"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"‏فصيلة A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"‏فصيلة B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"‏فصيلة O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"انتظار سيارات"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"‏فصيلة AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"واضح"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"لطيف"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"مجاني"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"هوية"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"جديد"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"سيئ"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"موافق"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"مساعدة"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"أعلى مع علامة تعجب"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"ضد"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"هنا"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"خدمة"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"مجانًا"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"مقعد محجوز"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"ممنوع"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"مكان شاغر"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"قبول"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"مشغول تمامًا"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"مدفوع"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"شهريًا"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"تطبيق"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"خصم"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"في العمل"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"ميزة"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"قبول"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"إعصار حلزوني"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"ضبابي"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"شمسية مغلقة"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"ليل ونجوم"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"شروق الشمس على جبال"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"شروق الشمس"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"مدينة عند الغسق"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"غروب الشمس على المباني"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"ألوان الطيف"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"جسر في الليل"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"موجة مياه"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"بركان"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"درب التبانة"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"كرة أرضية أوروبا وإفريقيا"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"كرة أرضية الأمريكيتان"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"كرة أرضية آسيا وأستراليا"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"كرة أرضية خطوط الطول"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"رمز محاق"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"رمز هلال"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"رمز تربيع أول"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"رمز أحدب متزايد"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"رمز بدر"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"رمز أحدب متناقص"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"رمز تربيع ثان"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"رمز هلال"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"رمز هلال"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"محاق بوجه"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"تربيع أول بوجه"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"تربيع ثان بوجه"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"بدر بوجه"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"شمس بوجه"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"نجم ساطع"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"شهاب"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"أبو فروة"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"شتلة"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"شجرة دائمة الخضرة"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"شجرة زائلة الخضرة"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"نخلة"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"صبار"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"خزامي"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"وردة كرز"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"وردة"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"كركديه"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"عباد الشمس"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"نوارة"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"كوز ذرة"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"سنبلة أرز"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"عشب"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"ورقة برسيم رباعية"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"ورقة قبقب"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"ورقة متساقطة"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"ورقة متطايرة في الريح"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"عيش الغراب"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"طماطم"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"باذنجان"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"عنب"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"شمام"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"بطيخ"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"يوسفي"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"ليمون"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"موز"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"أناناس"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"تفاح أحمر"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"تفاح أخضر"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"كمثرى"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"خوخ"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"كرز"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"فراولة"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"همبورغر"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"شريحة بيتزا"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"لحم على عظمة"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"ورك دجاجة"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"قراقيش أرز"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"كرة أرز"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"أرز مطبوخ"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"أرز وكاري"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"بولة وبخار"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"سباغتي"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"خبز"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"بطاطس مقلية"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"بطاطا مشوية معسلة"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"دانغو"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"أودين"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"سوشي"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"جمبري مقلي"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"كفتة سمك ملفوفة"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"آيس كريم سوفت"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"آيس كريم حلقات"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"آيس كريم"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"كعكة محلاة"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"كعكة"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"بار شيكولاتة"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"حلوى"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"كاسترد"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"جرة عسل"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"كعكة بسمن وسكر"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"علبة بنتو"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"حلة طعام"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"طهي"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"شوكة وسكينة"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"كوب شاي بدون يد"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"زجاجة وكأس"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wine glass"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"كأس كوكتيل"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"مشروب استوائي"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"ماغ بيرة"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"اثنان ماغ بيرة يرتطمان ببعضهما"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"زجاجة شراب رضيع"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"شريط"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"هدية ملفوفة"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"كعكة عيد ميلاد"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"قرعة مضيئة"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"شجرة كريسماس"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"بابا نويل"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"ألعاب نارية"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"ماسة ألعاب نارية"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"بالونة"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"بارتي بوبر"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"كرة كونفتي"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"شجرة تاناباتا"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"أعلام متقاطعة"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"ديكور صنوبر"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"دمى يابانية"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"كارب ستريمر"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"جرس الريح"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"استطلاع القمر"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"حقيبة مدرسية"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"قبعة تخرج"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"حصان الدوامة"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"دولاب ملاه"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"قطار ملاه"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"صنارة صيد وسمكة"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"ميكروفون"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"كاميرا أفلام"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"سينما"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"سماعة رأس"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"لوحة ألوان"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"قبعة عالية"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"خيمة سرك"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"تذكرة"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"كلاكيت"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"فنون استعر"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"لعبة فيديو"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"إصابة هدف"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"جهاز قمار"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"بيلياردو"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"نرد"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"بولينغ"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"كروت لعب أزهار"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"نوتة موسيقية"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"نوتات موسيقية متعددة"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"ساكسفون"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"غيتار"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"بيانو"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"آلة النفخ"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"كمان"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"سكور موسيقي"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"قميص للجري مع وشاح"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"مضرب تنس وكرة"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"تزلج وقارب تزلج"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"كرة سلة وطوق"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"علم مربعات"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"تزلج"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"جري"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"ركوب أمواج"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"كأس"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"سباق خيول"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"كرة قدم أمريكية"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"كرة راجبي"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"سباحة"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"ب"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"منزل وحديقة"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"مبنى إداري"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"مكتب بريد ياباني"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"مكتب بريد أوروبي"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"مستشفى"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"مصرف"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ماكينة صرف آلي"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"فندق"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"فندق حب"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"سوق 24 ساعة"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"مدرسة"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"سوق شامل"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"مصنع"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"فانوس إزاكايا"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"قلعة يابانية"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"قلعة أوروبية"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"فأر"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"ف"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"ثور"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"جاموس مائي"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"بقرة"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"فهد"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"أرنب"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"قطة"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"تنين"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"تمساح"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"حوت"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"قوقع"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"ثعبان"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"حصان"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"حمل"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"عنزة"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"نعجة"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"قرد"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"ديك"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"دجاجة"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"كلب"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"خنزير"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"خنزير بري"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"فيل"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"أخطبوط"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"صدفة حلزونية"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"بق"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"نملة"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"نحل"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"خنفساء"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"سمكة"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"سمكة استوائية"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"سمكة منتفخة"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"سلحفاة"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"كتكوت خارج البيضة"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"كتكوت"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"كتكوت يظهر بوجهه"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"طائر"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"بطريق"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"دب الكوال"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"كلب بودل"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"جمل وحيد السنام"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"جمل ثنائي السنام"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"دولفين"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"وجه فأر"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"وجه بقرة"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"وجه نمر"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"وجه أرنب"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"وجه قطة"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"وجه تنين"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"حوت بنافورة"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"وجه حصان"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"وجه قرد"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"وجه كلب"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"وجه خنزير"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"وجه ضفدع"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"وجه همستر"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"وجه ذئب"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"وجه دب"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"وجه باندا"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"أنف خنزير"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"آثار حوافر"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"أعين"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"أذن"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"أنف"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"فم"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"لسان"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"سبابة لأعلى بظهر اليد"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"سبابة لأسفل بظهر اليد"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"سبابة لليسار بظهر اليد"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"سبابة لليمين بظهر اليد"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"علامة قبضة يد"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"علامة يد تلوح"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"علامة يد موافقة"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"علامة استحسان"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"علامة استياء"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"علامة يدين تصفقان"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"علامة يدين مفتوحتين"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"تاج"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"قبعة حريمي"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"نظارة"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ربطة عنق"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"قميص"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"جينز"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"فستان"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"كيمون ياباني"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"بيكيني"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"ملابس حريمي"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"كيس نقود"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"حقيبة يد"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"حقيبة دبلوماسية"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"حذاء رياضي"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"حذاء رياضي"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"حذاء بكعب عال"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"صندل حريمي"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"حذاء عال حريمي"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"آثار أقدام"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"صورة ظلية"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"صورتان ظليتان"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"ولد"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"بنت"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"رجل"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"امرأة"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"عائلة"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"رجل وامرأة يد بيد"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"رجلان يد بيد"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"امرأتان يد بيد"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"ضابط شرطة"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"امرأة تلبس أذن أرنب"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"عروس ترتدي حجابًا"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"شخص أشقر"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"رجل يرتدي قبعة غوا بي ماو"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"رجل يرتدي عمامة"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"رجل عجوز"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"امرأة عجوز"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"رضيع"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"عامل تشييد"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"أميرة"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"غول ياباني"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"جن ياباني"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"عفريت"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"ملاك صغير"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"كائن فضائي"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"وحش غريب"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"شيطان"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"جمجمة"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"موظف استعلامات"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"حارس"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"راقصة"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"أحمر شفاه"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"عناية أظافر"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"مساج وجه"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"قصة شعر"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"قص شعر"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"إبرة"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"حبوب دواء"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"علامة قبلة"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"خطاب حب"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"خاتم"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"جوهرة"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"قبلة"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"باقة زهور"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"زوج وقلب"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"زفاف"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"قلب يخفق"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"قلب مكسور"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"قلبان"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"قلب لامع"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"قلب ينمو"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"قلب وسهم"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"قلب أزرق"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"قلب أخضر"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"قلب أصفر"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"قلب أرجواني"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"قلب عليه شريطة"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"قلب دوار"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"زخرفة قلب"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"شكل ماسة ونقطة بالداخل"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"مصباح كهربائي مضيء"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"علامة غضب"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"قنبلة"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"علامة نوم"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"علامة اصطدام"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"رمز عرق يتصبب"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"قطرة"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"علامة انطلاق"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"كومة فضلات"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"عضلة الذراع"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"علامة الدوار"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"فقاعة كلام"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"فقاعة تفكير"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"زهرة بيضاء"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"علامة 100 نقطة"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"كيس نقود"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"تغيير العملة"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"علامة دولار غامق"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"بطاقة ائتمان"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ورقة نقدية وعلامة ين"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"علامة ورقة نقدية ودولار"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ورقة نقدية وعلامة يورو"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ورقة نقدية وعلامة جنيه"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"نقود وأجنحة"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"مخطط وإشارة ارتفاع وين"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"مقعد"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"كمبيوتر شخصي"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"محفظة أوراق"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"قرص صغير"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"قرص مرن"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"قرص ضوئي"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"دي في دي"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"مجلد ملفات"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"مجلد ملفات مفتوح"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"صفحة بطية"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"صفحة بوجه لأعلى"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"تقويم"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"تقويم ممزق"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"فهرس بطاقات"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"مخطط يشير لصعود"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"مخطط يشير لهبوط"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"مخطط شريطي"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"لوحة ملصقات"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"دبوس"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"دبوس مستدير"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"مشبك ورق"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"مسطرة مستقيمة"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"مسطرة مثلثة"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"لصاقة علامات"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"كراسة ملاحظات"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"دفتر ملاحظات"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"دفتر ملاحظات بغلاف مزخرف"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"كتاب مغلق"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"كتاب مفتوح"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"كتاب أخضر"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"كتاب أزرق"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"كتاب برتقالي"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"كتب"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"ملصق اسم"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"ملفوف"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"مذكرة"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"سماعة هاتف"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"بيجر"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"فاكس"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"هوائي قمر صناعي"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"مكبر صوت للخطاب"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ميغافون للهتاف"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"صندوق صادر"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"صندوق وارد"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"طرد"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"رمز بريد إلكتروني"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ظرف وارد"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ظرف عليه سهم لأسفل"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"صندوق بريد مغلق بعلامة لأسفل"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"صندوق بريد مغلق بعلامة لأعلى"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"صندوق بريد مفتوح بعلامة لأعلى"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"صندوق بريد مفتوح بعلامة لأسفل"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"صندوق بريد"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"جرس بريد"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"جريدة"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"هاتف"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"هاتف جوال"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"وضع اهتزاز"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"هاتف جوال مغلق"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"ممنوع استخدام الهاتف الجوال"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"هوائي وأشرطة"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"كاميرا"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"كاميرا فيديو"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"تلفزيون"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"راديو"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"شريط فيديو"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"أسهم يمنى"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"أسهم يمنى ويسرى مستديرة ومفتوحة باتجاه عقارب الساعة"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"أسهم يمنى ويسرى مستديرة باتجاه عقارب الساعة مع رقم واحد"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"أسهم للأسفل مستديرة باتجاه عقارب الساعة مع رقم واحد"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"أسهم مستديرة ومفتوحة لأعلى وأسفل عكس اتجاه عقارب الساعة"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"رمز سطوع منخفض"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"رمز سطوع مرتفع"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"سماعة عليها علامة إلغاء"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"سماعة"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"سماعة عليها موجة صوتية واحدة"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"سماعة عليها ثلاث موجات صوتية"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"بطارية"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"قابس كهرباء"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"عدسة مكبرة لليسار"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"عدسة مكبرة لليمين"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"قفل عليه قلم حبر"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"قفل مغلق ومفتاح"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"مفتاح"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"قفل"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"قفل مفتوح"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"جرس"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"جرس عليه علامة إلغاء"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"علامة توقف قراءة"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"رمز رابط"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"زر راديو"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"رجوع مع سهم أيسر"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"انتهاء مع سهم أيسر"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"تشغيل مع علامة تعجب وسهم أيسر"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"علامة قريبًا مع سهم لليمين"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"أعلى مع سهم لأعلى"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"رمز ممنوع أقل من 18 عامًا"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"مفتاح عشرة"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"رمز إدخال لأحرف لاتينية كبيرة"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"رمز إدخال لأحرف لاتينية صغيرة"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"رمز إدخال لأرقام"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"رمز إدخال للرموز"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"رمز إدخال لأحرف لاتينية"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"حريق"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"كشاف كهربائي"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"مفتاح"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"مطرقة"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"صامولة ومسمار"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"هوتشو"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"مسدس"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"ميكروسكوب"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"تليسكوب"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"كرة كريستال"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"نجمة سداسية مع نقطة متوسطة"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"رمز ياباني بمعنى مبتدئ"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"رمز ثلاثي الشعب"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"زر مربع أسود"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"زر مربع أبيض"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"دائرة حمراء كبيرة"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"دائرة زرقاء كبيرة"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"ماسة برتقالية كبيرة"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"ماسة زرقاء كبيرة"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"ماسة برتقالية صغيرة"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"ماسة زرقاء صغيرة"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"مثلث أحمر لأعلى"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"مثلث أحمر يشير لأسفل"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"مثلث أحمر صغير يشير لأعلى"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"مثلث أحمر صغير يشير لأسفل"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"الساعة الواحدة"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"الساعة الثانية"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"الساعة الثالثة"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"الساعة الرابعة"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"الساعة الخامسة"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"الساعة السادسة"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"الساعة السابعة"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"الساعة الثامنة"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"الساعة التاسعة"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"الساعة العاشرة"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"الساعة الحادية عشر"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"الساعة الثانية عشر"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"الساعة الواحدة والنصف"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"الساعة الثانية والنصف"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"الساعة الثالثة والنصف"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"الساعة الرابعة والنصف"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"الساعة الخامسة والنصف"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"الساعة السادسة والنصف"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"الساعة السابعة والنصف"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"الساعة الثامنة والنصف"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"الساعة التاسعة والنصف"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"الساعة العاشرة والنصف"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"الساعة الحادية عشر والنصف"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"الساعة الثانية عشر والنصف"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"جبل فوجي"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"برج طوكيو"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"تمثال الحرية"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"صورة ظلية لليابان"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"موياي"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"وجه مبتسم"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"وجه مبتسم وأعين مبتسمة"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"وجه عليه دموع فرح"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"وجه مبتسم بفم مفتوح"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"وجه مبتسم بفم مفتوح وأعين مبتسمة"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"وجه مبتسم بفم مفتوح وعرق بارد"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"وجه مبتسم بفم مفتوح وأعين مغلقة بشدة"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"وجه مبتسم يعلوه هالة"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"وجه مبتسم بقرون"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"وجه بغمزة"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"وجه مبتسم بأعين مبتسمة"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"وجه يستلذ بطعام لذيذ"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"وجه"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"وجه مبتسم وأعين على شكل قلب"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"وجه مبتسم مع نظارة شمس"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"وجه"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"وجه محايد"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"وجه بدون تعبير"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"وجه غير مستمتع"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"وجه عليه عرق بارد"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"وجه متأمل"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"وجه متحير"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"وجه مرتبك"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"وجه يبعث قبلة"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"وجه يطرح قبلات"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"وجه يطرح قبلات بأعين مبتسمة"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"وجه يبعث قبلات بأعين مغلقة"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"وجه بلسان متدل"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"وجه بلسان متدل مع غمزة"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"وجه بلسان متدل وأعين مغلقة بشدة"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"وجه مستاء"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"وجه منزعج"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"وجه غاضب"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"وجه غاضب"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"وجه باك"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"وجه متجلد"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"وجه تعلوه نظرة انتصار"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"وجه ساكن بعد خيبة أمل"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"وجه عبوس بفم مفتوح"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"وجه مكروب"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"وجه خائف"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"وجه"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"وجه ناعس"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"وجه مجهد"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"وجه"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"وجه بصراخ مرتفع"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"وجه بفم مفتوح"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"وجه هادئ"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"وجه بفم مفتوح وعرق بارد"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"وجه يصرخ خوفًا"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"وجه مندهش"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"وجه متورد"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"وجه نائم"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"وجه مصاب بالدوار"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"وجه"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"وجه بكمامة برد"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"وجه قطة مبتسم بأعين مبتسمة"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"وجه قطة بدموع فرح"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"وجه قطة مبتسم بفم مفتوح"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"وجه قطة مبتسم بأعين على شكل قلب"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"وجه قطة وابتسامة ساخرة"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"وجه قطة"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"وجه قطة متجهم"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"وجه قطة باك"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"وجه قطة قلق"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"وجه بإشارة أمر سيئ"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"وجه بإشارة أمر جيد"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"شخص ينحني بشدة"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"قرد بحجب عينيه"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"قرد يحجب أذنيه"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"قرد يحجب كلامه"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"شخص سعيد يرفع يدًا واحدة"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"شخص يرفع يديه احتفاءً"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"شخص عبوس"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"شخص بوجه متجهم"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"شخص بيدين مضمومتين"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"صاروخ"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"هليكوبتر"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"جرار بخار"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"عربة قطار"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"قطار سريع"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"قطار سريع بوجه محدب"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"قطار"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"مترو"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"نقل خفيف"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"محطة"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ترام"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"سيارة ترام"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"حافلة"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"حافلة عن قرب"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"حافلة ترولي"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"موقف حافلات"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"حافلة صغيرة"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"سيارة إسعاف"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"سيارة إطفاء"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"سيارة شرطة"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"سيارة شرطة عن قرب"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"سيارة أجرة"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"سيارة أجرة عن قرب"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"سيارة"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"سيارة عن قرب"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"مركبة استجمام"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"شاحنة توصيل"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"لوري شبه مقطورة"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"جرار"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"خط سكة حديد أحادي"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"قطار جبلي"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"خط سكة حديد معلقة"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"قطار جبلي"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ترام هوائي"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"سفينة"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"زورق تجديف"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"قارب سريع"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"إشارة مرور أفقية"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"إشارة مرور أفقية"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"إشارة تحت الإنشاء"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"إضاءة سيارات شرطة متجددة"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"علم مثلث على عمود"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"باب"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"علامة ممنوع الدخول"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"رمز التدخين"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"رمز ممنوع التدخين"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"رمز وضع النفايات في مكانها"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"رمز عدم رمي النفايات"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"رمز مياه صالحة للشرب"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"رمز مياه غير صالحة للشرب"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"دراجة"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"ممنوع ركوب الدراجات"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"راكب دراجة"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"راكب دراجة جبال"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"مشاة"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"ممنوع سير المشاة"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"عبور أطفال"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"رمز رجال"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"رمز سيدات"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"مرحاض"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"رمز رضيع"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"حمام"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"دورة مياه"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"استحمام شاور"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"استحمام"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"حوض استحمام"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"مراقبة جوازات السفر"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"الجمارك"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"استرداد الحقائب"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"أمتعة"</string>
+</resources>
diff --git a/java/res/values-ar/strings-talkback-descriptions.xml b/java/res/values-ar/strings-talkback-descriptions.xml
index bd2d7c6..338a11d 100644
--- a/java/res/values-ar/strings-talkback-descriptions.xml
+++ b/java/res/values-ar/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"لم يتم إدخال نص"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> لتصحيح <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> إلى <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> لإجراء التصحيح التلقائي"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"لا اقتراحات"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"حرف غير معروف"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"المزيد من الرموز"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"رمز غير معروف"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"رمز تعبيري غير معروف"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"وجه يبدو عليه الملل"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"وجه يبدو عليه الإحراج"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"وجه يرتدي نظارات شمسية"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"وجه يبدو عليه الاندهاش"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"وجه يبعث قبلة"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"وجه عبوس"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"تتوفر الأحرف البديلة"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"تم تجاهل الأحرف البديلة"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"تتوفر الاقتراحات البديلة"</string>
diff --git a/java/res/values-ar/strings.xml b/java/res/values-ar/strings.xml
index e76280d..db78e31 100644
--- a/java/res/values-ar/strings.xml
+++ b/java/res/values-ar/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"اهتزاز عند ضغط مفتاح"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"صوت عند الضغط على مفتاح"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"انبثاق عند ضغط مفتاح"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"التفضيلات"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"الحسابات والخصوصية"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"المظهر والتنسيقات"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"الكتابة بالإشارة"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"تصحيح النص"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"الإعدادات المتقدمة"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"المظهر"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"هل تريد تمكين لوحة المفاتيح المقسمة"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"‏مزامنة لوحة مفاتيح Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"تم تشغيل المزامنة"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"يمكنك مزامنة قاموسك الشخصي على جميع الأجهزة"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"المزامنة الآن"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"حذف البيانات من السحاب"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"‏لحذف بياناتك التي تمت مزامنتها من Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"سيتم حذف بياناتك المتزامنة من السحاب. هل تريد ذلك بالتأكيد؟"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"حذف"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"إلغاء"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"‏ستتم مزامنة قاموسك الشخصي والاحتفاظ بنسخة احتياطية منه على خوادم Google، وقد يتم جمع المعلومات الإحصائية لتكرار الكلمات للمساعدة في تحسين منتجاتنا هذا وسيتوافق جمع كل المعلومات واستخدامها مع "<a href="https://www.google.com/policies/privacy">"سياسة خصوصية Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"‏الرجاء إضافة حساب Google إلى هذا الجهاز لتمكين هذه الميزة."</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">"يغطي مفتاح تبديل اللغات أساليب الإدخال الأخرى أيضًا"</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">"إظهار مؤشر التمرير"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"‏عرض تلميح مرئي أثناء التمرير من مفتاح 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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"مفتاح الإدخال الصوتي"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"لم يتم تمكين أي أساليب إدخال صوتي. تحقق من إعدادات اللغة والإدخال."</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="language_selection_title" msgid="3666971864764478269">"اللغات"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"المساعدة والتعليقات"</string>
+    <string name="select_language" msgid="5709487854987078367">"اللغات"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"المس مرة أخرى للحفظ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"المس هنا للحفظ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"مظهر لوحة المفاتيح"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"تبديل الحسابات"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"لم يتم تحديد أي حساب"</string>
+    <string name="account_selected" msgid="2846876462199625974">"يتم حاليًا استخدام <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"موافق"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"إلغاء"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"الخروج"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"تحديد حساب لاستخدامه"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"الإنجليزية (المملكة المتحدة)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"الإنجليزية (الولايات المتحدة)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"الإسبانية (الأميركية)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"هنجليزية"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"الصربية (اللاتينية)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"الإنجليزية (المملكة المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"الإنجليزية (الولايات المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"الإسبانية (الولايات المتحدة) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هنجليزية (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"الصربية (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (التقليدية)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (السريلية)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (اللاتينية)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (مكثفة)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"بدون لغة (أبجدية)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"‏الأبجدية (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"‏الأبجدية (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"‏الأبجدية (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"‏الأبجدية (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"الرموز التعبيرية"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"مظهر لوحة المفاتيح"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"أنماط الإدخال المخصصة"</string>
     <string name="add_style" msgid="6163126614514489951">"إضافة نمط"</string>
     <string name="add" msgid="8299699805688017798">"إضافة"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"هل تريد حقًا تثبيت هذا الملف للغة <xliff:g id="LANGUAGE_NAME">%s</xliff:g>؟"</string>
-    <string name="error" msgid="8940763624668513648">"حدث خطأ"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"تأخير الضغط الطويل للمفاتيح"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"الآن أصبح بإمكانك الكتابة في جميع تطبيقاتك المفضلة باستخدام <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">"عرض رمز التطبيق في المشغل"</string>
     <string name="app_name" msgid="6320102637491234792">"مقدم القاموس"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"مقدم القاموس"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"خدمة القاموس"</string>
diff --git a/java/res/values-az-rAZ/strings-talkback-descriptions.xml b/java/res/values-az-rAZ/strings-talkback-descriptions.xml
index 8f23627..104e57e 100644
--- a/java/res/values-az-rAZ/strings-talkback-descriptions.xml
+++ b/java/res/values-az-rAZ/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Mətn daxil edilməyib"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> sözünü <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> sözü ilə əvəzləyərək düzəldir"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> avto-korreksiyanı həyata keçirir"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Təklif yoxdur"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Naməlum simvol"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Sürüşdürmə"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Daha çox simvol"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Böyük I, üstü nöqtəli"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Naməlum rəmz"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Naməlum emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Darıxan sifət"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Çaşmış sifət"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gün eynəyi taxan sifət"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Təəccüblü sifət"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Öpən sifət"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Mısmırıqlı sifət"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativ simvollar əlçatandır"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativ simvollar kənarlaşdırılıb"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativ təkliflər əlçatandır"</string>
diff --git a/java/res/values-az-rAZ/strings.xml b/java/res/values-az-rAZ/strings.xml
index dea1f60..4fff000 100644
--- a/java/res/values-az-rAZ/strings.xml
+++ b/java/res/values-az-rAZ/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrasiyalı klikləmə"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Klikləmə səsi"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Klikləmədə popup"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Daxiletmə tərcihləri"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Görünüş"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Çoxdilli seçimlər"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Jest ilə yazı tərcihləri"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Seçimlər"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Hesablar &amp; Məxfilik"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Görünüş &amp; Düzümlər"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Jest ilə yazma"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Mətn korreksiyası"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Qabaqcıl"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Klaviaturanı ayırmağa icazə verin"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Klaviatura Sinxronlaşması"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinxronlaşdırma yandırılıb"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Cihazlarda şəxsi lüğətinizi sinxronlaşdırın"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"İndi sinxronizə edin"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Bulud datanı silin"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google\'dan olan sinx datanızı siləcək."</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Sinxronlaşdırılmış verilənləriniz buluddan silinəcək. Əminsiniz?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Silin"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Ləğv et"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Şəxsi lüğətiniz sinxronlaşdırılacaq və Google serverlərinə ehtiyat nüsxəsi çıxarılacaq. Söz tezliyinin statistik məlumatı məhsullarımızı təkmilləşdirməyə kömək üçün toplana bilər. Bütün məlumatın toplanması və istifadəsi "<a href="https://www.google.com/policies/privacy">"Google Məxfilik Siyasətinə"</a>" uyğun olmalıdır."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Bu funksiyanı aktivləşdirmək üçün cihaza Google hesabı əlavə edin"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Digər daxiletmə metodlarına keçin"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Dil keçid düyməsi başqa daxiletmə metodlarını da əhatə edir"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Dil keçidi düyməsi"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Çoxsaylı daxiletmə dilləri aktivləşdikdə göstər"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Slayd indikatorunu göstər"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Sürüşdürmə və ya Simvol düymələrinə keçərkən vizual işarəni göstər"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Klaviş popup kənarlaşdırılmasında gecikmə"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Gecikmə yoxdur"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Əsas lüğət"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Korreksiya təkliflərini göstər"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Yazarkən təklif edilən sözləri ekranda göstər"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Həmişə göstər"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Portret rejimində göstər"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Həmişə gizlət"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Təhqiredici sözləri əngəlləyin"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Potensial təhqiredici sözlər təklif etməyin"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Avtomatik-korreksiya"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Səs daxiletmə klavişi"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Heç bir səs daxiletmə metodu aktiv deyil. Dil və daxiletmə ayarlarını yoxlayın."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Daxiletmə üsullarını sazla"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Daxiletmə dilləri"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Cavab rəyi göndərin"</string>
-    <string name="select_language" msgid="3693815588777926848">"Daxiletmə dilləri"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Dillər"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Yardım və geri əlaqə"</string>
+    <string name="select_language" msgid="5709487854987078367">"Dillər"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Yadda saxlamaq üçün yenidən toxunun"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Yadda saxlamaq üçün buraya toxunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Lüğət mövcuddur"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatura teması"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Hesablar arasında keçid edin"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Heç bir hesab seçilməyib"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Hazırda istifadə olunur: <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Ok"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Ləğv et"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Çıxış"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"İşlətmək üçün hesab seçin"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"İngilis (BK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"İngilis (ABŞ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"İspan (ABŞ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hingilis"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serb (Latın)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"İngilis (Britaniya) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"İngilis (Amerika) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"İspan (Amerika) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilis (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Ənənəvi)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kiril)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latın)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Dil yoxdur (Əlifba)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Əlifba (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Əlifba (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Əlifba (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Klaviatura teması"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Holo Ağ"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Holo Göy"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Material Tünd"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Material Açıq"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Xüsusi daxiletmə üslubları"</string>
     <string name="add_style" msgid="6163126614514489951">"Stil əlavə et"</string>
     <string name="add" msgid="8299699805688017798">"Əlavə et"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktiv et"</string>
     <string name="not_now" msgid="6172462888202790482">"İndi yox"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Eyni daxiletmə üslubu artıq mövcuddur: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Klavişi uzun müddət basmada gecikmə"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrasiyalı klikləmə müddəti"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Səsli klikləmə səsi"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Xarici lüğət faylını oxuyun"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Endirmə Qovluğunda heç bir lüğət faylı yoxdur"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Yükləmək üçün lüğət faylı seçin"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> üçün faylı quraşdırmaq istədiyinizə əminsiniz?"</string>
-    <string name="error" msgid="8940763624668513648">"Xəta var idi"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Klavişi uzun müddət basmada gecikmə"</string>
     <string name="button_default" msgid="3988017840431881491">"Defolt"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> təbiqinə xoş gəlmisiniz"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Jest Yazısı ilə"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"İndi siz <xliff:g id="APPLICATION_NAME">%s</xliff:g> ilə bütün sevimli tətbiqlərinizdə yaza bilərsiniz."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Əlavə dillər quraşdır"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Sona çatdı"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Tətbiq ikonasını göstər"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Başlatma panelində tətbiq ikonasını göstər"</string>
     <string name="app_name" msgid="6320102637491234792">"Lüğət Provayderi"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Lüğət Provayderi"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Lüğət Xidməti"</string>
diff --git a/java/res/values-bg/strings-emoji-descriptions.xml b/java/res/values-bg/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..6aded1b
--- /dev/null
+++ b/java/res/values-bg/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Знак за авторски права"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Знак за запазена марка"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Двоен удивителен знак"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Удивителен и въпросителен знак"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Знак за търговска марка"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Източник на информация"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Стрелка за наляво и надясно"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Стрелка за нагоре и надолу"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Стрелка за север и запад"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Стрелка за север и изток"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Стрелка за юг и изток"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Стрелка за юг и запад"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Стрелка за наляво с кукичка"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Стрелка за надясно с кукичка"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Часовник"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Пясъчен часовник"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Черен, насочен надясно двоен триъгълник"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Черен, насочен наляво двоен триъгълник"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Черен, насочен нагоре двоен триъгълник"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Черен, насочен надолу двоен триъгълник"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Будилник"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Пясъчен часовник с падащ пясък"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Латинска главна буква M в кръгче"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Черно квадратче"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Бяло квадратче"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Черен, насочен надясно триъгълник"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Черен, насочен наляво триъгълник"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Среден бял квадрат"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Среден черен квадрат"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Средно бяло квадратче"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Средно черно квадратче"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Черно слънце с лъчи"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Облак"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Черен телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Избирателна кутия с отметка"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Чадър с дъждовни капки"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Гореща напитка"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Бял, сочещ нагоре показалец"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Бяло усмихнато лице"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Овен"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Телец"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Близнаци"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Рак"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Лъв"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Дева"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Везни"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Скорпион"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Стрелец"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Козирог"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Водолей"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Риби"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Черна карта пика"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Черна карта спатия"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Черна карта купа"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Черна карта каро"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Термални извори"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Универсален черен символ за рециклиране"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Символ за инвалидна количка"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Котва"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Знак за внимание"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Знак за високо напрежение"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Средно бяло кръгче"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Средно черно кръгче"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Топка за футбол"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бейзбол"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Снежен човек без сняг"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Слънце зад облак"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Змиеносец"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Влизането забранено"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Църква"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтан"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Флагче в дупка"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Платноходка"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Палатка"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Горивна помпа"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Черни ножици"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Масивна бяла отметка"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Самолет"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Плик"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Вдигнат юмрук"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Вдигната ръка"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Ръка с два пръста в знак за победа"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Молив"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Черно перо"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Масивна отметка"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Масивен знак за умножение „x“"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Искри"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Звездичка с осем лъча"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Осмоъгълна черна звезда"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Снежинка"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Искра"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Кръстче"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Кръстче в черно квадратче"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Черен въпросителен знак"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Бял въпросителен знак"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Бял удивителен знак"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Масивен удивителен знак"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Масивно черно сърце"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Масивен знак плюс"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Масивен знак минус"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Масивен знак за деление"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Черна, сочеща надясно стрелка"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Усукана примка"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Двойна усукана примка"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Стрелка, сочеща надясно и след това нагоре"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Стрелка, сочеща надясно и след това надолу"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Сочеща наляво черна стрелка"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Сочеща нагоре черна стрелка"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Сочеща надолу черна стрелка"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Голям черен квадрат"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Голям бял квадрат"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Бяла средна звезда"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Масивно голямо кръгче"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Вълнисто тире"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Музикален знак за смяна на гласа"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Идеограма „Поздравления“ в кръгче"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Идеограма „Тайна“ в кръгче"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Плочка от игра „Махджонг“ с червен дракон"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Карта черен джокер"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Кръвна група A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Кръвна група B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Кръвна група 0"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Паркинг"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Кръвна група AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"„CL“ в квадратче"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"„COOL“ в квадратче"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"„FREE“ в квадратче"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"„ID“ в квадратче"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"„NEW“ в квадратче"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"„N G“ в квадратче"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"„OK“ в квадратче"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"„SOS“ в квадратче"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"„Up с удивителен знак“ в квадратче"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"„VS“ в квадратче"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"„Тук“ на катакана в квадратче"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"„Услуга“ на катакана в квадратче"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Идеограма „Безплатно“ в квадратче"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Идеограма „Запазено място“ в квадратче"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Идеограма „Забрана“ в квадратче"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Идеограма „Празно място“ в квадратче"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Идеограма „Приемане“ в квадратче"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Идеограма „Пълна заетост“ в квадратче"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Идеограма „Платено“ в квадратче"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Идеограма „Месечно“ в квадратче"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Идеограма „Прилагане“ в квадратче"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Идеограма „Отстъпка“ в квадратче"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Идеограма „Отворено за бизнес“ в квадратче"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Идеограма „Предимство“ в кръгче"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Идеограма „Приемане“ в кръгче"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Мъгливо"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Затворен чадър"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Нощ със звезди"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Изгрев над планини"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Изгрев"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Градски пейзаж по здрач"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Залез над сгради"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Дъга"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Мост през нощта"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Водна вълна"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Млечен път"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Глобус с Европа и Африка"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Глобус с Южна и Северна Америка"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Глобус с Азия и Австралия"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Глобус с меридиани"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Символ за новолуние"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Символ на луна с нарастващ полумесец"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Символ за първата четвърт на луната"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Символ на луна преди пълнолуние"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Символ за пълнолуние"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Символ на луна след пълнолуние"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Символ за последната четвърт на луната"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Символ на луна с намаляващ полумесец"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Полумесец"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Новолуние с лице"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Първа четвърт на луната с лице"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Последна четвърт на луната с лице"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Пълнолуние с лице"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Слънце с лице"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Ярка звезда"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Падаща звезда"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Кестен"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Младо стръкче"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Вечнозелено дърво"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Широколистно дърво"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Палмово дърво"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Лале"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Черешов цвят"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Роза"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Хибискус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Слънчоглед"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Цвят"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Царевичен клас"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Оризов клас"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Билка"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Четирилистна детелина"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Кленов лист"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Паднало листо"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Листо, развяващо се от вятъра"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Гъба"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Домат"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Патладжан"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Грозде"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Пъпеш"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Диня"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарина"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банан"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Червена ябълка"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Зелена ябълка"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Круша"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Праскова"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Череши"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Ягода"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Хамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Парче пица"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Кокал с месо"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Пилешко бутче"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Оризов крекер"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Оризова топка"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Сварен ориз"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Къри и ориз"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Димяща купа"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Спагети"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Хляб"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Пържени картофи"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Печен сладък картоф"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Оден"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Пържена скарида"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Рибено роле"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Сладолед във фунийка от машина"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Плодов скреж"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Сладолед"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Поничка"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Курабийка"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Шоколадово блокче"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Бонбон"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Близалка"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Крем карамел"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Гърне с мед"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Маслена торта"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Кутия с бенто"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Купа с храна"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Готвене"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Вилица и нож"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Чаена чаша без дръжка"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Бутилка и чаша за саке"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Чаша за вино"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Чаша за коктейли"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропическа напитка"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Бирена халба"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Чукащи се халби за бира"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Бебешка бутилка"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Панделка"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Опакован подарък"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Торта за рожден ден"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Тиквен фенер"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Коледно дърво"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Дядо Коледа"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Фойерверки"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Бенгалски огън"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Балон"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Конфети"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Топка с конфети"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Дърво Танабата"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Кръстосани знамена"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Украса от бор"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Японски кукли"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Вимпел с шаран"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Вятърно звънче"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Церемония по наблюдение на луната"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Училищна чанта"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Абсолвентска шапка"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Конче на въртележка"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Виенско колело"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Влакче в увеселителен парк"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Въдица и риба"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Филмова камера"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кино"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Слушалки"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Палитра за рисуване"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Цилиндър"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Циркова шатра"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Билет"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Филмова клапа"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Сценични изкуства"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Видеоигра"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Право в целта"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Игрален автомат"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Билярд"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Зарче"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Боулинг"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Карти за игра с цветя"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музикална нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Няколко музикални ноти"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Китара"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Музикална клавиатура"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Тромпет"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Цигулка"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Партитура"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Състезателна фланелка с лента"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Тенис ракета и топка"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ски и ски обувка"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскетбол и кош"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Кариран флаг"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордист"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Бегач"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Сърфист"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Трофей"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Конни надбягвания"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Американски футбол"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ръгби"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Плувец"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Жилищна сграда"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Къща с градина"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Офис сграда"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Японска пощенска служба"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Европейска пощенска служба"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Болница"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банка"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Хотел"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Любовен хотел"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Магазин за хранителни стоки"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Училище"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Универсален магазин"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Фабрика"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Фенер за заведение тип „изакая“"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Японски замък"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Европейски замък"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Плъх"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Мишка"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Вол"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Воден бизон"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Крава"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Заек"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Котка"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Дракон"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Охлюв"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Змия"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Кон"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Овен"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Коза"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Овца"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Маймуна"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Петел"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Пиле"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Куче"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Прасе"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Глиган"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Слон"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Октопод"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Спираловидна черупка"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Дървеница"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Мравка"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Медоносна пчела"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Калинка"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Риба"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропическа риба"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Издуваща се риба"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Костенурка"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Излюпване на пиле"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Пиленце"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Пиленце, гледащо напред"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Птица"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудел"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Едногърба камила"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Двугърба камила"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Делфин"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Лице на мишка"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Лице на крава"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Лице на тигър"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Лице на заек"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Лице на котка"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Лице на дракон"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Кит, изхвърлящ фонтан от пръски"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Лице на кон"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Лице на маймуна"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Лице на куче"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Лице на прасе"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Лице на жаба"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Лице на хамстер"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Лице на вълк"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Лице на мечка"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Лице на панда"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Зурла"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Отпечатъци от лапи"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Очи"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ухо"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Нос"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Уста"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Език"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Бял, сочещ напред показалец"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Бял, сочещ надолу показалец"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Бял, сочещ наляво показалец"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Бял, сочещ надясно показалец"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Знак за юмрук"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Знак за махане с ръка"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Знак за „OK“ с ръка"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Знак за одобрение"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Знак за неодобрение"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Знак за пляскащи ръце"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Знак за отворени ръце"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Корона"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Женска шапка"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Очила"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Вратовръзка"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Тениска"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Дънки"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Рокля"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Дамски дрехи"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Портмоне"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Ръчна чанта"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Дамска чанта"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Мъжка обувка"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Спортна обувка"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Обувка с висок ток"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Женски сандал"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Женски ботуши"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Отпечатъци"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Силует на бюст"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Силует на бюстове"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Момче"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Момиче"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Мъж"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Жена"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Семейство"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Мъж и жена, които се държат за ръце"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Двама мъже, които се държат за ръце"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Две жени, които се държат за ръце"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полицай"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Жена със заешки уши"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Булка с воал"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Човек с руса коса"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Мъж с кепе"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Мъж с тюрбан"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Възрастен мъж"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Възрастна жена"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Бебе"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Строителен работник"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцеса"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Японско чудовище"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Японски таласъм"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Призрак"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Бебе ангел"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Извънземно"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Извънземно чудовище"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Дяволче"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Череп"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Човек на гише за информация"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Гвардеец"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Танцьор"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Червило"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Лак за нокти"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Масаж на лице"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Подстригване"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Знак за бръснарница"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Спринцовка"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Хапче"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Отпечатък от целувка"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Любовно писмо"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Пръстен"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Скъпоценен камък"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Целувка"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Двойка със сърце"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Сватба"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Туптящо сърце"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Разбито сърце"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Две сърца"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Блестящо сърце"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Растящо сърце"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Сърце със стрела"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Синьо сърце"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Зелено сърце"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Жълто сърце"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Лилаво сърце"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Сърце с панделка"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Въртящи се сърца"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Украса със сърца"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Ромбоид с точка по средата"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Електрическа крушка"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Символ за гняв"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Символ за сън"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Символ за удар"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Символ за пръски пот"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Капчица"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Символ за тире"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Купчина изпражнения"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Бицепс"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Символ за замайване"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Балонче с реч"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Балонче с мисъл"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Бяло цвете"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Символ за сто точки"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Чантичка с пари"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Обмяна на валута"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Масивен знак за долар"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Кредитна карта"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Банкнота със знака за йена"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Банкнота със знака за долар"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Банкнота със знака за евро"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Банкнота със знака за лира"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Пари с криле"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Диаграма с възходяща тенденция и знак за йена"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Седалка"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Персонален компютър"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Куфарче"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Минидиск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптичен диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Папка с файлове"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Отворена папка с файлове"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Подвита страница"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Страница, подвита в горната част"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Календар"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Календар с листчета за късане"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Визитник"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Диаграма с възходяща тенденция"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Диаграма с низходяща тенденция"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Стълбовидна диаграма"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Клипборд"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Кабърче"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Кръгло кабърче"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Кламер"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Линия"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Триъгълник за измерване"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Раздели за отметки"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Дневник"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Тетрадка"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Тетрадка с украсена корица"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Затворена книга"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Отворена книга"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Зелена книга"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Синя книга"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Оранжева книга"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Книги"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Значка за име"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Свитък"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Паметна бележка"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефонна слушалка"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пейджър"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Сателитна антена"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Високоговорител"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Мегафон"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Изходяща поща"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Входяща поща"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Пакет"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Символ за имейл"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Входящ плик"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Плик, над който има стрелка надолу"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Затворена пощенска кутия със свален капак"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Затворена пощенска кутия с вдигнат капак"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Отворена пощенска кутия с вдигнат капак"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Отворена пощенска кутия със свален капак"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Пощенска кутия"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Пощенски рог"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Вестник"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобилен телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Мобилен телефон със сочеща надясно стрелка отляво"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Режим на вибриране"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Изключен мобилен телефон"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Забрана за мобилни телефони"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Антена с чертички"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Видеокамера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Телевизия"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Видеокасета"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Усукани надясно стрелки"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Стрелки в отворен кръг, сочещи надясно и наляво по часовниковата посока"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Сочещи надясно и наляво в отворен кръг стрелки по часовниковата посока с едно в кръгче върху тях"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Стрелки в отворен кръг, сочещи надолу и нагоре по часовниковата посока"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Стрелки в отворен кръг, сочещи надолу и нагоре обратно на часовниковата посока"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Символ за ниска яркост"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Символ за висока яркост"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Зачеркнат говорител"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Говорител"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Говорител с една звукова вълна"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Говорител с три звукови вълни"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батерия"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Електрически щепсел"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Сочеща наляво лупа"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Сочеща надясно лупа"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Катинар с писалка"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Заключен катинар с ключ"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ключ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Катинар"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Отворен катинар"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Звънец"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Зачеркнат звънец"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Отметка"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Символ за връзка"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Бутон за избор"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Думата „BACK“, над която има сочеща наляво стрелка"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Думата „END“, над която има сочеща наляво стрелка"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Думата „ON“ с удивителен знак, над които има сочеща наляво стрелка"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Думата „SOON“, над която има сочеща надясно стрелка"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Думата „TOP“, над която има сочеща нагоре стрелка"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Символ за забранено под 18 години"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Бутон 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Символ за въвеждане на главни латински букви"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Символ за въвеждане на малки латински букви"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Символ за въвеждане на числа"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Символ за въвеждане на символи"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Символ за въвеждане на латински букви"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Пожар"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Електрическо фенерче"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Гаечен ключ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Чук"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Гайка и болт"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Японски кухненски нож"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пистолет"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Кристална топка"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Шестолъчка с точка в средата"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Японски символ за начинаещ"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Емблема с тризъбец"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Бутон черно квадратче"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Бутон бяло квадратче"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Голям червен кръг"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Голям син кръг"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Голям оранжев ромб"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Голям син ромб"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Малък оранжев ромб"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Малък син ромб"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Сочещ нагоре червен триъгълник"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Сочещ надолу червен триъгълник"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Сочещ нагоре малък червен триъгълник"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Сочещ надолу малък червен триъгълник"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Часовник, показващ един часа"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Часовник, показващ два часа"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Часовник, показващ три часа"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Часовник, показващ четири часа"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Часовник, показващ пет часа"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Часовник, показващ шест часа"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Часовник, показващ седем часа"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Часовник, показващ осем часа"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Часовник, показващ девет часа"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Часовник, показващ десет часа"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Часовник, показващ единадесет часа"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Часовник, показващ дванадесет часа"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Часовник, показващ един и тридесет"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Часовник, показващ два и тридесет"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Часовник, показващ три и тридесет"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Часовник, показващ четири и тридесет"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Часовник, показващ пет и тридесет"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Часовник, показващ шест и тридесет"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Часовник, показващ седем и тридесет"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Часовник, показващ осем и тридесет"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Часовник, показващ девет и тридесет"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Часовник, показващ десет и тридесет"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Часовник, показващ единадесет и тридесет"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Часовник, показващ дванадесет и тридесет"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Фуджи"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токийската кула"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Статуята на Свободата"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Силует на Япония"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Статуя"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Ухилено лице"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Ухилено лице със засмени очи"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Лице със сълзи от радост"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Усмихнато лице с отворена уста"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Усмихнато лице с отворена уста и засмени очи"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Усмихнато лице с отворена уста и студена пот"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Усмихнато лице с отворена уста и плътно затворени очи"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Усмихнато лице с ореол"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Усмихнато лице с рога"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Намигващо лице"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Усмихнато лице със засмени очи"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Лице, наслаждаващо се на вкусна храна"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Облекчено лице"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Усмихнато лице с очи във формата на сърце"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Усмихнато лице със слънчеви очила"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Самодоволно лице"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Неутрално лице"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Безизразно лице"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Безинтересно лице"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Лице със студена пот"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Замислено лице"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Объркано лице"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Смутено лице"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Целуващо лице"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Лице, изпращащо целувка"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Целуващо лице със засмени очи"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Целуващо лице със затворени очи"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Лице с изплезен език"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Лице с изплезен език и намигащи очи"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Лице с изплезен език и плътно затворени очи"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Разочаровано лице"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Притеснено лице"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Ядосано лице"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Сърдито лице"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Плачещо лице"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Упорито лице"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Лице с триумфален поглед"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Разочаровано, но облекчено лице"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Намръщено лице с отворена уста"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Измъчено лице"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Уплашено лице"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Отегчено лице"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Спящо лице"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Изморено лице"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Правещо гримаса лице"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Ревящо лице"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Лице с отворена уста"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Притихнало лице"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Лице с отворена уста и студена пот"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Лице, крещящо от страх"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Изумено лице"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Изчервено лице"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Спящо лице"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Замаяно лице"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Лице без уста"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Лице с медицинска маска"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Ухилено лице на котка със засмени очи"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Лице на котка със сълзи от радост"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Усмихнато лице на котка с отворена уста"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Усмихнато лице на котка с очи във формата на сърце"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Лице на котка с иронична усмивка"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Целуващо лице на котка със затворени очи"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Сърдито лице на котка"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Плачещо лице на котка"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Отегчено лице на котка"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Неодобряващо лице"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Одобряващо лице"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Покланящ се човек"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Маймунка, която си закрива очите, за да не види нещо лошо"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Маймунка, която си запушва ушите, за да не чуе нещо лошо"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Маймунка, която си запушва устата, за да не каже нещо лошо"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Весел човек, който си вдига едната ръка"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Човек с вдигнати ръце в знак на празнуване"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Човек, който се мръщи"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Човек със сърдито лице"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Човек, който се моли"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Хеликоптер"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Парен локомотив"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Вагон"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Високоскоростен влак"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Високоскоростен влак-стрела"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Влак"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Леко метро"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станция"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвай"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Трамвай"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Насрещен автобус"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Тролейбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобусна спирка"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Микробус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Линейка"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Противопожарна кола"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полицейска кола"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Насрещна полицейска кола"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Насрещно такси"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автомобил"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Насрещен автомобил"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Джип"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Камион за доставки"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Съчленен камион"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Монорелса"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Планинска железница"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Окачена железница"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Планински лифт"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Въздушен трамвай"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Кораб"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Гребна лодка"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Бърза моторна лодка"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Хоризонтален светофар"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Вертикален светофар"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Знак за строеж"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Сигнална лампа на полицейска кола"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Триъгълен флаг"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Врата"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Знак за забранено влизане"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Знак за пушене"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Символ за забранено пушене"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Символ за хвърляне на отпадъците на съответното място"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Символ да не се хвърлят отпадъци"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Символ за питейна вода"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Символ за непитейна вода"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Забранено за велосипеди"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Колоездач"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Планински колоездач"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Пешеходец"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Забранено за пешеходци"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Пресичащи деца"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Символ за мъже"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Символ за жени"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Обществена тоалетна"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Символ за бебета"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Тоалетна"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Тоалетна"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Душ"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Баня"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Вана"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Паспортен контрол"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Митница"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Вземане на багажа"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Съхраняване на багаж"</string>
+</resources>
diff --git a/java/res/values-bg/strings-talkback-descriptions.xml b/java/res/values-bg/strings-talkback-descriptions.xml
index c1271bf..d7c3449 100644
--- a/java/res/values-bg/strings-talkback-descriptions.xml
+++ b/java/res/values-bg/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Няма въведен текст"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"„<xliff:g id="KEY_NAME">%1$s</xliff:g>“ коригира „<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>“ на „<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>“"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"„<xliff:g id="KEY_NAME">%1$s</xliff:g>“ изпълнява автоматично коригиране"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Няма предложение"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Неизвестен знак"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Още символи"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Главна буква I с точка отгоре"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Неизвестен символ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Неизвестен емотикон"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Отегчено лице"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Засрамено лице"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Лице със слънчеви очила"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Изненадано лице"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Целуващо лице"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Намръщено лице"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Налице са алтернативни знаци"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Алтернативните знаци са отхвърлени"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Налице са алтернативни предложения"</string>
diff --git a/java/res/values-bg/strings.xml b/java/res/values-bg/strings.xml
index a2ded38..e5b8f05 100644
--- a/java/res/values-bg/strings.xml
+++ b/java/res/values-bg/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Да вибрира при натискане на клавиш"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натискане на клавиш"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Изскачащ прозорец при натискане на клавиш"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Предпочитания"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Профили и поверителност"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Облик и оформления"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Въвеждане чрез жест"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Коригиране на текст"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Разширени"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Активиране на разделената клавиатура"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Клавиатура на Google: Синхрон."</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхронизирането е включено"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Синхронизиране на личния ви речник на устройствата"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Синхронизиране сега"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Изтриване на данните в облака"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Изтрива синхронизираните ви данни от Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Синхрон. ви данни ще бъдат изтрити от облака. Сигурни ли сте?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Изтриване"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Отказ"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Личният ви речник ще бъде синхронизиран и за него ще бъде създадено резервно копие на сървърите на Google. Статистическата информация за честотата на използване на думите може да се събира с цел подобряване на продуктите ни. Събирането и ползването на всички данни ще бъде съгласно "<a href="https://www.google.com/policies/privacy">"Декларацията ни за поверителност"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"За да активирате функцията, добавете профил в Google към у-вото"</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">"Клавишът за превкл. на езика обхваща и други методи за въвеждане"</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">"Индикатор за плъзгане: Показв."</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Визуална подсказка при плъзгане от „Shift“ или клавиш за символи"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Клавиш за гласово въвеждане"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Няма активирани методи на гласово въвеждане. Проверете настройките за език и въвеждане."</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="language_selection_title" msgid="3666971864764478269">"Езици"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Помощ и отзиви"</string>
+    <string name="select_language" msgid="5709487854987078367">"Езици"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Докоснете отново, за да запазите"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Докоснете тук, за да запазите"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема на клавиатурата"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Превключване между профилите"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Няма избрани профили"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Понастоящем използвате <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ОK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Отказ"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Изход"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Изберете профил, който да използвате"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английски (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английски (САЩ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"испански (САЩ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Сръбска (латиница)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"английски (Великобр.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"английски (САЩ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"испански (САЩ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сръбска (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционна клавиатура)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кирилица)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (компактна)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Без език (латиница)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиница (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиница (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Латиница (Коулмак)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Латиница (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Емотикони"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Тема на клавиатурата"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Персон. стилове за въвежд."</string>
     <string name="add_style" msgid="6163126614514489951">"+ стил"</string>
     <string name="add" msgid="8299699805688017798">"Добавяне"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"Наистина ли да се инсталира този файл за <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Възникна грешка"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Забавяне при продълж. натискане"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Вече можете да пишете във всичките си любими приложения посредством <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">"Показване на иконата на приложението в стартовия панел"</string>
     <string name="app_name" msgid="6320102637491234792">"Доставчик на речника"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Доставчик на речника"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Услуга за речник"</string>
diff --git a/java/res/values-bn-rBD/strings-talkback-descriptions.xml b/java/res/values-bn-rBD/strings-talkback-descriptions.xml
index 7cf17a1..3d3cbfc 100644
--- a/java/res/values-bn-rBD/strings-talkback-descriptions.xml
+++ b/java/res/values-bn-rBD/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"কোনো পাঠ্য লেখা হয়নি"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> কী <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> কে <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> এ সংশোধন করছে"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> স্বত:সংশোধন করে"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"কোনো প্রস্তাবনা নেই"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"অজানা অক্ষর"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"শিফ্ট"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"আরো প্রতীক"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"বড় হাতের I, উপরে বিন্দু"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"অজানা প্রতীক"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"অজানা ইমোজি"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"বিরক্তিকর চেহারা"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"বিব্রত চেহারা"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"সানগ্লাস পরিহিত চেহারা"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"বিস্মিত চেহারা"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"চুম্বনরত চেহারা"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"ভ্রূকুঞ্চিত চেহারা"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"বিকল্প অক্ষরগুলি উপলব্ধ রয়েছে"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"বিকল্প অক্ষরগুলি সরিয়ে দেওয়া হয়"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"বিকল্প প্রস্তাবনাগুলি উপলব্ধ রয়েছে"</string>
diff --git a/java/res/values-bn-rBD/strings.xml b/java/res/values-bn-rBD/strings.xml
index 75bcc6b..de96826 100644
--- a/java/res/values-bn-rBD/strings.xml
+++ b/java/res/values-bn-rBD/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"ইনপুট পছন্দগুলি"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"উপস্থিতি"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"একাধিক ভাষা বিকল্পগুলি"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"অঙ্গভঙ্গি টাইপিং অভিরুচি"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"পছন্দসমূহ"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"অ্যাকাউন্টগুলি ও গোপনীয়তা"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"চেহারা ও লেআউটগুলি"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"অঙ্গভঙ্গি টাইপিং"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"পাঠ্য সংশোধন"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"উন্নত"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"থিম"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"বিভক্ত কীবোর্ড সক্ষম করুন"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google কীবোর্ড সিঙ্ক"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"সিঙ্ক চালু করা হয়েছে"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ডিভাইস জুড়ে আপনার ব্যক্তিগত অভিধান সিঙ্ক করুন"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"এখন সিঙ্ক করুন"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ক্লাউড ডেটা মুছুন"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google থেকে আপনার সিঙ্ক করা ডেটা মুছে ফেলে"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"আপনার সিঙ্ক করা ডেটা ক্লাউড থেকে মুছে ফেলা হবে৷ আপনি কি নিশ্চিত?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"মুছুন"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"বাতিল"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"আপনার ব্যক্তিগত অভিধান Google সার্ভারগুলিতে সিঙ্ক এবং ব্যাকআপ নেওয়া হবে৷ শব্দ ফ্রিকোয়েন্সির পরিসংখ্যানগত তথ্য আমাদের পণ্য উন্নতিতে সহায়তার জন্য সংগ্রহ করা হতে পারে৷ এই সংগ্রহ এবং সমস্ত তথ্যের ব্যবহার "<a href="https://www.google.com/policies/privacy">"Google এর গোপনীয়তা নীতি"</a>"-র সাথে সঙ্গতিশীল হবে৷"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"এই বৈশিষ্ট্যটি সক্ষম করার জন্য অনুগ্রহ করে এই ডিভাইসে একটি Google অ্যাকাউন্ট যোগ করুন"</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">"ভাষা স্যুইচ কীতে অন্যান্য ইনপুট পদ্ধতি পাওয়া যায়"</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">"স্লাইড সূচক দেখান"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"শিফ্ট বা সাংকেতিক চিহ্ন থেকে স্লাইড করার সময় চাক্ষুষ ইঙ্গিত প্রদর্শন"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"ভয়েস ইনপুট কী"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"কোনো ভয়েস ইনপুট পদ্ধতি সক্ষম নয়। ভাষা &amp; ইনপুট সেটিংস পরীক্ষা করুন।"</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="language_selection_title" msgid="3666971864764478269">"ভাষাগুলি"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"সহায়তা এবং প্রতিক্রিয়া"</string>
+    <string name="select_language" msgid="5709487854987078367">"ভাষাগুলি"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"সংরক্ষণ করতে আবার ছোঁন"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"সংরক্ষণ করতে এখানে স্পর্শ করুন"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"অভিধান উপলব্ধ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"কীবোর্ড থিম"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"অ্যাকাউন্ট পাল্টান"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"কোন অ্যাকাউন্ট নির্বাচন করা হয়নি"</string>
+    <string name="account_selected" msgid="2846876462199625974">"বর্তমানে <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> ব্যবহার করা হচ্ছে"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ঠিক আছে"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"বাতিল করুন"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"সাইন আউট"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"ব্যবহার করার জন্য একটি অ্যাকাউন্ট নির্বাচন করুন"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ইংরেজি (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ইংরেজি (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"স্প্যানিশ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"সার্বিয়ান (ল্যাটিন)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ইংরেজি (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ইংরেজি (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"স্প্যানিশ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"সার্বিয়ান (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ঐতিহ্যবাহি)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (সিরিলিক)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ল্যাটিন)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (কম্প্যাক্ট)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"কোনো ভাষা নয় (বর্ণমালা)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"বর্ণমালা (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"বর্ণমালা (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"বর্ণমালা (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ইমোজি"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"কীবোর্ড থিম"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"হলো হোয়াইট"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"হলো ব্লু"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"ম্যাটেরিয়াল ডার্ক"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"ম্যাটেরিয়াল লাইট"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"কাস্টম ইনপুট শৈলীগুলি"</string>
     <string name="add_style" msgid="6163126614514489951">"শৈলী জুড়ুন"</string>
     <string name="add" msgid="8299699805688017798">"জুড়ুন"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"সত্যিই কি <xliff:g id="LANGUAGE_NAME">%s</xliff:g> এর জন্য এই ফাইলটি ইনস্টল করবেন?"</string>
-    <string name="error" msgid="8940763624668513648">"একটি ত্রুটি ছিল"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"কী প্রেসে দীর্ঘ বিলম্ব"</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>
@@ -133,8 +143,8 @@
     <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_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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"এখন <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">"লঞ্চারে অ্যাপ্লিকেশান আইকন প্রদর্শন"</string>
     <string name="app_name" msgid="6320102637491234792">"অভিধান প্রদানকারী"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"অভিধান প্রদানকারী"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"অভিধান পরিষেবা"</string>
diff --git a/java/res/values-ca/strings-emoji-descriptions.xml b/java/res/values-ca/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..0a356f8
--- /dev/null
+++ b/java/res/values-ca/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Signe de drets d\'autor"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Signe de marca registrada"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Signe d\'exclamació doble"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Signe d\'exclamació i d\'interrogació"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Signe de marca comercial"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Punt d\'informació"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Fletxa cap a l\'esquerra i cap a la dreta"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Fletxa cap amunt i cap avall"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Fletxa nord-oest"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Fletxa nord-est"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Fletxa sud-est"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Fletxa sud-oest"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Fletxa cap a l\'esquerra amb ganxo"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Fletxa cap a la dreta amb ganxo"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Rellotge"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Rellotge de sorra"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Triangle negre doble cap a la dreta"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Triangle negre doble cap a l\'esquerra"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Triangle negre doble cap amunt"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Triangle negre doble cap avall"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Rellotge despertador"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Rellotge de sorra amb sorra que cau"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Lletra de l\'alfabet llatí M majúscula encerclada"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Quadrat negre petit"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Quadrat blanc petit"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triangle negre cap a la dreta"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triangle negre cap a l\'esquerra"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Quadrat blanc mitjà"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Quadrat negre mitjà"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Quadrat blanc petit"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Quadrat negre petit"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sol negre amb raigs"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Núvol"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telèfon negre"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Casella amb marca de verificació"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraigües amb les gotes de pluja"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Beguda calenta"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Dit índex que apunta cap amunt"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Cara somrient blanca"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Àries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taure"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Bessons"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Càncer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lleó"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Verge"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Balança"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Escorpió"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagitari"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquari"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Peixos"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Pica negra"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Trèvol negre"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Cor negre"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Diamant negre"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Font termal"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Símbol universal de reciclatge negre"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Símbol de cadira de rodes"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Àncora"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Senyal d\'advertiment"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Senyal d\'alt voltatge"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Cercle blanc mitjà"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Cercle negre mitjà"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Pilota de futbol"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beisbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Ninot de neu"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol darrere d\'un núvol"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Serpentari"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Prohibit el pas"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Església"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Font"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Banderí al forat"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Veler"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tenda de campanya"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Assortidor de gasolina"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Tisores negres"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Marca de verificació blanca gran"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avió"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Sobre"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Puny aixecat"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Mà aixecada"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Senyal de la victòria"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Llapis"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Ploma negra"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Marca de verificació gran"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Signe de multiplicar gran"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Espurnejos"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisc de vuit radis"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Estrella negra de vuit puntes"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Floc de neu"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Espurneig"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Creu"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Creu blanca sobre quadrat negre"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Signe d\'interrogació negre"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Signe d\'interrogació blanc"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Signe d\'exclamació blanc"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Signe d\'exclamació blanc gran"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Cor molt negre"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signe més gran"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signe menys gran"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signe de divisió gran"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Fletxa negra cap a la dreta"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Bucle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Bucle doble"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Fletxa cap a la dreta que es corba cap amunt"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Fletxa cap a la dreta que es corba cap avall"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Fletxa negra cap a l\'esquerra"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Fletxa negra cap amunt"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Fletxa negra cap avall"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Quadrat negre gran"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Quadrat blanc gran"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Estrella blanca mitjana"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Cercle gran"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Guió ondulat"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Signe d\'alternança"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograma circular de felicitació"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograma circular de secret"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Fitxa de Mahjong del drac vermell"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Comodí negre de les cartes"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Tipus de sang A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Tipus de sang B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Tipus de sang O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Aparcament"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Tipus de sang AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Quadre amb el símbol CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Quadre amb la paraula Cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Quadre amb la paraula Free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Quadre amb la paraula ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Quadre amb la paraula New"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Quadre amb el símbol NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Quadre amb la paraula OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Quadre amb la paraula SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Quadre amb un signe d\'exclamació"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Quadre amb el símbol VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Quadre amb l\'ideograma japonès per a \"aquí\""</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Quadre amb l\'ideograma japonès per a \"servei\""</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Quadre amb l\'ideograma de gratuït"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Quadre amb l\'ideograma de seient reservat"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Quadre amb l\'ideograma de prohibició"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Quadre amb l\'ideograma de lliure"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Quadre amb l\'ideograma d\'acceptació"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Quadre amb l\'ideograma d\'ocupació total"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Quadre amb l\'ideograma de pagat"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Quadre amb l\'ideograma de mensual"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Quadre amb l\'ideograma d\'aplicació"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Quadre amb l\'ideograma de descompte"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Quadre amb l\'ideograma de negocis"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Cercle amb l\'ideograma d\'avantatge"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Cercle amb l\'ideograma d\'acceptar"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cicló"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Emboirat"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Paraigües tancat"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Nit amb estrelles"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sortida del sol sobre les muntanyes"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sortida del sol"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Paisatge urbà al vespre"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Posta de sol sobre els edificis"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arc de Sant Martí"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Pont a la nit"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Onada"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcà"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Via Làctia"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globus terraqüi d\'Europa i Àfrica"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globus terraqüi del continent americà"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globus terraqüi d\'Àsia i Austràlia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globus terraqüi amb meridians"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Lluna nova"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Lluna en quart creixent"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Lluna en el primer quart creixent"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Lluna gibosa creixent"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Lluna plena"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Lluna gibosa minvant"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Lluna en l\'últim quart minvant"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Lluna minvant"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Lluna creixent"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Lluna nova amb cara"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Lluna creixent amb cara"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Lluna minvant amb cara"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Lluna plena amb cara"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol amb cara"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Estrella que brilla"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Estrella fugaç"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Castanya"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Planta de planter"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Arbre de fulla perenne"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Arbre de fulla caduca"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmera"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipa"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Flor de cirerer"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisc"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Gira-sol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Flor"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Panotxa de blat de moro"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Espiga d\'arròs"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herba"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trèvol de quatre fulles"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Fulla d\'auró"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Fulla caiguda"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Fulla que vola amb el vent"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Bolet"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomàquet"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Albergínia"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Raïm"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Meló"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Síndria"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Llimona"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Plàtan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Pinya"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Poma vermella"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Poma verda"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Préssec"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cireres"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Maduixa"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburguesa"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Porció de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Carn amb l\'os"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Cuixa de pollastre"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galeta d\'arròs"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Bola d\'arròs"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arròs bullit"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Arròs amb curri"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Plat fumejant"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Espagueti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pa"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patates fregides"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Moniato rostit"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Gamba fregida"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Pastís de peix amb forma de remolí"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Gelat de màquina"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Granissat"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Gelat"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Rosquilla"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Galeta"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Rajola de xocolata"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Caramel"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Pirulí"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Flam"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Pot de mel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Porció de pastís"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Caixa de bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Plat de menjar"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Fent un ou ferrat"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Forquilla i ganivet"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tassa de te sense nansa"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Ampolla de sake i got"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Copa de vi"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Còctel"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Beguda tropical"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Gerra de cervesa"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Brindis amb gerres de cervesa"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberó"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Llaç"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Regal embolicat"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Pastís d\'aniversari"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Carabassa de Halloween"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Arbre de Nadal"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Pare Noel"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Focs artificials"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Bengala"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Globus"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Tub de confeti"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Bola de confeti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Arbre dels desitjos de Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Banderes creuades"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Decoració de bambú"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Nines japoneses"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Banderins de carpes"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Mòbil sonor"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Cerimònia de contemplació de la lluna"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Motxilla de l\'escola"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Birret de la graduació"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cavall dels cavallets"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Sínia de fira"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Muntanya russa"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Canya de pescar i peix"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Micròfon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Càmera de cinema"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Auricular"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta de l\'artista"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Barret de copa"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Vela de circ"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Entrada"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Claqueta"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Arts escèniques"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videojoc"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Diana"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Escurabutxaques"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dau"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bitlles"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Cartes de les flors"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota musical"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Diverses notes musicals"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxòfon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Teclat musical"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violí"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitura"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Samarreta per córrer amb banda"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raqueta de tennis i pilota"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Esquí"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Bàsquet"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandera a quadres"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Surfista de neu"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Corredor"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfista"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofeu"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Curses de cavalls"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Futbol americà"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nedador"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Casa"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa amb jardí"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Edifici d\'oficines"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Oficina de correus japonesa"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Oficina de correus europea"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banc"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Caixer automàtic"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel de cites"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Botiga local"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Escola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Grans magatzems"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fàbrica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Llum d\'izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Castell japonès"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castell europeu"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rata"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Ratolí"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Bou"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Búfal indi"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vaca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Lleopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Conill"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drac"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Cocodril"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balena"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Caragol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serp"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cavall"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Moltó"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Cabra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovella"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Mona"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gall"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Gallina"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Gos"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Porc"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Porc senglar"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pop"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Cargol de mar"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insecte"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Formiga"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abella"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Marieta"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Peix"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Peix tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Peix globus"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tortuga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pollet sortint de l\'ou"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pollet"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pollet de cara"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ocell"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingüí"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Coala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedari"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Camell"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dofí"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Cara de ratolí"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cara de vaca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Cara de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Cara de conill"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cara de gat"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Cara de drac"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Balena que treu aigua"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Cara de cavall"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Cara de mona"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Cara de gos"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cara de porc"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Cara de granota"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Cara d\'hàmster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Cara de llop"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Cara d\'ós"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Cara d\'ós panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nas de porc"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Petjades d\'animal"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ulls"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Orella"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nas"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Boca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Llengua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Dit índex que apunta cap amunt"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Dit índex que apunta cap avall"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Dit índex que apunta cap a l\'esquerra"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Dit índex que apunta cap a la dreta"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Puny"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Mà que saluda"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Signe d\'OK amb la mà"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Signe de m\'agrada"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Signe de no m\'agrada"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Mans aplaudint"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Mans obertes"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Corona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Barret de dona"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Ulleres"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Corbata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Samarreta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Texans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Vestit"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Quimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Biquini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Camisa de dona"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Moneder"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Bossa de mà"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Estoig"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Sabata d\'home"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sabatilla esportiva"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Sabata de taló alt"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandàlia de dona"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Botes de dona"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Petjades"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta de bust"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silueta de bustos"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Noi"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Noia"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Home"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Dona"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Família"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Home i dona agafats de la mà"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dos homes agafats de la mà"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dues dones agafades de la mà"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Agent de policia"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Dona amb orelles de conill"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Núvia amb vel"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persona rossa"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Home amb barret típic"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Home amb turbant"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Home gran"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Dona gran"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Nadó"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Treballador de la construcció"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogre japonès"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Follet japonès"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Angelet"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Alienígena"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Invasor de l\'espai"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Dimoniet"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Calavera"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Recepcionista"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guàrdia"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Ballarina"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Pintallavis"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Pintaungles"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Massatge facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Tall de cabell"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barberia"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Xeringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Píndola"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Marca de petó"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Carta d\'amor"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anell"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Gemma"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Petó"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Ram"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Parella amb cor"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Casament"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Cor que batega"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Cor trencat"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dos cors"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Cor espurnejant"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Cor que creix"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Cor amb una fletxa"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Cor blau"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Cor verd"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Cor groc"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Cor porpra"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Cor amb un llaç"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Cors que giren"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Decoració de cor"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Forma de diamant amb un punt a l\'interior"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Bombeta"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Signe de la ira"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Signe de dormir"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Signe de col·lisió"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Esquitx de suor"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Gota"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Signe de córrer"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Caca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bíceps flexionat"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Signe de mareig"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bafarada de parlar"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bafarada de pensar"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Flor blanca"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Signe d\'excel·lent"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Bossa dels diners"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Canvi de divisa"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Signe del dòlar gran"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Targeta de crèdit"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bitllets amb el signe del ien"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Bitllets amb el signe del dòlar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bitllets amb el signe de l\'euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bitllets amb el signe de la lliura"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Diners amb ales"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Gràfic d\'increment amb el signe del ien"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Seient"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Ordinador"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Maletí"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquet"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disc òptic"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Carpeta d\'arxius"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Carpeta de fitxer oberta"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Pàgina que es cargola"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Pàgina cap amunt"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendari"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendari de tall"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Organitzador de targetes"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Gràfic d\'increment"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Gràfic de disminució"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Gràfic de barres"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Portanotes"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Xinxeta"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Xinxeta rodona"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Clip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Regle"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Escaire"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Marcadors"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Llibre major"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Quadern"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Quadern amb coberta decorativa"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Llibre tancat"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Llibre obert"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Llibre verd"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Llibre blau"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Llibre taronja"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Llibres"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Etiqueta identificativa"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Desplaça"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Nota"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Auricular del telèfon"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Cercapersones"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena de satèl·lit"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Altaveu de megafonia"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megàfon d\'animació"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Safata de sortida"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Safata d\'entrada"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paquet"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Símbol de correu electrònic"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Correu entrant"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Sobre amb una fletxa cap avall al damunt"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Bústia tancada amb la bandera baixada"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Bústia tancada amb la bandera aixecada"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Bústia oberta amb la bandera aixecada"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Bústia oberta amb la bandera baixada"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Bústia"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Símbol de correus"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Diari"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Telèfon mòbil"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Telèfon mòbil amb una fletxa cap a la dreta a l\'esquerra"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Mode de vibració"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Telèfon mòbil apagat"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Senyal de prohibit telèfons mòbils"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Gràfic de barres"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Càmera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Càmera de vídeo"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisió"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Ràdio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Cinta de vídeo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Fletxes creuades cap a la dreta"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Fletxes cap a la dreta i l\'esquerra que formen un cercle obert en sentit horari"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Fletxes cap a la dreta i l\'esquerra que formen un cercle obert en sentit horari i un número u encerclat"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Fletxes cap avall i cap amunt que formen un cercle obert en sentit horari"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Fletxes cap avall i cap amunt que formen un cercle obert en sentit antihorari"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Símbol de brillantor baixa"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Símbol de brillantor alta"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altaveu amb barra de cancel·lació"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altaveu"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altaveu amb una ona de so"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altaveu amb tres ones de so"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Bateria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Endoll elèctric"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa cap a l\'esquerra"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa cap a la dreta"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Cadenat amb ploma"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Cadenat amb clau"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Clau"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Cadenat tancat"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Cadenat obert"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Campana"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Campana amb barra de cancel·lació"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Marcador"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Signe d\'enllaç"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Botó d\'opció"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Paraula Back amb fletxa cap a l\'esquerra a sobre"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Paraula End amb fletxa cap a l\'esquerra a sobre"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Paraula On amb fletxa cap a l\'esquerra i la dreta a sobre"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Paraula Soon amb fletxa cap a la dreta a sobre"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Paraula Top amb fletxa cap amunt a sobre"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Prohibit per a menors de 18 anys"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tecla 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Tecla per introduir majúscules de l\'alfabet llatí"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Tecla per introduir minúscules de l\'alfabet llatí"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Tecla per introduir nombres"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Símbol d\'entrada per a símbols"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Tecla per introduir lletres de l\'alfabet llatí"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Foc"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Llanterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Clau anglesa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martell"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Femella i cargol"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Ganivet per cuinar"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscopi"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescopi"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bola de vidre"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Estrella de sis puntes amb un punt central"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Símbol japonès per a principiants"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trident"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botó negre quadrat"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botó blanc quadrat"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Cercle vermell gran"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Cercle blau gran"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Rombe taronja gran"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Rombe taronja blau"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Rombe taronja petit"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Rombe blau petit"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triangle vermell cap amunt"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triangle vermell cap avall"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triangle vermell petit cap amunt"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triangle vermell petit cap avall"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Rellotge que marca la una"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Rellotge que marca les dues"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Rellotge que marca les tres"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Rellotge que marca les quatre"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Rellotge que marca les cinc"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Rellotge que marca les sis"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Rellotge que marca les set"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Rellotge que marca les vuit"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Rellotge que marca les nou"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Rellotge que marca les deu"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Rellotge que marca les onze"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Rellotge que marca les dotze"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Rellotge que marca dos quarts de dues"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Rellotge que marca dos quarts de tres"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Rellotge que marca dos quarts de quatre"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Rellotge que marca dos quarts de cinc"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Rellotge que marca dos quarts de sis"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Rellotge que marca dos quarts de set"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Rellotge que marca dos quarts de vuit"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Rellotge que marca dos quarts de nou"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Rellotge que marca dos quarts de deu"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Rellotge que marca dos quarts d\'onze"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Rellotge que marca dos quarts de dotze"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Rellotge que marca dos quarts d\'una"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mont Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Torre de Tòquio"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Estàtua de la Llibertat"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silueta del Japó"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Cara somrient"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Cara amb somriure i ulls somrients"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Cara amb llàgrimes d\'alegria"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Cara somrient amb la boca oberta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Cara somrient amb la boca oberta i els ulls contents"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Cara somrient amb la boca oberta i la suor freda"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Cara somrient amb la boca oberta i els ulls tancats fortament"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Cara somrient amb halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Cara somrient amb banyes"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Cara picant l\'ullet"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Cara somrient amb els ulls contents"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Cara d\'assaborir un menjar deliciós"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Cara d\'alleujament"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Cara somrient amb els ulls en forma de cor"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Cara somrient amb ulleres de sol"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Somriure amb superioritat"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Cara neutral"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Cara inexpressiva"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Cara de desaprovació"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Cara amb suor freda"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Cara pensativa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Cara de confusió"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Cara de frustració"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Cara que fa un petó"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Cara llançant un petó"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Cara que fa un petó amb els ulls contents"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Cara que fa un petó amb els ulls tancats"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Cara que treu la llengua"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Cara que treu la llengua i pica l\'ullet"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Cara que treu la llengua i tanca fortament els ulls"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Cara de decepció"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Cara de preocupació"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Cara enutjada"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Cara molt enutjada"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Cara que plora"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Cara de perseverança"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Cara amb expressió de triomf"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Cara de decepció, però alleujada"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Cara emmurriada amb la boca oberta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Cara angoixada"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Cara de por"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Cara d\'esgotament"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Cara de son"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Cara de cansament"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Ganyota amb les dents"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Cara que plora desconsoladament"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Cara amb la boca oberta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Cara de silenci"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Cara amb la boca oberta i la suor freda"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Cara que crida de por"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Cara de sorpresa"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Cara enrogida"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Cara adormida"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Cara marejada"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Cara sense boca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Cara amb màscara"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Cara de gat amb somriure i ulls somrients"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cara de gat amb llàgrimes d\'alegria"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Cara de gat somrient amb la boca oberta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Cara de gat somrient amb els ulls en forma de cor"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cara de gat amb somriure irònic"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Cara de gat que fa un petó amb els ulls tancats"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Cara de gat molt enutjada"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Cara de gat que plora"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Cara de gat esgotada"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Cara sense expressió"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Cara amb expressió d\'acceptació"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persona que mostra un agraïment profund"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Mona que no veu"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Mona que no escolta"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Mona que no parla"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Persona feliç que aixeca una mà"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Dues mans aixecades a manera de celebració"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persona emmurriada"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persona amb cara d\'enuig"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persona amb les mans creuades"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Coet"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicòpter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotora de vapor"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagó de ferrocarril"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tren d\'alta velocitat"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Tren bala"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tren lleuger"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Estació"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvia"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagó de tramvia"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobús"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Bus que arriba"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Troleibús"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Parada d\'autobús"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Microbús"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulància"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camió de bombers"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Cotxe de policia"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Cotxe de policia que arriba"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi que arriba"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automòbil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automòbil que arriba"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Vehicle d\'ús recreatiu"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camió de repartiment"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camió articulat"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monocarril"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ferrocarril de muntanya"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Ferrocarril de suspensió"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Telefèric de muntanya"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Tramvia aeri"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Vaixell"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Bot de rems"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Llanxa"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semàfor horitzontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semàfor vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Senyal de construcció"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Llum giratòria dels cotxes de policia"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Banderí triangular"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Senyal de prohibida l\'entrada"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Senyal de es permet fumar"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Senyal de prohibit fumar"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Senyal de llençar la brossa on toca"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Senyal de no llençar escombraries"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Senyal d\'aigua potable"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Senyal d\'aigua no potable"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Prohibit per a bicicletes"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista de muntanya"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Vianant"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Prohibit per a vianants"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Nens que creuen"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Símbol d\'home"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Símbol de dona"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Lavabos"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Símbol de nadó"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Vàter"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Lavabo"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dutxa"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bany"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Banyera"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Control de passaport"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Duana"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Recollida d\'equipatges"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Consigna"</string>
+</resources>
diff --git a/java/res/values-ca/strings-talkback-descriptions.xml b/java/res/values-ca/strings-talkback-descriptions.xml
index 9b01c75..625afb7 100644
--- a/java/res/values-ca/strings-talkback-descriptions.xml
+++ b/java/res/values-ca/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"No s\'ha introduït cap text."</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corregeix <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> per <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> executa la correcció automàtica."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No hi ha cap suggeriment"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caràcter desconegut"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Maj"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Més símbols"</string>
@@ -57,7 +58,7 @@
     <string name="announce_keyboard_mode" msgid="6698257917367823205">"Es mostra el teclat per a <xliff:g id="KEYBOARD_MODE">%s</xliff:g>."</string>
     <string name="keyboard_mode_date" msgid="6597407244976713364">"data"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"data i hora"</string>
-    <string name="keyboard_mode_email" msgid="1239682082047693644">"correu electrònic"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"adreça electrònica"</string>
     <string name="keyboard_mode_im" msgid="3812086215529493501">"missatgeria"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"número"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"telèfon"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majúscula, punt superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbol desconegut"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconegut"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara d\'avorriment"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara de vergonya"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara amb ulleres de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara de sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara que fa un petó"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara que arrufa el nas"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Hi ha caràcters alternatius disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Els caràcters alternatius s\'ignoren."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Hi ha suggeriments alternatius disponibles."</string>
diff --git a/java/res/values-ca/strings.xml b/java/res/values-ca/strings.xml
index 80d2987..d1c58b2 100644
--- a/java/res/values-ca/strings.xml
+++ b/java/res/values-ca/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibra en prémer tecles"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"So en prémer tecles"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Amplia en prémer tecles"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferències"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Comptes i privadesa"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aparença i disseny"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escriptura gestual"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Correcció de textos"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avançat"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Activa el teclat partit"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronitz. del Teclat de Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"La sincronització està activada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronitza el diccionari personal als dispositius"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronitza ara"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Suprimeix les dades del núvol"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Suprimeix les dades sincronitzades de Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Les teves dades sincronitzades se suprimiran del núvol. Vols continuar?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Suprimeix"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancel·la"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"El teu diccionari personal se sincronitzarà i se\'n farà una còpia de seguretat als servidors de Google. És possible que es recopili informació estadística sobre la freqüència de les paraules per poder millorar els nostres productes. La recopilació i l\'ús de tota la informació complirà la "<a href="https://www.google.com/policies/privacy">"Política de privadesa de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Afegeix un compte de Google al dispositiu per activar la funció"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Altres mètodes d\'introducció"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de canvi d\'idioma serveix també per a altres mètodes d\'entrada"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla de canvi d\'idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostra-la quan hi hagi diversos idiomes d\'introducció activats"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostra l\'indicador per lliscar"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostra la indicació visual en lliscar des de la tecla Maj o Símbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retard en ampliar tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sense retard"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminat"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionari principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Suggeriments de correcció"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Mostra paraules suggerides mentre s\'escriu"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostra en mode vertical"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Amaga sempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloqueja paraules ofensives"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"No suggereixis paraules potencialment ofensives"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correcció automàtica"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tecla d\'entrada de veu"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No hi ha cap mètode d\'introducció activat. Comprova la configuració d\'Idioma i introducció de text."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomes"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envia comentaris"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomes d\'introducció"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomes"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda i suggeriments"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomes"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí per desar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclat"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Canvi de compte"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"No hi ha cap compte seleccionat."</string>
+    <string name="account_selected" msgid="2846876462199625974">"Actualment es fa servir <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>."</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"D\'acord"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancel·la"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Tanca la sessió"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecció d\'un compte per utilitzar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglès (Regne Unit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglès (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espanyol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbi (llatí)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Anglès (Regne Unit) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Anglès (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanyol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbi (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ciríl·lic)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (llatí)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacte)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Cap idioma (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,18 +121,9 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema del teclat"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estils d\'entrada personalitzats"</string>
-    <string name="add_style" msgid="6163126614514489951">"Afeg. estil"</string>
+    <string name="add_style" msgid="6163126614514489951">"Afegeix estil"</string>
     <string name="add" msgid="8299699805688017798">"Afegeix"</string>
     <string name="remove" msgid="4486081658752944606">"Elimina"</string>
     <string name="save" msgid="7646738597196767214">"Desa"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activa"</string>
     <string name="not_now" msgid="6172462888202790482">"Ara no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ja existeix aquest estil d\'entrada: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retard en mantenir premut"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durada vibració en prémer"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volum del so en prémer tecles"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lectura d\'un fitxer de diccionari extern"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hi ha cap fitxer de diccionari a la carpeta Baixades"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecció d\'un fitxer de diccionari per instal·lar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Realment vols instal·lar aquest fitxer per a <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"S\'ha produït un error"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retard en mantenir premut"</string>
     <string name="button_default" msgid="3988017840431881491">"Predeterminat"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Et donem la benvinguda a <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"amb Escriptura gestual"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Ara ja pots escriure en totes les teves aplicacions preferides amb <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configura altres idiomes"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Finalitzat"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostra la icona de l\'aplicació"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostra la icona de l\'aplicació al menú d\'aplicacions"</string>
     <string name="app_name" msgid="6320102637491234792">"Proveïdor de diccionaris"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveïdor de diccionaris"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Servei de diccionari"</string>
diff --git a/java/res/values-cs/strings-action-keys.xml b/java/res/values-cs/strings-action-keys.xml
index c398032..a220ee7 100644
--- a/java/res/values-cs/strings-action-keys.xml
+++ b/java/res/values-cs/strings-action-keys.xml
@@ -23,7 +23,7 @@
     <string name="label_go_key" msgid="4033615332628671065">"Jít"</string>
     <string name="label_next_key" msgid="5586407279258592635">"Další"</string>
     <string name="label_previous_key" msgid="1421141755779895275">"Před."</string>
-    <string name="label_done_key" msgid="7564866296502630852">"Hot."</string>
+    <string name="label_done_key" msgid="7564866296502630852">"OK"</string>
     <string name="label_send_key" msgid="482252074224462163">"Odes."</string>
     <string name="label_search_key" msgid="7965186050435796642">"Hledat"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pauza"</string>
diff --git a/java/res/values-cs/strings-emoji-descriptions.xml b/java/res/values-cs/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..b7f359c
--- /dev/null
+++ b/java/res/values-cs/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Znak copyrightu"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Symbol registrované ochranné známky"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dvojitý vykřičník"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Vykřičník a otazník"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Symbol ochranné známky"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Zdroj informací"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Šipka vlevo a vpravo"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Šipka nahoru a dolů"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Šipka na severozápad"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Šipka na severovýchod"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Šipka na jihovýchod"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Šipka na jihozápad"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Šipka vlevo s háčkem"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Šipka vpravo s háčkem"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Hodinky"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Přesýpací hodiny"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Černý dvojitý trojúhelník směřující vpravo"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Černý dvojitý trojúhelník směřující vlevo"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Černý dvojitý trojúhelník směřující nahoru"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Černý dvojitý trojúhelník směřující dolů"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Budík"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Přesýpací hodiny se sypajícím se pískem"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Velké písmeno latinky M v kroužku"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Malý černý čtverec"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Malý bílý čtverec"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Černý trojúhelník směřující vpravo"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Černý trojúhelník směřující vlevo"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Bílý střední čtverec"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Černý střední čtverec"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Bílý střední malý čtverec"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Černý střední malý čtverec"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Černé slunce s paprsky"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Mrak"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Černý telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Hlasovací políčko se zatržením"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Deštník s kapkami deště"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Horký nápoj"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Bílý nahoru ukazující ukazatel"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Bílý usmívající se obličej"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Beran"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Býk"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Blíženci"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rak"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lev"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Panna"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Váhy"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Štír"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Střelec"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Kozoroh"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vodnář"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ryby"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Černé piky"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Černé kříže"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Černá srdce"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Černé káry"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Horký pramen"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Černý univerzální symbol recyklace"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Symbol vozíčku pro tělesně postižené"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Kotva"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Výstražný symbol"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Značka vysokého napětí"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Střední bílý kroužek"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Střední černý kroužek"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Fotbalový míč"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Sněhulák beze sněhu"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Slunce za mrakem"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Hadonoš"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Zákaz vstupu"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kostel"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Kašna"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Praporek v jamce"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Jachta"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Stan"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Čerpací stanice"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Černé nůžky"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Bílé tučné zatržítko"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Letadlo"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Obálka"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Zvednutá pěst"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Zvednutá ruka"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Vítězné gesto"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Tužka"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Černý hrot psacího pera"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Tučné zatržítko"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Tučný diagonální křížek"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Jiskry"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Osmicípá hvězda"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Černá osmicípá hvězda"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Sněhová vločka"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Jiskra"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Křížek"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negativní hranatý křížek"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Černý ornamentální otazník"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Bílý ornamentální otazník"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Bílý ornamentální vykřičník"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Tučný vykřičník"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Tučné černé srdce"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Tučné znaménko plus"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Tučné znaménko minus"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Tučné znaménko dělení"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Černá šipka vpravo"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Smyčka"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dvojitá smyčka"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Šipka směřující vpravo a potom zahnutá nahoru"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Šipka směřující vpravo a potom zahnutá dolů"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Černá šipka směřující doleva"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Černá šipka směřující nahoru"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Černá šipka směřující dolů"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Černý velký čtverec"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Bílý velký čtverec"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Bílá střední hvězda"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Tučný velký kruh"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Vlnitá pomlčka"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Znak výměny části"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Znak Blahopřání v kroužku"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Znak Tajný v kroužku"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Kostka Mahjong s červeným drakem"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Hrací karta s černým žolíkem"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Krevní skupina A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Krevní skupina B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Krevní skupina O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkoviště"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Krevní skupina AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Hranatý symbol CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Hranatý symbol COOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Hranatý symbol FREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Hranatý symbol ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Hranatý symbol NEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Hranatý symbol NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Hranatý symbol OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Hranatý symbol SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Hranatý symbol UP s vykřičníkem"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Hranatý symbol VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Hranatá katakana koko"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Hranatá katakana sa"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Hranatý znak Zdarma"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Hranatý znak Vyhrazené sedadlo"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Hranatý znak Zákaz"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Hranatý znak Volné místo"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Hranatý znak Převzetí"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Hranatý znak Plně obsazeno"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Hranatý znak Zaplaceno"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Hranatý znak Měsíčně"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Hranatý znak Žádost"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Hranatý znak Sleva"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Hranatý znak V provozu"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Znak Výhoda v kroužku"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Znak Přijímám v kroužku"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyklón"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Mlha"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Zavřený deštník"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Hvězdná noc"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Východ slunce nad horami"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Východ slunce"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Silueta města za soumraku"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Západ slunce nad budovami"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Duha"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Most v noci"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vodní vlna"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Sopka"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Mléčná dráha"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Zeměkoule – Evropa a Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Zeměkoule – Severní a Jižní Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Zeměkoule – Asie a Austrálie"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Zeměkoule s poledníky"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbol novoluní"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbol dorůstajícího srpku měsíce"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbol měsíce v první čtvrti"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbol dorůstajícího měsíce"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbol úplňku"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbol couvajícího měsíce"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbol měsíce v poslední čtvrti"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbol couvajícího srpku měsíce"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Půlměsíc"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Novoluní s obličejem"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Měsíc v první čtvrti s obličejem"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Měsíc v poslední čtvrti s obličejem"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Úplněk s obličejem"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Slunce s obličejem"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Zářící hvězda"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Padající hvězda"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kaštan"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Sazenička"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Jehličnatý strom"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Listnatý strom"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kvetoucí třešeň"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Růže"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Ibišek"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Slunečnice"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Květ"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kukuřice"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Rýže"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Bylina"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Čtyřlístek"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Javorový list"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Spadlý list"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"List poletující ve větru"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Houba"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Rajče"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Lilek"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Hrozny"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Meloun"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Vodní meloun"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarinka"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citrón"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banán"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Červené jablko"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zelené jablko"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Hruška"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Broskev"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Třešně"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jahoda"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Plátek pizzy"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Maso na kosti"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Drůbeží stehno"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rýžový krekr"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Kopeček rýže"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Vařená rýže"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Kari s rýží"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Kouřící mísa"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Špagety"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Chléb"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Hranolky"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pečená brambora"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Suši"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Smažený garnát"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Rybí karbanátek se spirálou"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Zmrzlina v kornoutu"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Porcovaná zmrzlina"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Zmrzlina"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Kobliha"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Sušenka"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Tabulka čokolády"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bonbon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Pudink"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Hrnek medu"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Dort"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Krabička na jídlo"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Hrnec jídla"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Vaření"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Vidlička a nůž"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Šálek bez ouška"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Láhev saké a šálek"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Sklenka na víno"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Sklenka na koktejl"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropický drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Půllitr piva"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Cinkající půllitry piva"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Dětská láhev"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Stuha"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Zabalený dárek"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Narozeninový dort"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Lucerna z dýně"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Vánoční stromeček"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Santa Klaus"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Ohňostroj"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Prskavka"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balónek"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Vystřelovač konfet"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfety"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Strom Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Zkřížené vlajky"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Dekorace z borovicových větviček"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japonské panenky"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Vlajka s kaprem"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Větrná zvonkohra"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Oslava sklizně"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Školní brašna"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Absolventská čapka"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Kolotočový kůň"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ruské kolo"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Horská dráha"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Rybářský prut a ryba"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Promítačka"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Sluchátka"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Malířská paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cylindr"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkusový stan"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Vstupenka"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Filmařská klapka"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Múzická umění"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videohra"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Přímý zásah"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Herní automat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Kulečník"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Hrací kostka"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Květinové hrací karty"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Hudební nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Několik hudebních not"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Kytara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klaviatura"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trumpeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Housle"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Hudební osnova"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Běžecké triko s šerpou"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tenisová raketa a míček"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Lyže a lyžařská bota"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbalový míč a obruč"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Kostkovaná vlajka"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboardista"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Běžec"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfař"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofej"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Dostihy"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Americký fotbal"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Plavec"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Dům"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Dům se zahradou"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kancelářská budova"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japonská poštovní schránka"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Evropská poštovní schránka"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Nemocnice"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hodinový hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Večerka"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Škola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Obchodní dům"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Továrna"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Japonská lucerna"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japonský hrad"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Evropský hrad"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Krysa"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Myš"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Vůl"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vodní buvol"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Kráva"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Králík"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kočka"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drak"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodýl"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Velryba"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Hlemýžď"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Had"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Kůň"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Beran"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Koza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovce"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Opice"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Kohout"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kuře"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Pes"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Prase"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Divočák"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Slon"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Chobotnice"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Ulita"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Brouk"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mravenec"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Včela"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Beruška"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Ryba"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropická ryba"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Ježík"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Želva"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Vylíhnuté kuře"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kuřátko"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kuřátko zepředu"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Pták"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Tučňák"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudl"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Jednohrbý velbloud"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Dvouhrbý velbloud"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfín"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Hlava myši"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Hlava krávy"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Hlava tygra"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Hlava králíka"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Hlava kočky"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Hlava draka"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Tryskající velryba"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Hlava koně"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Hlava opice"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hlava psa"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Hlava prasete"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Hlava žáby"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hlava křečka"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Hlava vlka"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Hlava medvěda"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Hlava pandy"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Prasečí rypák"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Otisky tlap"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oči"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ucho"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nos"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ústa"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Jazyk"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Bílý ukazováček směřující nahoru"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Bílý ukazováček směřující dolů"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Bílý ukazováček směřující doleva"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Bílý ukazováček směřující doprava"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Symbol zaťaté pěsti"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Symbol mávající ruky"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Symbol ruky ukazující, že je vše v pořádku"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Symbol palce nahoru"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Symbol palce dolů"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Symbol tleskajících dlaní"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Symbol otevřených rukou"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Koruna"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Dámský klobouk"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Brýle"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kravata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Tričko"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Džíny"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Šaty"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikiny"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Dámské oblečení"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Peněženka"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Kabelka"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Tobolka"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Pánská obuv"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportovní obuv"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Bota na podpatku"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Dámské sandály"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Dámské kozačky"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Šlépěje"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta postavy"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Siluety postav"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Chlapec"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Dívka"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Muž"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Žena"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Rodina"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Muž a žena držící se za ruce"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dva muži držící se za ruce"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dvě ženy držící se za ruce"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policista"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Žena s králičíma ušima"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Nevěsta se závojem"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Osoba se světlými vlasy"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Muž s knírem"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Muž s turbanem"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Starší muž"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Starší žena"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Dítě"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Stavební dělník"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princezna"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japonský strašák"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japonský skřet"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Duch"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Andílek"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Mimozemšťan"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Příšera"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Rarášek"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Lebka"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Osoba u informační přepážky"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Strážce"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Tanečník"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rtěnka"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Lak na nehty"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masáž obličeje"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Stříhání vlasů"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Kadeřnický poutač"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Injekční stříkačka"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilulka"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Symbol polibku"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Milostný dopis"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Prsten"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Drahokam"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Polibek"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Kytice"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Dvojice se srdcem"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Svatba"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Tlukoucí srdce"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Zlomené srdce"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dvě srdce"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Jiskřivé srdce"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Zvětšující se srdce"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Srdce zasažené šípem"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Modré srdce"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zelené srdce"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Žluté srdce"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Nachové srdce"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Srdce se stužkou"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Rotující srdce"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Dekorace se srdcem"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Kosočtverec s bodem uvnitř"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Žárovka"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbol hněvu"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbol spánku"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbol střetu"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbol řinoucího se potu"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Kapka"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbol spěchu"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Hromádka bobků"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Napnutý biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbol závratě"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bublina s řečí"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bublina s myšlenkami"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Bílá květina"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbol stovky bodů"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Měšec na peníze"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Převod měn"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Tučný symbol dolaru"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Platební karta"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bankovka se symbolem jenu"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Bankovka se symbolem dolaru"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bankovka se symbolem eura"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bankovka se symbolem libry"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Okřídlené peníze"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Graf s vzestupnou tendencí a symbolem jenu"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sedadlo"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Osobní počítač"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktovka"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketa"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optický disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Složka souborů"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Otevřená složka"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Ohnutá stránka"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Stránka lícem nahoru"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendář"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Trhací kalendář"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Pořadač"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Graf se vzestupnou tendencí"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Graf s klesající tendencí"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Pruhový graf"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Schránka"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Špendlík"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Kulatý špendlík"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Kancelářská sponka"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Rovné pravítko"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trojúhelníkové pravítko"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Štítky záložek"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Účetní kniha"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Poznámkový blok"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Poznámkový blok s dekorativním obalem"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Zavřená kniha"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Otevřená kniha"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zelená kniha"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Modrá kniha"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranžová kniha"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Knihy"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Jmenovka"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Svitek"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Poznámka"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonní sluchátko"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelitní anténa"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Tlampač"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Hlasitý megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Přihrádka pro poštu k odeslání"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Přihrádka pro doručenou poštu"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Balíček"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Symbol e-mailu"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Příchozí obálka"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Obálka, nad kterou je šipka dolů"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Zavřená poštovní schránka se sklopeným praporkem"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Zavřená poštovní schránka se vztyčeným praporkem"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Otevřená poštovní schránka se vztyčeným praporkem"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Otevřená poštovní schránka se sklopeným praporkem"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Poštovní schránka"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Poštovní roh"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Noviny"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobilní telefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobilní telefon, který má po levé straně šipku vpravo"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrační režim"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Vypnutý mobilní telefon"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Zákaz mobilních telefonů"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Anténa se stupnicí"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoaparát"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televize"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Rádio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokazeta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Zkroucené šipky vpravo"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Šipky vpravo a vlevo v otevřeném kruhu ve směru hodinových ručiček"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Šipky vpravo a vlevo v otevřeném kruhu ve směru hodinových ručiček s číslem 1 v kruhu"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Šipky dolů a nahoru v otevřeném kruhu ve směru hodinových ručiček"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Šipky vpravo a vlevo v otevřeném kruhu proti směru hodinových ručiček"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol nízkého jasu"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol vysokého jasu"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Přeškrtnutý reproduktor"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Reproduktor"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Reproduktor s jednou zvukovou vlnou"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Reproduktor se dvěma zvukovými vlnami"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Baterie"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektrická zástrčka"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa směřující doleva"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa směřující doprava"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Zámek s inkoustovým perem"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Zavřený zámek s klíčem"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Klíč"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Zámek"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Otevřený zámek"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zvonek"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Přeškrtnutý zvonek"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Záložka"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Symbol odkazu"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Přepínač"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Slovo Back, nad kterým je šipka vlevo"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Slovo End, nad kterým je šipka vlevo"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Slovo On s vykřičníkem, nad kterým je šipka vlevo a vpravo"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Slovo Soon, nad kterým je šipka vpravo"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Slovo Top, nad kterým je šipka nahoru"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Znak Od osmnácti let"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Klávesa s desítkou"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Symbol pro zadávání velkých písmen v latině"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Symbol pro zadávání malých písmen v latině"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Symbol pro zadávání číslic"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Symbol zadávání symbolů"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Symbol pro zadávání písmen v latině"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Oheň"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elektrická svítilna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Montážní klíč"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Kladivo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Matice a šroub"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Kuchyňský nůž"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistole"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Dalekohled"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Křišťálová koule"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Šesticípá hvězda s bodem uprostřed"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japonský symbol pro začátečníka"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Obrázek trojzubce"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Černé hranaté tlačítko"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Bílé hranaté tlačítko"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Velký červený kruh"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Velký modrý kruh"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Velký oranžový kosočtverec"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Velký modrý kosočtverec"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Malý oranžový kosočtverec"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Malý modrý kosočtverec"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Červený trojúhelník ukazující nahoru"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Červený trojúhelník ukazující dolů"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Malý červený trojúhelník ukazující nahoru"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Malý červený trojúhelník ukazující dolů"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Hodiny ukazující jednu hodinu"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Hodiny ukazující dvě hodiny"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Hodiny ukazující tři hodiny"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Hodiny ukazující čtyři hodiny"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Hodiny ukazující pět hodin"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Hodiny ukazující šest hodin"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Hodiny ukazující sedm hodin"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Hodiny ukazující osm hodin"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Hodiny ukazující devět hodin"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Hodiny ukazující deset hodin"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Hodiny ukazující jedenáct hodin"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Hodiny ukazující dvanáct hodin"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Hodiny ukazující půl druhé"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Hodiny ukazující půl třetí"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Hodiny ukazující půl čtvrté"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Hodiny ukazující půl páté"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Hodiny ukazující půl šesté"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Hodiny ukazující půl sedmé"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Hodiny ukazující půl osmé"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Hodiny ukazující půl deváté"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Hodiny ukazující půl desáté"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Hodiny ukazující půl jedenácté"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Hodiny ukazující půl dvanácté"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Hodiny ukazující půl jedné"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Hora Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokijská věž"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Socha svobody"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Obrys Japonska"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Socha Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Zubící se obličej"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Zubící se obličej se smějícíma se očima"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Obličej se slzami smíchu"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Usmívající se obličej s otevřenými ústy"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Usmívající se obličej s otevřenými ústy a smějícíma se očima"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Usmívající se obličej s otevřenými ústy a studeným potem"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Usmívající se obličej s otevřenými ústy a zavřenýma očima"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Usmívající se obličej se svatozáří"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Usmívající se obličej s rohy"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Mrkající obličej"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Usmívající se obličej se smějícíma se očima"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Obličej, který cítí dobré jídlo"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Úlevný obličej"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Usmívající se obličej s očima ve tvaru srdce"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Usmívající se obličej se slunečními brýlemi"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Drzý obličej"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutrální obličej"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Obličej bez výrazu"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Nepobavený obličej"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Obličej se studeným potem"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Zamyšlený obličej"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zmatený obličej"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Rozpačitý obličej"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Líbající obličej"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Obličej posílající polibek"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Líbající obličej se smějícíma se očima"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Líbající obličej se zavřenýma očima"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Obličej s vyplazeným jazykem"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Obličej s vyplazeným jazykem a mrkajícím okem"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Obličej s vyplazeným jazykem a zavřenýma očima"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Zklamaný obličej"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Znepokojený obličej"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Rozzlobený obličej"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Našpulený obličej"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Plačící obličej"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Obličej s vytrvalým výrazem"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Obličej s výrazem vítězství"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Zklamaný obličej s výrazem úlevy"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Zamračený obličej s otevřenými ústy"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Ztrápený obličej"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Vystrašený obličej"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Vyčerpaný obličej"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Ospalý obličej"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Unavený obličej"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Šklebící se obličej"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Hlasitě plačící obličej"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Obličej s otevřenými ústy"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Mlčící obličej"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Obličej s otevřenými ústy a studeným potem"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Obličej křičící strachem"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Udivený obličej"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Zrudlý obličej"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Spící obličej"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Obličej s výrazem závrati"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Obličej bez úst"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Obličej s lékařskou maskou"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Zubící se kočičí hlava se smějícíma se očima"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Kočičí hlava se slzami smíchu"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Usmívající se kočičí hlava s otevřenými ústy"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Usmívající se kočičí hlava s očima ve tvaru srdce"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Kočičí hlava s úšklebkem"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Líbající kočičí hlava se zavřenýma očima"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Našpulená kočičí hlava"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Plačící kočičí hlava"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Vyčerpaná kočičí hlava"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Obličej s gestem vyjadřujícím odmítnutí"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Obličej s gestem vyjadřujícím souhlas"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Osoba v hlubokém úklonu"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Opice, která nevidí zlo"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Opice, která nenaslouchá zlým řečem"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Opice, která nepomlouvá"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Šťastná osoba zvedající jednu ruku"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Osoba zvedající obě ruce na oslavu"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Zamračená osoba"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Osoba s našpuleným obličejem"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Osoba se sepnutýma rukama"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Vrtulník"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parní lokomotiva"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Železniční vagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Vysokorychlostní vlak"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Vysokorychlostní vlak s kulatou přídí"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vlak"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Železnice"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stanice"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvaj"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagon tramvaje"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Přijíždějící autobus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobusová zastávka"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Záchranka"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Hasičský vůz"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policejní auto"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Přijíždějící policejní auto"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Přijíždějící taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Přijíždějící automobil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Obytný vůz"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Dodávka"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Tahač s návesem"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Jednokolejka"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Lanovka"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Visutá železnice"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Horská lanovka"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Visutá lanovka"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Loď"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Člun"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motorový člun"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vodorovný semafor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Svislý semafor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Značka stavby"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Maják policejního auta"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trojúhelníkový praporek na stanovišti"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Dveře"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Symbol zákazu vstupu"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Značka kouření"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Značka zákazu kouření"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Symbol uklízení odpadků"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Symbol zákazu odhazování odpadků"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbol pitné vody"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbol nepitné vody"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Jízdní kolo"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Zákaz jízdních kol"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cyklista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Horský cyklista"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Chodec"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Zákaz chodců"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Přechod pro děti"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbol pro muže"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbol pro ženy"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"WC"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Symbol dítěte"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toaleta"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Splachovací záchod"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Sprcha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Vana"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Vana"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasová kontrola"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Celní kontrola"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Výdej zavazadel"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Úschovna zavazadel"</string>
+</resources>
diff --git a/java/res/values-cs/strings-talkback-descriptions.xml b/java/res/values-cs/strings-talkback-descriptions.xml
index 6c9c800..d3ae187 100644
--- a/java/res/values-cs/strings-talkback-descriptions.xml
+++ b/java/res/values-cs/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Není zadán žádný text"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Klávesou <xliff:g id="KEY_NAME">%1$s</xliff:g> opravíte <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Klávesou <xliff:g id="KEY_NAME">%1$s</xliff:g> provedete automatickou opravu"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Žádný návrh"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Neznámý znak"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Další symboly"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Velké I s tečkou nad"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznámý znak"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznámý smajlík emodži"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Znuděný obličej"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Rozpačitý obličej"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Obličej se slunečními brýlemi"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Překvapený obličej"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Líbající obličej"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Zamračený obličej"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativní znaky jsou k dispozici"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativní znaky jsou ignorovány"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativní návrhy jsou k dispozici"</string>
diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml
index d5c479c..2d81208 100644
--- a/java/res/values-cs/strings.xml
+++ b/java/res/values-cs/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Při stisku klávesy vibrovat"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk při stisku klávesy"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Detail znaku při stisku klávesy"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Předvolby"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Účty a ochrana soukromí"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Vzhled a rozvržení"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Psaní gesty"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Oprava textu"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Rozšířená nastavení"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Motiv"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktivovat rozdělenou klávesnici"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synchronizace Klávesnice Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synchronizace je zapnutá"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synchronizovat váš osobní slovník mezi zařízeními"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synchronizovat"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Smazat data z cloudu"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Smaže z Googlu vaše synchronizovaná data"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Synchronizovaná data budou z cloudu smazána. Chcete pokračovat?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Smazat"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Zrušit"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Váš osobní slovník bude synchronizován a zálohován na servery Google. Za účelem vylepšení našich služeb mohou být shromažďovány statistické informace o četnosti slov. Shromažďování a využití všech informací bude probíhat v souladu se "<a href="https://www.google.com/policies/privacy">"zásadami ochrany soukromí společnosti Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Za účelem aktivace této funkce přidejte do zařízení účet Google."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Přepínat metody zadávání"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klávesa pro přepínání jazyka ovládá i další metody zadávání"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Klávesa přepínání jazyka"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Zobrazit, když je aktivováno více vstupních jazyků"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Indikátor přejetí prstem"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Zobrazit vizuální signál při přejetí z klávesy Shift nebo Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Prodleva vysk. okna klávesnice"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez prodlevy"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Výchozí"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hlavní slovník"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Zobrazit návrhy oprav"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Zobrazovat navržená slova během psaní"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovat"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Zobrazovat v režimu na výšku"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývat"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokovat nevhodná slova"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Nenavrhovat potenciálně nevhodná slova"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatické opravy"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Klávesa hlasového vstupu"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nejsou povoleny žádné metody hlasového vstupu. Zkontrolujte nastavení Jazyk a vstup."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod zadávání"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Odeslat zpětnou vazbu"</string>
-    <string name="select_language" msgid="3693815588777926848">"Vstupní jazyky"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Jazyky"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Nápověda a zpětná vazba"</string>
+    <string name="select_language" msgid="5709487854987078367">"Jazyky"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opětovným dotykem provedete uložení"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klepnutím sem položku uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovník k dispozici"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motiv klávesnice"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Přepnout účty"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nebyly vybrány žádné účty"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Aktuálně používáte účet <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Zrušit"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Odhlásit se"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Vyberte účet, který chcete použít"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angličtina (Velká Británie)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angličtina (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španělština (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"srbština (latinka)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angličtina (VB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angličtina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španělština (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"srbština (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradiční)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrilice)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinka)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktní)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Žádný jazyk (latinka)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinka (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinka (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Latinka (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Latinka (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emodži"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Motiv klávesnice"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastní styl zadávání"</string>
     <string name="add_style" msgid="6163126614514489951">"Přidat styl"</string>
     <string name="add" msgid="8299699805688017798">"Přidat"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Povolit"</string>
     <string name="not_now" msgid="6172462888202790482">"Teď ne"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Tento styl zadávání již existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Prodleva dlouhého stisknutí"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Délka vibrace u stisku klávesy"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Hlasitost stisknutí klávesy"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Číst soubor externího slovníku"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Ve složce Stažené nejsou žádné soubory slovníků."</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vyberte soubor slovníku k instalaci"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Chcete nainstalovat tento soubor pro jazyk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Došlo k chybě"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Prodleva dlouhého stisknutí"</string>
     <string name="button_default" msgid="3988017840431881491">"Výchozí"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Vítá vás <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"s psaním gesty"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nyní můžete ve všech svých oblíbených aplikacích psát pomocí aplikace <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Nakonfigurovat další jazyky"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Hotovo"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Zobrazit ikonu aplikace"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Zobrazí ikonu aplikace ve spouštěči"</string>
     <string name="app_name" msgid="6320102637491234792">"Poskytovatel slovníku"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Poskytovatel slovníku"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Služba slovníku"</string>
diff --git a/java/res/values-da/strings-emoji-descriptions.xml b/java/res/values-da/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..afe0060
--- /dev/null
+++ b/java/res/values-da/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyrighttegn"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registreret varemærke-tegn"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dobbelt udråbstegn"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Udråbstegn spørgsmålstegn"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Varemærketegn"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Information"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Venstre-højrepil"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Op-ned-pil"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Nordvestpil"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Nordøstpil"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Sydøstpil"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Sydvestpil"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Pil mod venstre med krog"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Pil mod højre med krog"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Ur"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Timeglas"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Sort dobbelttrekant, der peger mod højre"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Sort dobbelttrekant, der peger mod venstre"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Sort dobbelttrekant, der peger opad"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Sort dobbelttrekant, der peger nedad"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Vækkeur"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Timeglas med løbende sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Stort M i cirkel"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Lille, sort firkant"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Lille, hvid firkant"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Sort trekant, der peger mod højre"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Sort trekant, der peger mod venstre"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Hvid, mellemstor firkant"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Sort, mellemstor firkant"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Hvid, mellemstor/lille firkant"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Sort, mellemstor/lille firkant"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sort sol med stråler"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Sky"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Sort telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Afkrydsningsfelt med markering"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraply med regndråber"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Varm drik"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Hvid hånd, der peger opad"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Hvidt smilende ansigt"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Vædderen"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tyren"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Tvillingerne"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Krebs"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Løven"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Jomfruen"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Vægten"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpionen"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Skytten"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Stenbukken"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vandmanden"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Fiskene"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Sort spar"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Sort klør"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Sort hjerter"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Sort ruder"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Varme kilder"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Sort genbrugssymbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Kørestolssymbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anker"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Advarselsskilt"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Højspændingstegn"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Mellemstor, hvid cirkel"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Mellemstor, sort cirkel"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Fodbold"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snemand uden sne"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol bag sky"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Slangebæreren"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Adgang forbudt"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kirke"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Springvand"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Flag i hul"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Sejlbåd"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Telt"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Benzinpumpe"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Sort saks"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Kraftig hvid markering"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Flyvemaskine"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Kuvert"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Løftet knytnæve"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Løftet hånd"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Sejrshånd"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Blyant"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Sort pen"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Kraftig markering"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Kraftigt gangetegn x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Gnister"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisk med otte takker"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Sort stjerne med otte takker"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snefnug"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Gnist"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kryds"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Firkant med negativt kryds"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Sort spørgsmålstegn, ornament"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Hvidt spørgsmålstegn, ornament"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Hvidt udråbstegn, ornament"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Kraftigt udråbstegn"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Kraftigt sort hjerte"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Kraftigt plustegn"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Kraftigt minustegn"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Kraftigt divisionstegn"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Sort pil mod højre"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Krølle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dobbelt krølle"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pil, der peger mod højre og derefter buer opad"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pil, der peger mod højre og derefter buer nedad"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Sort pil mod venstre"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Sort pil opad"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Sort pil nedad"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Sort, stor firkant"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Hvid, stor firkant"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Hvid, mellemstor stjerne"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Kraftig, stor cirkel"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Bølgestreg"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Skiftemærke"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Cirkel med ideogram, lykønskning"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Cirkel med ideogram, hemmelighed"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong-brik, rød drage"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Spillekort, sort joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blodtype A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blodtype B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blodtype O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkeringsplads"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blodtype AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Firkant med \"CL\""</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Firkant med \"cool\""</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Firkant med \"free\""</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Firkant med \"ID\""</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Firkant med \"new\""</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Firkant med \"NG\""</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Firkant med \"OK\""</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Firkant med \"SOS\""</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Firkant med \"up\" og udråbstegn"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Firkant med \"vs\""</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Firkant med katakana, her"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Firkant med katakana, service"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Firkant med ideogram, gebyrfri"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Firkant med ideogram, reserveret sæde"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Firkant med ideogram, forbud"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Firkant med ideogram, ledig"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Firkant med ideogram, accept"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Firkant med ideogram, alt optaget"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Firkant med ideogram, betalt"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Firkant med ideogram, månedlig"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Firkant med ideogram, ansøgning"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Firkant med ideogram, rabat"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Firkant med ideogram, åben"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Cirkel med ideogram, fordel"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Cirkel med ideogram, accept"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Tåget"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Lukket paraply"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Nat med stjerner"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Solopgang over bjerge"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Solopgang"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Bybillede ved skumring"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Solnedgang over bygninger"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Regnbue"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Bro om natten"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Bølge"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Mælkevejen"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Jordklode, Europa og Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Jordklode, Nord- og Sydamerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Jordklode, Asien og Australien"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globus med meridianer"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Nymåne"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Tiltagende halvmåne"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Måne i første kvarter"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Tiltagende måne mod fuldmåne"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Fuldmåne"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Aftagende måne lige efter fuldmåne"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Måne i sidste kvarter"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Aftagende halvmåne"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Halvmåne"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nymåne med ansigt"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Måne i første kvarter med ansigt"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Måne i sidste kvarter med ansigt"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Fuldmåne med ansigt"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol med ansigt"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Funklende stjerne"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Stjerneskud"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanje"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Kimplante"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Stedsegrønt træ"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Løvfældende træ"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmetræ"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kirsebærblomst"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Solsikke"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blomst"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Majskolbe"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Risplante"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Urt"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Firkløver"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Ahornblad"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Nedfaldsløv"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blad i vinden"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Svamp"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Vindruer"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Vandmelon"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citron"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rødt æble"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Grønt æble"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pære"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Fersken"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kirsebær"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jordbær"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzastykke"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Kød på ben"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Fjerkrælår"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Riskiks"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Risbolle"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kogt ris"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Karry og ris"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Dampende skål"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Brød"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Pommes frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Stegte søde kartofler"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Stegte rejer"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fiskefrikadeller med pynt"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Softice"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Is i flager"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Is"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Doughnut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chokoladebar"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Slik"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Slikkepind"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vaniljecreme"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honningkrukke"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Lagkage"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento-boks"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Gryde med mad"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Madlavning"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Kniv og gaffel"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tekop uden håndtag"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakeflaske med kop"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vinglas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktailglas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropisk drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Ølkrus"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Klirrende ølkrus"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Sutteflaske"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Sløjfe"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Indpakket gave"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Fødselsdagskage"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Græskarlygte"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Juletræ"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Julemanden"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fyrværkeri"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Stjernekaster"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Bordbombe"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettikugle"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata-træ"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Krydsede flag"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Japansk nytårspynt"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanske dukker"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Koinobori"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vindklokke"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Månekiggeri"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Skoletaske"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Dimissionshat"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karruselhest"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Pariserhjul"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Rutsjebane"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Fiskestang og fisk"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmkamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Biograf"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Hovedtelefoner"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Malerpalet"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Høj hat"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkustelt"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Billet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klaptræ"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Udøvende kunst"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videospil"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Fuldtræffer"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Spilleautomat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billiard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Spilterning"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Spillekort med blomster"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Node"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Flere noder"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Tangenter"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violin"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Musikstykke"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Løbetrøje med skærf"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisketsjer og bold"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski og skistøvle"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball og kurv"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Ternet flag"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Løber"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Pokal"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Hestevæddeløb"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikansk fodbold"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Svømmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Hus"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Hus med have"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kontorbygning"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japansk posthus"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europæisk posthus"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Hæveautomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Romantisk hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Døgnbutik"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Skole"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Stormagasin"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrik"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya-lanterne"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japansk slot"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europæisk slot"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rotte"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mus"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Okse"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vandbøffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Ko"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Kanin"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drage"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodille"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Hval"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Snegl"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Slange"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Hest"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Vædder"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Ged"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Får"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Abe"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Hane"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kylling"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hund"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Gris"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Vildsvin"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Blæksprutte"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Sneglehus"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insekt"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Myre"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Honningbi"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Mariehøne"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fisk"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropisk fisk"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Pindsvinefisk"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Skildpadde"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kylling under udklækning"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kylling"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kylling set forfra"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Fugl"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koalabjørn"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Puddelhund"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedar"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kamel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Musehoved"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Kohoved"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigerhoved"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Kaninhoved"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kattehoved"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Dragehoved"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Hvalsprøjt"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Hestehoved"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Abehoved"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hundehoved"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Grisehoved"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Frøhoved"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamsterhoved"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Ulvehoved"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Bjørnehoved"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandahoved"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Grisetryne"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Poteaftryk"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Øjne"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Øre"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Næse"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mund"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tunge"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Hvid håndryg med pegefinger op"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Hvid håndryg med pegefinger ned"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Hvid håndryg med pegefinger mod venstre"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Hvid håndryg med pegefinger mod højre"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Knytnæve"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Vinkende hånd"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Håndtegn for OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Tommelfinger op"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Tommelfinger ned"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Klappende hænder"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Åbne hænder"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Krone"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Damehat"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Briller"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Slips"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Kjole"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Dametøj"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Pung"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Håndtaske"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pung"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Herresko"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportssko"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Højhælet sko"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Damesandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Damestøvler"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Fodspor"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Buste i silhuet"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Buster i silhuet"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Dreng"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Pige"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mand"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Kvinde"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familie"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Mand og kvinde, der holder hinanden i hånden"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"To mænd, der holder hinanden i hånden"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"To kvinder, der holder hinanden i hånden"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Politibetjent"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Kvinde med kaninører"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Brud med slør"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Person med lyst hår"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Mand med gua pi mao-hat"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Mand med turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Ældre mand"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Ældre kvinde"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Bygningsarbejder"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinsesse"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japansk trold"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japansk nisse"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spøgelse"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Barneengel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Rumvæsen"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Rummonster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Djævleunge"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Kranium"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Receptionist"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Vagt"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danser"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Læbestift"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Neglelak"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Ansigtsmassage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Klipning"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barberskilt"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Sprøjte"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pille"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kyssemærke"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Kærestebrev"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Ædelsten"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kys"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Buket"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Par med hjerte"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Bryllup"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Bankende hjerte"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Knust hjerte"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"To hjerter"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Glitrende hjerte"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Voksende hjerte"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hjerte med pil"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blåt hjerte"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Grønt hjerte"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Gult hjerte"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lilla hjerte"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hjerte med bånd"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Roterende hjerter"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Hjertedekoration"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamant med en prik"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektrisk pære"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Vredessymbol"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bombe"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Sovesymbol"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Kollisionssymbol"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Sveddryp-symbol"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Dråbe"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Løbesymbol"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Bunke møg"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Spændte biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Svimmelhedssymbol"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Taleboble"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Tankeboble"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Hvid blomst"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Hundred point-symbol"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Pengesæk"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valutaveksling"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Kraftigt dollartegn"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditkort"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Seddel med yentegn"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Seddel med dollartegn"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Seddel med eurotegn"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Seddel med pundtegn"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Penge med vinger"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Diagram med stigende kurve og yentegn"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sæde"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"PC"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Mappe"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppydisk"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optisk disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Filmappe"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Åben filmappe"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Side med flip"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Opadvendt side"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Afrivningskalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kartotek"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Diagram med stigende kurve"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Diagram med faldende kurve"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Søjlediagram"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Udklipsholder"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Tegnestift"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Rund tegnestift"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Papirclips"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Lige lineal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trekantet lineal"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Faneblade"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Regnskabsbog"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notesbog"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notesbog med pænt omslag"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Lukket bog"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Åben bog"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Grøn bog"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blå bog"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Orange bog"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Bøger"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Navneskilt"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Rulle"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Notat"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonrør"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Personsøger"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faxmaskine"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Parabolantenne"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Højttaler"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Udbakke"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Indbakke"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakke"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mailsymbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Indgående kuvert"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Kuvert under pil, der peger nedad"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Lukket postkasse med flaget nede"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Lukket postkasse med flaget oppe"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Åben postkasse med hævet flag"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Åben postkasse med flaget nede"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postkasse"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posthorn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Avis"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiltelefon med pil, der peger mod højre, til venstre"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrationstilstand"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Slukket mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Ingen mobiltelefoner"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Tv-antenne"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Tv"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Snoede pile mod højre"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Pile mod højre og mod venstre i åben cirkel i urets retning"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Pile mod højre og mod venstre i åben cirkel i urets retning med overlejret \"1\" i en cirkel"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Pile opad og nedad i en åben cirkel i urets retning"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Pile nedad og opad i en åben cirkel mod urets retning"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol for lav lysstyrke"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol for høj lysstyrke"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Overstreget højttaler"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Højttaler"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Højttaler med en lydbølge"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Højttaler med tre lydbølger"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batteri"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elstik"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lup mod venstre"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lup mod højre"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lås med pen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Lukket lås med nøgle"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Nøgle"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lås"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Åben lås"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Klokke"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Overstreget klokke"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bogmærke"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Linksymbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Drejeknap"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"BACK\" under en pil mod venstre"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"END\" under en pil mod venstre"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"ON\" med udråbstegn under en venstre-højrepil"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"SOON\" under en pil mod højre"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"TOP\" under en pil opad"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Forbudt under 18 år-symbol"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tast ti"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Inputsymbol for latinske store bogstaver"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Inputsymbol for latinske små bogstaver"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Inputsymbol for tal"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Inputsymbol for symboler"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Inputsymbol for latinske bogstaver"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Ild"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Lommelygte"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Skruenøgle"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Møtrik og bolt"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho-kniv"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Krystalkugle"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sekstakket stjerne med prik"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japansk symbol for begynder"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Treforkemblem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Sort firkantet knap"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Hvid firkantet knap"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Stor, rød cirkel"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Stor, blå cirkel"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Stor, orange rombe"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Stor, blå rombe"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Lille, orange rombe"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Lille, blå rombe"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Rød trekant, der peger opad"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Rød trekant, der peger nedad"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Lille, rød trekant, der peger opad"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Lille, rød trekant, der peger nedad"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Urskive, klokken et"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Urskive, klokken to"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Urskive, klokken tre"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Urskive, klokken fire"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Urskive, klokken fem"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Urskive, klokken seks"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Urskive, klokken syv"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Urskive, klokken otte"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Urskive, klokken ni"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Urskive, klokken ti"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Urskive, klokken elleve"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Urskive, klokken tolv"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Urskive, klokken halv to"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Urskive, klokken halv tre"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Urskive, klokken halv fire"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Urskive, klokken halv fem"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Urskive, klokken halv seks"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Urskive, klokken halv syv"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Urskive, klokken halv otte"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Urskive, klokken halv ni"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Urskive, klokken halv ti"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Urskive, klokken halv elleve"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Urskive, klokken halv tolv"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Urskive, klokken halv et"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji-bjerget"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo Tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Frihedsgudinden"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhuet af Japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai-stenstatue"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Storsmilende ansigt"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Storsmilende ansigt med smilende øjne"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Ansigt med glædestårer"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Smilende ansigt med åben mund"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Smilende ansigt med åben mund og smilende øjne"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Smilende ansigt med åben mund og koldsved"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Smilende ansigt med åben mund og øjne knebet i"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Smilende ansigt med glorie"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Smilende ansigt med horn"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Blinkede ansigt"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Smilende ansigt med smilende øjne"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Ansigt, der slikker sig om munden"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lettet ansigt"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Smilende ansigt med hjerteformede øjne"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Smilende ansigt med solbriller"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Smørret ansigt"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutralt ansigt"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Udtryksløst ansigt"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Ubegejstret ansigt"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Ansigt med koldsved"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Eftertænksomt ansigt"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Forvirret ansigt"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Forvirret ansigt"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kyssende ansigt"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Ansigt, som sender et luftkys"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kyssende ansigt med smilende øjne"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kyssende ansigt med lukkede øjne"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Ansigt, der rækker tunge"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Ansigt, der rækker tunge og blinker"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Ansigt, der rækker tunge, med øjne knebet i"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Skuffet ansigt"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Bekymret ansigt"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Vredt ansigt"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Surmulende ansigt"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Grædende ansigt"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Ihærdigt ansigt"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Triumferende ansigt"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Skuffet, men lettet ansigt"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Galt ansigt med åben mund"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Forpint ansigt"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Frygtsomt ansigt"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Udmattet ansigt"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Søvnigt ansigt"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Træt ansigt"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimasse"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Stortudende ansigt"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Ansigt med åben mund"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Tavst ansigt"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Ansigt med åben mund og koldsved"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Ansigt, der skriger af frygt"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Forbløffet ansigt"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Blussende ansigt"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Sovende ansigt"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Svimmelt ansigt"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Ansigt uden mund"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Ansigt med ansigtsmaske"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Storsmilende katteansigt med smilende øjne"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Katteansigt med glædestårer"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Smilende katteansigt med åben mund"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Smilende katteansigt med hjerteformede øjne"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Katteansigt med skævt smil"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kyssende katteansigt med lukkede øjne"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Surmulende katteansigt"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Grædende katteansigt"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Udmattet katteansigt"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Ansigt med \"duer ikke\"-udtryk"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Ansigt med \"OK\"-udtryk"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Person, som bukker dybt"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Abe, der holder sig for øjnene"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Abe, der holder sig for ørerne"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Abe, der holder sig for munden"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Glad person med en hånd i luften"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person med begge hænder løftet i glæde"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Gal person"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Surmulende person"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person med foldede hænder"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Damplokomotiv"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Togvogn"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Lyntog"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Lyntog med afrundet front"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tog"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Letbane"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Station"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Sporvogn"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Sporvogn"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Modkørende bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleyvogn"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Busstoppested"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Brandbil"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Politibil"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Modkørende politibil"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxa"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Modkørende taxa"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Bil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Modkørende bil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Autocamper"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Varevogn"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Sættevogn"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Bjergbane"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Luftbane"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Kabelbane"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Svævebane"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Skib"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Robåd"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedbåd"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vandret trafiklys"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Lodret trafiklys"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Vejarbejdeskilt"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Rotorblink på politibil"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trekantet flag på stang"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Dør"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Adgang forbudt-skilt"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Rygning tilladt-symbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Rygning forbudt-symbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Put affald i skraldespanden-symbol"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Smid ikke affald-symbol"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Drikkevandssymbol"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Vandet kan ikke drikkes-symbol"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Cykel"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Cykler forbudt"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cyklist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountainbiker"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Fodgænger"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Fodgængere forbudt"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Børn på vejen"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbol for herrer"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbol for damer"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toilet"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Babysymbol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Bruser"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bad"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badekar"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Paskontrol"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Told"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagageområde"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Bagageopbevaring"</string>
+</resources>
diff --git a/java/res/values-da/strings-talkback-descriptions.xml b/java/res/values-da/strings-talkback-descriptions.xml
index 5f54004..29f4461 100644
--- a/java/res/values-da/strings-talkback-descriptions.xml
+++ b/java/res/values-da/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Der er ingen indtastet tekst"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> retter <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> til <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> udfører automatisk stavekontrol"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ingen forslag"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Ukendt tegn"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Flere symboler"</string>
@@ -38,7 +39,7 @@
     <string name="spoken_description_settings" msgid="7281251004003143204">"Indstillinger"</string>
     <string name="spoken_description_tab" msgid="8210782459446866716">"Fane"</string>
     <string name="spoken_description_space" msgid="5908716896642059145">"Mellemrum"</string>
-    <string name="spoken_description_mic" msgid="6153138783813452464">"Stemmeinput"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Indtaling"</string>
     <string name="spoken_description_emoji" msgid="7990051553008088470">"Emoji"</string>
     <string name="spoken_description_return" msgid="3183692287397645708">"Return"</string>
     <string name="spoken_description_search" msgid="5099937658231911288">"Søgning"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Stort I med prik over"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ukendt symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ukendt emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Træt ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Forlegent ansigt"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ansigt med solbriller"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Overrasket ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kyssende ansigt"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Surt ansigt"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative tegn er tilgængelige"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative tegn er deaktiveret"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative forslag er tilgængelige"</string>
diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml
index b33cacc..f40b645 100644
--- a/java/res/values-da/strings.xml
+++ b/java/res/values-da/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibration ved tastetryk"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetryk"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop op ved tastetryk"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Præferencer"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Konti og privatliv"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Udseende og layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Glidende indtastning"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Tekstkorrigering"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avanceret"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktivér delt tastatur"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synkronisering af Google-tastatur"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synkronisering er slået til"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synkroniser din personlige ordbog på alle enheder"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synkroniser nu"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Slet data fra skyen"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Sletter dine synkroniserede data fra Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Dine synkroniserede data slettes fra skyen. Er du sikker?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Slet"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Annuller"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Din personlige ordbog synkroniseres og sikkerhedskopieres til Googles servere. De statistiske oplysninger om ordfrekvens indsamles muligvis med henblik på at forbedre vores produkter. Indsamlingen og brugen af alle oplysninger sker i overensstemmelse med "<a href="https://www.google.com/policies/privacy">"Googles privatlivspolitik"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Føj en Google-konto til enheden for at aktivere denne funktion"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skift inputmetode"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten til sprogskift gælder også for andre inputmetoder"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Knap til sprogskift"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Vis, når der er aktiveret flere inputsprog"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Vis indikator ved glidning"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Vis et visuelt tip, når du glider fra Shift eller symboltaster"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Forsink. afvis. af taste-pop op"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ingen forsink."</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
@@ -62,44 +67,52 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hovedordbog"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Vis rettelsesforslag"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vis ordforslag under indtastning"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis altid"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Vis i oprejst format"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul altid"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloker stødende ord"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Foreslå ikke potentielt stødende ord"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatisk rettelse"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"Mellemrumstast og tegnsætning retter automatisk forkerte ord"</string>
     <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Fra"</string>
     <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Moderat"</string>
-    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Aggressiv"</string>
-    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Meget aggressiv"</string>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Middel"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Maksimal"</string>
     <string name="bigram_prediction" msgid="1084449187723948550">"Forslag til næste ord"</string>
     <string name="bigram_prediction_summary" msgid="3896362682751109677">"Brug det forrige ord til at give forslag"</string>
     <string name="gesture_input" msgid="826951152254563827">"Aktivér glidende indtastning"</string>
-    <string name="gesture_input_summary" msgid="9180350639305731231">"Skriv et ord ved at glide mellem bogstaverne"</string>
+    <string name="gesture_input_summary" msgid="9180350639305731231">"Skriv et ord ved at trække fingeren rundt mellem bogstaverne"</string>
     <string name="gesture_preview_trail" msgid="3802333369335722221">"Vis glidende trykspor"</string>
     <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamiske ordeksempler"</string>
     <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Se ordforslag ved glidende indtastning"</string>
-    <string name="gesture_space_aware" msgid="2078291600664682496">"Bevægelse for udtryk"</string>
+    <string name="gesture_space_aware" msgid="2078291600664682496">"Glidende mellemrum"</string>
     <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Tilføj mellemrum ved at glide til mellemrumstasten"</string>
-    <string name="voice_input" msgid="3583258583521397548">"Knap til taleinput"</string>
-    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Der er ingen aktiverede stemmeinputmetoder. Kontrollér Indstillinger for sprog og input."</string>
+    <string name="voice_input" msgid="3583258583521397548">"Knap til indtaling"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Der er ingen aktiverede indtalingsmetoder. Kontrollér Indstillinger for sprog og input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Sprog"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hjælp og feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Sprog"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klik her for at gemme"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Skift konto"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Du har ikke valgt en konto"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Du bruger i øjeblikket <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Annuller"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Log ud"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Vælg den konto, du vil bruge"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannien)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spansk (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbisk (latinsk)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelsk (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelsk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spansk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisk (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionelt)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Intet sprog (Alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tastaturtema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Tilpasset inputtypografi"</string>
     <string name="add_style" msgid="6163126614514489951">"Tilføj typografi"</string>
     <string name="add" msgid="8299699805688017798">"Tilføj"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktivér"</string>
     <string name="not_now" msgid="6172462888202790482">"Ikke nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Denne inputstil findes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinket langt tastetryk"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrationstid ved tastetryk"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Lydstyrke ved tastetryk"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Læs ekstern ordbogsfil"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Der er ingen ordbogsfiler i mappen Downloads"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vælg den ordbog, som du vil installere"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vil du virkelig installere denne fil for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Der opstod en fejl"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinket langt tastetryk"</string>
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Velkommen til <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"med glidende indtastning"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nu kan du skrive i alle dine favoritapps med <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurer flere sprog"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Afslut"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Vis appikon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Vis appikon på applisten"</string>
     <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Ordbogstjeneste"</string>
diff --git a/java/res/values-de/strings-emoji-descriptions.xml b/java/res/values-de/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..d964e53
--- /dev/null
+++ b/java/res/values-de/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyright-Zeichen"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registered Trademark-Zeichen"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Doppeltes Ausrufezeichen"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Ausrufe- und Fragezeichen"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Trademark-Zeichen"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Symbol für Informationsquelle"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Pfeil nach rechts und links"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Pfeil nach oben und unten"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Pfeil nach links oben"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Pfeil nach rechts oben"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Pfeil nach rechts unten"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Pfeil nach links unten"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Linkspfeil mit Haken"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Rechtspfeil mit Haken"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Uhr"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Sanduhr"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Nach rechts zeigendes schwarzes doppeltes Dreieck"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Nach links zeigendes schwarzes doppeltes Dreieck"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Nach oben zeigendes schwarzes doppeltes Dreieck"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Nach unten zeigendes schwarzes doppeltes Dreieck"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Wecker"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Sanduhr mit rieselndem Sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Eingekreister lateinischer Großbuchstabe M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Kleines schwarzes Quadrat"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Kleines weißes Quadrat"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Nach rechts zeigendes schwarzes Dreieck"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Nach links zeigendes schwarzes Dreieck"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Mittelgroßes weißes Quadrat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Mittelgroßes schwarzes Quadrat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Mittelkleines weißes Quadrat"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Mittelkleines schwarzes Quadrat"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Schwarze Sonne mit Strahlen"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Wolke"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Schwarzes Telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Markierungsfeld mit Häkchen"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Schirm mit Regentropfen"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Heißgetränk"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Nach oben deutender Zeigefinger"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Weißes Smiley"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Sternzeichen Widder"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Sternzeichen Stier"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Sternzeichen Zwillinge"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Sternzeichen Krebs"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Sternzeichen Löwe"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Sternzeichen Jungfrau"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Sternzeichen Waage"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Sternzeichen Skorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sternzeichen Schütze"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Sternzeichen Steinbock"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Sternzeichen Wassermann"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Sternzeichen Fische"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Pik schwarz"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Kreuz schwarz"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Herz schwarz"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Karo schwarz"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Thermalquellen"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Schwarzes allgemeingültiges Recycling-Symbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Rollstuhlsymbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anker"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Warnzeichen"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Hochspannungszeichen"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Mittelgroßer weißer Kreis"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Mittelgroßer schwarzer Kreis"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Fußball"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Schneemann ohne Schnee"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sonne hinter Wolke"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Sternbild Schlangenträger"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Zeichen für \"Kein Durchgang\""</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kirche"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Brunnen"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Fahne im Loch"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Segelboot"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Zelt"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Zapfsäule"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Schwarze Schere"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Weißes Häkchen in Fettdruck"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Flugzeug"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Briefumschlag"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Erhobene Faust"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Erhobene Hand"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Victoryzeichen"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Bleistift"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Schwarze Schreibfeder"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Häkchen in Fettdruck"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Malzeichen in Fettdruck"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Funkeln"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Achtzackiges Sternchen"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Achtzackiger schwarzer Stern"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Schneeflocke"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Funken"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Angekreuzt-Zeichen"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Angekreuztes gefülltes Quadrat"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Schwarzes Fragezeichen"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Weißes Fragezeichen"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Weißes Ausrufezeichen"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Ausrufezeichen in Fettdruck"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Schwarzes Herz in Fettdruck"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Pluszeichen in Fettdruck"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Minuszeichen in Fettdruck"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Divisionszeichen in Fettdruck"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Schwarzer Pfeil nach rechts"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Schleife"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Doppelschleife"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pfeil nach rechts und dann im Bogen nach oben"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pfeil nach rechts und dann im Bogen nach unten"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Schwarzer Pfeil nach links"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Schwarzer Pfeil nach oben"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Schwarzer Pfeil nach unten"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Großes schwarzes Quadrat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Großes weißes Quadrat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Mittelgroßer weißer Stern"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Großer Kreis in Fettdruck"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Wellenlinie"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Ioriten"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Rundes Ideogramm für \"Glückwunsch\""</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Rundes Ideogramm für \"Geheimnis\""</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong-Stein Roter Drache"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Spielkarte mit schwarzem Joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blutgruppe A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blutgruppe B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blutgruppe O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkplatz-Symbol"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blutgruppe AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Quadrat mit \"CL\" (Clear)"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Quadrat mit \"Cool\""</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Quadrat mit \"Free\""</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Quadrat mit \"ID\""</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Quadrat mit \"New\""</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Quadrat mit \"NG\" (No Good)"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Quadrat mit \"OK\""</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Quadrat mit \"SOS\""</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Quadrat mit \"UP\" und Ausrufezeichen"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Quadrat mit \"VS\" (Versus)"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Quadrat mit japanischem Zeichen für \"Hier\""</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Quadrat mit japanischem Zeichen für \"Service\""</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Quadrat mit Ideogramm \"Nichts\""</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Quadrat mit Ideogramm \"Reserviert\""</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Quadrat mit Ideogramm \"Verbot\""</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Quadrat mit Ideogramm \"Frei\""</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Quadrat mit Ideogramm \"Passend/Bestätigt\""</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Quadrat mit Ideogramm \"Voll/Besetzt\""</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Quadrat mit Ideogramm \"Bezahlt\""</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Quadrat mit Ideogramm \"Monatlich\""</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Quadrat mit Ideogramm \"Antrag\""</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Quadrat mit Ideogramm \"Rabatt\""</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Quadrat mit Ideogramm \"Geöffnet\""</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Rundes japanisches Ideogramm für \"Vorteil\""</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Rundes japanisches Ideogramm für \"Akzeptieren\""</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Zyklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Neblig"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Geschlossener Schirm"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Sternennacht"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sonnenaufgang in den Bergen"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sonnenaufgang"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Stadtsilhouette in der Abenddämmerung"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Stadtsilhouette mit Sonnenuntergang"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Regenbogen"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Brücke bei Nacht"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Welle"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Milchstraße"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globus mit Europa/Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globus mit Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globus mit Asien/Australien"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globus mit Meridianen"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Neumond"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Zunehmender Sichelmond"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Mond im ersten Viertel"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Zunehmender Dreiviertelmond"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Vollmond"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Abnehmender Dreiviertelmond"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Mond im letzten Viertel"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Abnehmender Sichelmond"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Mondsichel"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Neumond mit Gesicht"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Mond mit Gesicht im ersten Viertel"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Mond mit Gesicht im letzten Viertel"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Vollmond mit Gesicht"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sonne mit Gesicht"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Leuchtender Stern"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Sternschnuppe"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanie"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Setzling"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Nadelbaum"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Laubbaum"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palme"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulpe"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kirschblüte"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sonnenblume"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blüte"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Maiskolben"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Reisähren"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Kräuter"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Vierblättriges Kleeblatt"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Ahornblatt"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Herabgefallenes Blatt"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blatt im Wind"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Pilz"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Trauben"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melone"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Wassermelone"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Zitrone"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banane"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Roter Apfel"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Grüner Apfel"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Birne"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pfirsich"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kirschen"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Erdbeere"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzastück"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Fleisch am Knochen"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Geflügelschenkel"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Reiscracker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Reisbällchen"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Gekochter Reis"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Reis mit Curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Dampfende Schüssel"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Brot"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Pommes frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Geröstete Süßkartoffel"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Frittierte Garnele"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fischfrikadelle mit Wirbelverzierung"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Softeis"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Shaved Ice"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Eiscreme"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Schokoladentafel"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bonbon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lutscher"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vanillepudding/Eiercreme"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honigtopf"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Shortcake"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento-Box"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Schale mit Essen"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Kochen"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Messer und Gabel"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Teetasse ohne Henkel"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake-Flasche und -Tasse"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Weinglas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktailglas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Cocktail"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Bierkrug"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Anstoßende Bierkrüge"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Babyfläschchen"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Schleife"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Geschenk"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Geburtstagstorte"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Halloweenkürbis"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Weihnachtsbaum"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Weihnachtsmann"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Feuerwerk"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Wunderkerze"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Luftballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfettikanone"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettiball"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata-Baum"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Gekreuzte Flaggen"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Japanische Neujahrsdekoration"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanische Puppen"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Japanische Karpfenfahne"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Windspiel"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Japanisches Mondfest"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Schulranzen"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"College-Hut"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karussellpferd"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Riesenrad"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Achterbahn"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Angelrute und Fisch"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmkamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Kopfhörer"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Farbpalette"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Zylinder"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Zirkuszelt"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ticket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Filmklappe"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Darstellende Künste"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videospiel"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Volltreffer"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Spielautomat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Spielwürfel"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Japanische Spielkarten mit Blumenmotiv"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musiknote"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Mehrere Musiknoten"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitarre"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klaviatur"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompete"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Geige"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitur"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Laufshirt mit Schärpe"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisschläger und Ball"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski und Skischuhe"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball und Korb"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Zielflagge"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Läufer"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Pokal"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Pferderennen"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"American Football"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugbyball"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Schwimmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Haus"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Haus mit Garten"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Bürogebäude"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japanisches Postamt"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europäisches Postamt"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Krankenhaus"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Geldautomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love Hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Verbrauchermarkt"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Schule"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Kaufhaus"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrik"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya-Laterne"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Burg/Schloss japanisch"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Burg/Schloss europäisch"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Ratte"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Maus"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Ochse"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Wasserbüffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Kuh"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Kaninchen"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Katze"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drache"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Wal"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Schnecke"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Schlange"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Pferd"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Schafbock"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Ziege"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Schaf"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Affe"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Hahn"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Huhn"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hund"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Schwein"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Wildschwein"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Krake"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiralmuschel"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insekt/Käfer"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Ameise"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Biene"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Marienkäfer"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fisch"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropischer Fisch"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Kugelfisch"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Schildkröte"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Schlüpfendes Küken"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Küken"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Küken von vorne"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Vogel"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pinguin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedar"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kamel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mäusekopf"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Kuhkopf"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigerkopf"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Hasenkopf"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Katzenkopf"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Drachenkopf"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Fontäne ausstoßender Wal"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Pferdekopf"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Affenkopf"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hundekopf"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Schweinekopf"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Froschkopf"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamsterkopf"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wolfskopf"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Bärenkopf"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandakopf"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Schweinenase"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pfotenabdrücke"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Augen"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ohr"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nase"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mund"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Zunge"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Handrückseite mit nach oben deutendem Zeigefinger"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Handrückseite mit nach unten deutendem Zeigefinger"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Handrückseite mit nach links deutendem Zeigefinger"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Handrückseite mit nach rechts deutendem Zeigefinger"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Faust"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Winkende Hand"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Handzeichen für \"OK\""</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Daumen hoch"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Daumen runter"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Klatschende Hände"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Geöffnete Hände"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Krone"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Damenhut"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Brille"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Krawatte"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-Shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Kleid"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Damenkleidung"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Geldbörse"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handtasche"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Beutel"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Herrenschuh"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Turnschuh"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Stöckelschuh"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Damensandalette"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Damenstiefel"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Fußabdrücke"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhouette eines Oberkörpers"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhouette mehrerer Oberkörper"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Junge"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Mädchen"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mann"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Frau"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familie"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Mann und Frau halten sich an der Hand"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Zwei Männer halten sich an der Hand"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Zwei Frauen halten sich an der Hand"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polizist"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Frau mit Hasenohren"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Braut mit Schleier"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Person mit blondem Haar"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Mann mit japanischer Kopfbedeckung (Gua Pi Mao)"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Mann mit Turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Älterer Mann"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Ältere Frau"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Bauarbeiter"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinzessin"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanischer Oger"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanischer Kobold"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Geist"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Engelchen"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Alien"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Alien-Monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Teufelchen"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Schädel"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Mitarbeiter am Informationsschalter"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardist"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Tänzer"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lippenstift"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nagellack"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Gesichtsmassage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Haarschnitt"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Friseurzunftzeichen"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Spritze"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pille"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kussmund"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Liebesbrief"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Edelstein"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kuss"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Blumenstrauß"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pärchen mit Herz"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Hochzeit"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Schlagendes Herz"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Gebrochenes Herz"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Zwei Herzen"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Funkelndes Herz"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Größer werdendes Herz"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Herz mit Pfeil"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blaues Herz"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Grünes Herz"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Gelbes Herz"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lilafarbenes Herz"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Herz mit Schleife"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Umeinander kreisende Herzen"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Herzverzierung"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Rautenform mit Punkt innen"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Glühbirne"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbol für Ärger"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bombe"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbol für Schlafen"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbol für Kollision"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbol für Schwitzen"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Tropfen"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbol für Sausen (Staubwolke)"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kothäufchen"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Angespannter Bizeps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbol für \"Schwindelig\""</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Sprechblase"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Gedankenblase"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Weiße Blume"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbol für 100 Punkte"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Geldsack"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Geldwechsel"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dollarzeichen in Fettdruck"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditkarte"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Geldschein mit Yen-Zeichen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Geldschein mit Dollar-Zeichen"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Geldschein mit Euro-Zeichen"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Geldschein mit Pfund-Zeichen"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Geld mit Flügeln"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Diagramm mit Aufwärtstrend und Yen-Zeichen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sitz"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Computer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktentasche"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskette"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"CD"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Ordner"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Geöffneter Ordner"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Teilweise eingerolltes Blatt"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Vorderseite eines Dokuments"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Abreißkalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kartei"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Diagramm mit Aufwärtstrend"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Diagramm mit Abwärtstrend"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Balkendiagramm"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Klemmbrett"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pinnadel"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Pinnadel mit rundem Kopf"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Büroklammer"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Lineal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Geodreieck"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Haftmarker"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Kontenbuch"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notizbuch"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notizbuch mit dekorativem Cover"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Geschlossenes Buch"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Offenes Buch"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Grünes Buch"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blaues Buch"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranges Buch"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Bücher"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Namensschild"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Schriftrolle"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonhörer"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faxgerät"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellitenschüssel"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Beschallungslautsprecher"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Ablage für Postausgang"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Ablage für Posteingang"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-Mail-Symbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Briefeingang"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Briefumschlag mit nach unten zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Geschlossener Briefkasten mit gesenkter Fahne"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Geschlossener Briefkasten mit erhobener Fahne"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Offener Briefkasten mit erhobener Fahne"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Offener Briefkasten mit gesenkter Fahne"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Briefkasten"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posthorn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Zeitung"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiltelefon mit nach rechts zeigendem Pfeil links daneben"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrationsmodus"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiltelefon aus"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Keine Mobiltelefone"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Balkenförmige Signalstärkenanzeige"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoapparat"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Fernseher"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Verschlungene Pfeile nach rechts"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Kreisförmige Pfeile im Uhrzeigersinn"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Kreisförmige Pfeile im Uhrzeigersinn mit überlagerter eingerahmter Ziffer 1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Kreisförmige Pfeile nach unten und oben im Uhrzeigersinn"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Kreisförmige Pfeile nach unten und oben gegen den Uhrzeigersinn"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol für schwache Helligkeit"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol für starke Helligkeit"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Durchgestrichener Lautsprecher"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Lautsprecher"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Lautsprecher mit einer Schallwelle"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Lautsprecher mit drei Schallwellen"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batterie"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Stecker"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Nach links geneigte Lupe"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Nach rechts geneigte Lupe"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Vorhängeschloss mit Füllfederhalter"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Geschlossenes Vorhängeschloss mit Schlüssel"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Schlüssel"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Vorhängeschloss"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Geöffnetes Vorhängeschloss"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Glocke"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Durchgestrichene Glocke"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Lesezeichen"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Symbol für Verknüpfung"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Auswahltaste"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"BACK\" mit nach links zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"END\" mit nach links zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"ON\" mit Ausrufezeichen und nach links und rechts zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"SOON\" mit nach rechts zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"TOP\" mit nach oben zeigendem Pfeil darüber"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbol für \"Erst ab 18\""</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Computertaste mit der Ziffer 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Eingabesymbol für lateinische Großbuchstaben"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Eingabesymbol für lateinische Kleinbuchstaben"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Eingabesymbol für Ziffern"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Eingabesymbol für Sonderzeichen"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Eingabesymbol für lateinische Buchstaben"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Feuer"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Taschenlampe"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Schraubenschlüssel"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Schraube und Mutter"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Japanisches Küchenmesser"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistole"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristallkugel"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sechszackiger Stern mit Punkt in der Mitte"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japanisches Symbol für Anfänger"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Dreizack-Symbol"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Schwarze quadratische Taste"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Weiße quadratische Taste"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Großer roter Kreis"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Großer blauer Kreis"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Große orange Raute"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Große blaue Raute"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Kleine orange Raute"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Kleine blaue Raute"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Nach oben zeigendes rotes Dreieck"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Nach unten zeigendes rotes Dreieck"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Nach oben zeigendes kleines rotes Dreieck"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Nach unten zeigendes kleines rotes Dreieck"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Ziffernblatt mit der Anzeige ein Uhr"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Ziffernblatt mit der Anzeige zwei Uhr"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Ziffernblatt mit der Anzeige drei Uhr"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Ziffernblatt mit der Anzeige vier Uhr"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Ziffernblatt mit der Anzeige fünf Uhr"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Ziffernblatt mit der Anzeige sechs Uhr"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Ziffernblatt mit der Anzeige sieben Uhr"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Ziffernblatt mit der Anzeige acht Uhr"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Ziffernblatt mit der Anzeige neun Uhr"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Ziffernblatt mit der Anzeige zehn Uhr"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Ziffernblatt mit der Anzeige elf Uhr"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Ziffernblatt mit der Anzeige zwölf Uhr"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Ziffernblatt mit der Anzeige ein Uhr dreißig"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Ziffernblatt mit der Anzeige zwei Uhr dreißig"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Ziffernblatt mit der Anzeige drei Uhr dreißig"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Ziffernblatt mit der Anzeige vier Uhr dreißig"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Ziffernblatt mit der Anzeige fünf Uhr dreißig"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Ziffernblatt mit der Anzeige sechs Uhr dreißig"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Ziffernblatt mit der Anzeige sieben Uhr dreißig"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Ziffernblatt mit der Anzeige acht Uhr dreißig"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Ziffernblatt mit der Anzeige neun Uhr dreißig"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Ziffernblatt mit der Anzeige zehn Uhr dreißig"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Ziffernblatt mit der Anzeige elf Uhr dreißig"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Ziffernblatt mit der Anzeige zwölf Uhr dreißig"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Vulkan Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo Tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Freiheitsstatue"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Umriss von Japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai-Statue"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Grinsendes Gesicht"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Grinsendes Gesicht mit lächelnden Augen"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Gesicht mit Freudentränen"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Lächelndes Gesicht mit offenem Mund"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Lächelndes Gesicht mit offenem Mund und fröhlichen Augen"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Lächelndes Gesicht mit offenem Mund und Angstschweiß"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Lächelndes Gesicht mit offenem Mund und zugekniffenen Augen"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Lächelndes Gesicht mit Heiligenschein"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Lächelndes Gesicht mit Hörnern"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Zwinkerndes Gesicht"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Lächelndes Gesicht mit lächelnden Augen"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Gesicht, das köstliches Essen genießt"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Erleichtertes Gesicht"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Lächelndes Gesicht mit herzförmigen Augen"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Lächelndes Gesicht mit Sonnenbrille"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Süffisant lächelndes Gesicht"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutrales Gesicht"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Ausdrucksloses Gesicht"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Unerfreutes Gesicht"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Gesicht mit Angstschweiß"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Nachdenkliches Gesicht"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Verwirrtes Gesicht"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Bestürztes Gesicht"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Küssendes Gesicht"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Gesicht, das einen Kuss zuwirft"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Küssendes Gesicht mit lächelnden Augen"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Küssendes Gesicht mit geschlossenen Augen"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Gesicht mit herausgestreckter Zunge"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Gesicht mit herausgestreckter Zunge und zwinkerndem Auge"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Gesicht mit herausgestreckter Zunge und zugekniffenen Augen"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Enttäuschtes Gesicht"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Besorgtes Gesicht"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Verärgertes Gesicht"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Schmollendes Gesicht"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Weinendes Gesicht"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Hartnäckiges Gesicht"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Triumphierendes Gesicht"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Enttäuschtes, aber erleichtertes Gesicht"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Stirnrunzelndes Gesicht mit offenem Mund"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Schmerzgeplagtes Gesicht"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Ängstliches Gesicht"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Erschöpftes Gesicht"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Schläfriges Gesicht"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Müdes Gesicht"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimassen schneidendes Gesicht"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Heftig weinendes Gesicht"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Gesicht mit offenem Mund"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Sprachloses Gesicht"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Gesicht mit offenem Mund und Angstschweiß"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Vor Angst schreiendes Gesicht"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Erstauntes Gesicht"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Errötetes Gesicht"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Schlafendes Gesicht"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Schwindeliges Gesicht"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Gesicht ohne Mund"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Gesicht mit Mundschutz"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Grinsendes Katzengesicht mit lächelnden Augen"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Katzengesicht mit Freudentränen"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Lächelndes Katzengesicht mit offenem Mund"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Lächelndes Katzengesicht mit herzförmigen Augen"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Katzengesicht mit schiefem Lächeln"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Küssendes Katzengesicht mit geschlossenen Augen"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Schmollendes Katzengesicht"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Weinendes Katzengesicht"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Erschöpftes Katzengesicht"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Gesicht mit Nicht in Ordnung-Geste"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Gesicht mit OK-Geste"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Sich tief verneigende Person"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Nichts-Sehen-Affe"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Nichts-Hören-Affe"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Nichts-Sagen-Affe"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Glückliche Person mit einer erhobenen Hand"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person streckt vor Freude die Arme in die Höhe"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Stirnrunzelnde Person"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Person mit schmollendem Gesicht"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person mit gefalteten Händen"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rakete"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Hubschrauber"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Dampflokomotive"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Eisenbahnwaggon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Hochgeschwindigkeitszug"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Hochgeschwindigkeitszug mit abgerundeter Spitze"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Zug"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"U-Bahn"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Stadtahn"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Haltestelle"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Straßenbahn"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Straßenbahnwagen"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Entgegenkommender Bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Oberleitungsbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bushaltestelle"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Krankenwagen"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Feuerwehrauto"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Polizeiauto"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Entgegenkommendes Polizeiauto"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Entgegenkommendes Taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"PKW"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Entgegenkommender PKW"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Wohnmobil"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"LKW"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Sattelschlepper"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Einschienenbahn"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Bergbahn"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Schwebebahn"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Seilbahn"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Pendelseilbahn"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Schiff"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Ruderboot"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Schnellboot"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontale Ampel"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikale Ampel"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Baustellenschild"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Polizeiblaulicht"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Dreieckige Flagge an Fahnenmast"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Tür"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Zeichen für \"Kein Zutritt\""</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Symbol für \"Rauchen erlaubt\""</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Symbol für \"Rauchen verboten\""</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Symbol für \"Müll in Abfalleimer\""</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Symbol für \"Bitte sauber halten\""</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbol für Trinkwasser"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbol für \"Kein Trinkwasser\""</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Fahrrad"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Symbol für \"Radfahren verboten\""</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Radfahrer"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountainbiker"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Fußgänger"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Symbol für \"Keine Fußgänger\""</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Symbol für \"Kinder unterwegs\""</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbol für \"Herren\""</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbol für \"Damen\""</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Symbol für \"Toiletten\""</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Symbol für \"Baby\""</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilette"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC-Symbol"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dusche"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bad"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badewanne"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Symbol für Passkontrolle"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Symbol für Zollabfertigung"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Symbol für Gepäckausgabe"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Symbol für Gepäckaufbewahrung"</string>
+</resources>
diff --git a/java/res/values-de/strings-talkback-descriptions.xml b/java/res/values-de/strings-talkback-descriptions.xml
index 27e9ecc..469267b 100644
--- a/java/res/values-de/strings-talkback-descriptions.xml
+++ b/java/res/values-de/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Kein Text eingegeben"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Mit <xliff:g id="KEY_NAME">%1$s</xliff:g> wird \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" in \"<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>\" geändert."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Mit <xliff:g id="KEY_NAME">%1$s</xliff:g> erfolgt eine Autokorrektur."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Kein Vorschlag"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Unbekanntes Zeichen"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Umschalttaste"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Weitere Symbole"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Großbuchstabe I mit übergesetztem Punkt"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unbekanntes Symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unbekanntes Emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Gelangweiltes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Verlegenes Gesicht"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gesicht mit Sonnenbrille"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Überraschtes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Küssendes Gesicht"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Finsteres Gesicht"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Es sind Alternativzeichen verfügbar."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativzeichen werden ausgeblendet."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Es sind Alternativvorschläge verfügbar."</string>
diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml
index ece1a20..bbee769 100644
--- a/java/res/values-de/strings.xml
+++ b/java/res/values-de/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Bei Tastendruck vibrieren"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Ton bei Tastendruck"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bei Tastendruck"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Einstellungen"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Konten &amp; Datenschutz"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Darstellung &amp; Layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Bewegungseingabe"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Textkorrektur"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Erweitert"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Design"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Geteilte Tastatur aktivieren"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-Tastatur-Synchronisierung"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Die Synchronisierung ist aktiviert."</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Persönliches Wörterbuch geräteübergreifend synchronisieren"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Jetzt synchronisieren"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Cloud-Daten löschen"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Löscht Ihre synchronisierten Daten aus Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Die synchronisierten Daten werden aus der Cloud gelöscht. Sicher?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Löschen"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Abbrechen"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Ihr persönliches Wörterbuch wird mit den Google-Servern synchronisiert und auf diesen Servern gesichert. Zur Verbesserung unserer Produkte werden eventuell statistische Daten zur Worthäufigkeit erfasst. Die Erfassung und Nutzung sämtlicher Daten erfolgt gemäß der "<a href="https://www.google.com/policies/privacy">"Datenschutzerklärung von Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Zur Aktivierung dieser Funktion Google-Konto zu Gerät hinzufügen"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Eingabemethoden wechseln"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Sprachwechseltaste umfasst auch andere Eingabemethoden."</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Sprachwechsel"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Anzeigen, wenn mehrere Eingabesprachen aktiviert sind"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Ziehbewegung anzeigen"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Ziehen mit gedrückter Symboltaste oder Shift visuell darstellen"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tasten-Pop-up"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Keine Verzögerung"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Allgemeines Wörterbuch"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Änderungsvorschläge"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vorgeschlagene Wörter während des Tippens anzeigen"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Immer anzeigen"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Im Hochformat anzeigen"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nie anzeigen"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Anstößige Wörter sperren"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Keine potenziell anstößigen Wörter vervollständigen"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autokorrektur"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Taste für Spracheingabe"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Keine Spracheingabemethoden aktiviert. Rufen Sie die Einstellungen für \"Sprache &amp; Eingabe\" auf."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Feedback geben"</string>
-    <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Sprachen"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hilfe &amp; Feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Sprachen"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tippen Sie hier zum Speichern."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturdesign"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Konto wechseln"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Keine Konten ausgewählt"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Momentan wird <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> verwendet."</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Abbrechen"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Abmelden"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Zu verwendendes Konto auswählen"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Englisch (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Englisch (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanisch (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbisch (Lateinisch)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Englisch (GB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Englisch (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanisch (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisch (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisch)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lateinisch)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Keine Sprache (lat. Alphabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Lat. Alphabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Lat. Alphabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Lat. Alphabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Lat. Alphabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tastaturdesign"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Benutzerdefinierte Eingabestile"</string>
     <string name="add_style" msgid="6163126614514489951">"Stil hinzufügen"</string>
     <string name="add" msgid="8299699805688017798">"Hinzufügen"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktivieren"</string>
     <string name="not_now" msgid="6172462888202790482">"Später"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Der gleiche Eingabestil ist bereits vorhanden: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Verzögerung für langes Drücken"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrationsdauer bei Tastendruck"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Tonlautstärke bei Tastendruck"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Externe Wörterbuchdatei lesen"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Keine Wörterbuchdateien im Ordner \"Downloads\""</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Wörterbuchdatei zum Installieren auswählen"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Möchten Sie diese Datei für <xliff:g id="LANGUAGE_NAME">%s</xliff:g> installieren?"</string>
-    <string name="error" msgid="8940763624668513648">"Es ist ein Fehler aufgetreten"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Verzögerung für langes Drücken"</string>
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Willkommen bei <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"mit Bewegungseingabe"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Jetzt können Sie in allen Ihren Lieblings-Apps über <xliff:g id="APPLICATION_NAME">%s</xliff:g> Text eingeben."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Weitere Sprachen konfigurieren"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Fertig"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"App-Symbol anzeigen"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"App-Symbol in der Übersicht anzeigen"</string>
     <string name="app_name" msgid="6320102637491234792">"Wörterbuchbereitstellung"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Wörterbuchbereitstellung"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Wörterbuch"</string>
diff --git a/java/res/values-el/donottranslate-config-spacing-and-punctuations.xml b/java/res/values-el/donottranslate-config-spacing-and-punctuations.xml
new file mode 100644
index 0000000..117c075
--- /dev/null
+++ b/java/res/values-el/donottranslate-config-spacing-and-punctuations.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Symbols that terminate sentences and require capitalization on the next char -->
+    <string name="symbols_sentence_terminators">.;!?</string>
+</resources>
diff --git a/java/res/values-el/strings-emoji-descriptions.xml b/java/res/values-el/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..a15d0fd
--- /dev/null
+++ b/java/res/values-el/strings-emoji-descriptions.xml
@@ -0,0 +1,853 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Σύμβολο πνευματικών δικαιωμάτων"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Σύμβολο κατατεθέντος"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Διπλό θαυμαστικό"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Θαυμαστικό ερωτηματικό"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Σύμβολο εμπορικού σήματος"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Πηγή πληροφοριών"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Αριστερό-δεξί βέλος"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Επάνω-κάτω βέλος"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Βορειοδυτικό βέλος"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Βορειοανατολικό βέλος"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Νοτιοανατολικό βέλος"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Νοτιοδυτικό βέλος"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Βέλος προς τα αριστερά με κλείσιμο"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Βέλος προς τα δεξιά με κλείσιμο"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Ρολόι"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Κλεψύδρα"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Δύο μαύρα τρίγωνα που δείχνουν προς τα δεξιά"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Δύο μαύρα τρίγωνα που δείχνουν προς τα αριστερά"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Δύο μαύρα τρίγωνα που δείχνουν προς τα επάνω"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Δύο μαύρα τρίγωνα που δείχνουν προς τα κάτω"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Ξυπνητήρι"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Κλεψύδρα με άμμο που ρέει"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Λατινικό κεφαλαίο γράμμα M σε κύκλο"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Μαύρο μικρό τετράγωνο"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Λευκό μικρό τετράγωνο"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Μαύρο τρίγωνο που δείχνει προς τα δεξιά"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Μαύρο τρίγωνο που δείχνει προς τα αριστερά"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Τετράγωνο με λευκό εσωτερικό"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Τετράγωνο με μαύρο εσωτερικό"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Μικρό τετράγωνο με λευκό εσωτερικό"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Μικρό τετράγωνο με μαύρο εσωτερικό"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Μαύρος ήλιος με ακτίνες"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Σύννεφο"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Μαύρο τηλέφωνο"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Κουτάκι με τσεκάρισμα"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Ομπρέλα με σταγόνες βροχής"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Ζεστό ρόφημα"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Λευκός δείκτης που δείχνει προς τα επάνω"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Λευκό χαμογελαστό πρόσωπο"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Κριός"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Ταύρος"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Δίδυμοι"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Καρκίνος"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Λέων"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Παρθένος"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Ζυγός"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Σκορπιός"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Τοξότης"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Αιγόκερως"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Υδροχόος"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ιχθείς"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Μαύρο μπαστούνι"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Μαύρο σπαθί"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Μαύρη κούπα"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Μαύρο καρό"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Θερμές πηγές"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Μαύρο γενικό σύμβολο ανακύκλωσης"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Σύμβολο αναπηρικής καρέκλας"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Άγκυρα"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Προειδοποιητικό σήμα"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Σύμβολο υψηλής τάσης"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Κύκλος με λευκό εσωτερικό"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Κύκλος με μαύρο εσωτερικό"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Μπάλα ποδοσφαίρου"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Μπάλα μπέιζμπολ"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Χιονάνθρωπος χωρίς χιόνι"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Ήλιος πίσω από σύννεφο"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Οφιούχος"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Απαγορεύεται η είσοδος"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Εκκλησία"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Σιντριβάνι"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Σημαιάκι σε τρύπα"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Ιστιοπλοϊκό"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Σκηνή"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Αντλία βενζίνης"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Μαύρο ψαλίδι"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Λευκό έντονο σημάδι ολοκλήρωσης"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Αεροπλάνο"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Φάκελος"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Υψωμένη γροθιά"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Υψωμένο χέρι"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Σήμα νίκης"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Μολύβι"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Μαύρη μύτη πένας"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Έντονο σημάδι ολοκλήρωσης"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Έντονο σύμβολο πολλαπλασιασμού Χ"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Αστεράκια που ακτινοβολούν"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Αστερίσκος οκτώ ακτίνων"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Μαύρο αστέρι οκτώ ακτίνων"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Νιφάδα χιονιού"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Αστεράκι που ακτινοβολεί"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Σύμβολο \"Χ\""</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Αρνητικό σύμβολο \"Χ\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Μαύρο διακοσμητικό ερωτηματικό"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Λευκό διακοσμητικό ερωτηματικό"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Λευκό διακοσμητικό θαυμαστικό"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Έντονο σύμβολο θαυμαστικού"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Έντονες μαύρες κούπες"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Έντονο σύμβολο του \"συν\""</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Έντονο σύμβολο του \"μείον\""</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Έντονο σύμβολο διαίρεσης"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Μαύρο βέλος προς τα δεξιά"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Καμπυλωτή θηλιά"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Διπλή καμπυλωτή θηλιά"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Βέλος που δείχνει προς τα δεξιά και έπειτα στρίβει προς τα πάνω"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Βέλος που δείχνει προς τα δεξιά και έπειτα στρίβει προς τα κάτω"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Μαύρο βέλος προς τα αριστερά"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Μαύρο βέλος προς τα πάνω"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Μαύρο βέλος προς τα κάτω"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Μαύρο μεγάλο τετράγωνο"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Λευκό μεγάλο τετράγωνο"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Αστέρι με λευκό εσωτερικό"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Έντονος μεγάλος κύκλος"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Κυματιστή παύλα"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Σημάδι εναλλαγής μέρους"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ιδεογράφημα σε κύκλο \"συγχαρητήρια\""</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ιδεογράφημα σε κύκλο \"μυστικό\""</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Πλακίδιο Mahjong με κόκκινο δράκο"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Χαρτί τράπουλας με μαύρο μπαλαντέρ"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Ομάδα αίματος Α"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Ομάδα αίματος Β"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Ομάδα αίματος Ο"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Χώρος στάθμευσης"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Ομάδα αίματος ΑΒ"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"\"CL\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"\"Cool\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"\"Free\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"\"ID\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"\"New\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"\"NG\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"\"OK\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"\"SOS\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"\"Up\" με θαυμαστικό σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"\"VS\" σε τετράγωνο"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Γράμμα Katakana σε τετράγωνο \"εδώ\""</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Γράμμα Katakana σε τετράγωνο \"υπηρεσία\""</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ιδεογράφημα σε τετράγωνο \"δωρεάν\""</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ιδεογράφημα σε τετράγωνο \"κρατημένη θέση\""</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ιδεογράφημα σε τετράγωνο \"απαγόρευση\""</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ιδεογράφημα σε τετράγωνο \"κενή θέση\""</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ιδεογράφημα σε τετράγωνο \"αποδοχή\""</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for spoken_emoji_1F235 (5320186982841793711) -->
+    <skip />
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ιδεογράφημα σε τετράγωνο \"πληρώθηκε\""</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ιδεογράφημα σε τετράγωνο \"μηνιαίως\""</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ιδεογράφημα σε τετράγωνο \"εφαρμογή\""</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ιδεογράφημα σε τετράγωνο \"έκπτωση\""</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ιδεογράφημα σε τετράγωνο \"ανοίξαμε\""</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ιδεογράφημα σε κύκλο \"πλεονέκτημα\""</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ιδεογράφημα σε κύκλο \"αποδοχή\""</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Κυκλώνας"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Ομιχλώδης"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Κλειστή ομπρέλα"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Νύχτα με αστέρια"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Ανατολή του ηλίου πίσω από τα βουνά"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Ανατολή ηλίου"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Περίγραμμα πόλης το σούρουπο"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Ηλιοβασίλεμα πίσω από κτίρια"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Ουράνιο τόξο"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Γέφυρα τη νύχτα"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Κύμα νερού"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Ηφαίστειο"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Γαλαξίας"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Υδρόγειος Ευρώπη-Αφρική"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Υδρόγειος Αμερική"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Υδρόγειος Ασία-Αυστραλία"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Υδρόγειος με μεσημβρινούς"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Σύμβολο νέας σελήνης"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Σύμβολο σελήνης αύξουσας, πριν από το πρώτο τέταρτο"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Σύμβολο σελήνης πρώτου τετάρτου"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Σύμβολο σελήνης αύξουσας, πριν από την πανσέληνο"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Σύμβολο πανσελήνου"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Σύμβολο σελήνης φθίνουσας, πριν από το τελευταίο τέταρτο"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Σύμβολο σελήνης τελευταίου τετάρτου"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Σύμβολο σελήνης φθίνουσας, πριν από τη νέα σελήνη"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Ημισέληνος"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Νέα σελήνη με πρόσωπο"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Σελήνη πρώτου τετάρτου με πρόσωπο"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Σελήνη τελευταίου τετάρτου με πρόσωπο"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Πανσέληνος με πρόσωπο"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Ήλιος με πρόσωπο"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Λαμπερό αστέρι"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Πεφταστέρι"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Κάστανο"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Δενδρύλλιο"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Αειθαλές δέντρο"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Φυλλοβόλο δέντρο"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Φοίνικας"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Κάκτος"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Τουλίπα"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Άνθος κερασιάς"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Τριαντάφυλλο"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Ιβίσκος"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Ηλιοτρόπιο"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Άνθος"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Στάχυ καλαμποκιού"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Στάχυ ρυζιού"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Γρασίδι"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Τετράφυλλο τριφύλλι"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Φύλλο σφενδάμου"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Πεσμένο φύλλο"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Φύλλο που πετάει στον άνεμο"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Μανιτάρι"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Ντομάτα"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Μελιτζάνα"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Σταφύλια"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Πεπόνι"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Καρπούζι"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Μανταρίνι"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Λεμόνι"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Μπανάνα"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ανανάς"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Κόκκινο μήλο"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Πράσινο μήλο"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Αχλάδι"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Ροδάκινο"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Κεράσια"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Φράουλα"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Χάμπουργκερ"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Κομμάτι πίτσας"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Κρέας σε κόκαλο"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Μπούτι πουλερικού"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Ρυζογκοφρέτα"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Μπαλάκι ρυζιού"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Μαγειρεμένο ρύζι"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Κάρι και ρύζι"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Αχνιστό μπολ"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Σπαγγέτι"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Ψωμί"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Τηγανητές πατάτες"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Ψητή γλυκοπατάτα"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Ντάνγκο"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Όντεν"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Σούσι"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Τηγανητή γαρίδα"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Ψαροκεφτές με σχέδιο δίνης"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Μαλακό παγωτό"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Τριμμένος πάγος"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Παγωτό"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Ντόνατ"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Κούκι"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Σοκολάτα"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Γλυκά"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Κρέμα"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Βάζο με μέλι"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Μπισκότο"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Κουτί γεύματος"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Κατσαρόλα με φαγητό"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Μαγείρεμα"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Πιρούνι και μαχαίρι"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Φλιτζάνι τσαγιού χωρίς χερούλι"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Μπουκάλι και ποτήρι σακέ"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Ποτήρι κρασιού"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Ποτήρι κοκτέιλ"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Τροπικό ποτό"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Ποτήρι μπύρας"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Ποτήρια μπύρας που τσουγκρίζουν"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Μπιμπερό"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Κορδέλα"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Τυλιγμένο δώρο"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Τούρτα γενεθλίων"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Σκαλισμένο πρόσωπο σε κολοκύθα"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Χριστουγεννιάτικο δέντρο"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Άγιος Βασίλης"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Πυροτεχνήματα"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Στικάκι με σπίθες"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Μπαλόνι"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Εκτοξευτήρας για πάρτι"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Μπάλα με κομφετί"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Διακοσμημένο δέντρο"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Διασταυρωμένες σημαίες"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Στολίδια πεύκου"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Ιαπωνικές κούκλες"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Αιωρούμενα ψαράκια"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Μελωδός"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Εορτασμός θέασης της σελήνης"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Σχολική τσάντα"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Καπέλο αποφοίτησης"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Ξύλινο αλογάκι"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Τροχός λούνα παρκ"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Τρενάκι λούνα παρκ"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Καλάμι ψαρέματος και ψάρι"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Μικρόφωνο"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Κινηματογραφική κάμερα"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Κινηματογράφος"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Ακουστικά"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Παλέτα καλλιτέχνη"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Ημίψηλο"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Tσίρκο"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Εισιτήριο"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Κλακέτα"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Παραστατικές τέχνες"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Βιντεοπαιχνίδι"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Απευθείας κρούση"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Κουλοχέρης"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Μπιλιάρδο"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Ζάρια παιχνιδιού"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Μπόουλινγκ"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Τράπουλα με λουλούδια"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Μουσική νότα"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Πολλές μουσικές νότες"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Σαξόφωνο"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Κιθάρα"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Αρμόνιο"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Τρομπέτα"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Βιολί"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Παρτιτούρα"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Μπλουζάκι με κορδέλα"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Ρακέτα και μπαλάκι τένις"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Σκι και μποτάκι του σκι"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Καλάθι και στεφάνη μπάσκετ"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Καρό σημαία"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Αθλητής του σνόουμπορντ"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Δρομέας"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Σέρφερ"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Τρόπαιο"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Ιπποδρομίες"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Αμερικανικό ποδόσφαιρο"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ράγκμπι"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Κολυμβητής"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Πολυκατοικία"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Σπίτι με κήπο"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Κτίριο γραφείων"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Ιαπωνικό ταχυδρομείο"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Ευρωπαϊκό ταχυδρομείο"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Νοσοκομείο"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Τράπεζα"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ΑΤΜ"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Ξενοδοχείο"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Ξενοδοχείο για ζευγάρια"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Ψιλικατζίδικο"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Σχολείο"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Πολυκατάστημα"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Εργοστάσιο"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Φανάρι Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Ιαπωνικό κάστρο"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Ευρωπαϊκό κάστρο"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Αρουραίος"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Ποντίκι"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Βόδι"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Νεροβούβαλος"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Αγελάδα"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Λεοπάρδαλη"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Κουνέλι"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Γάτα"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Δράκος"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Κροκόδειλος"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Φάλαινα"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Σαλιγκάρι"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Φίδι"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Άλογο"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Κριάρι"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Κατσίκα"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Πρόβατο"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Μαϊμού"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Κόκορας"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Κοτόπουλο"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Σκύλος"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Γουρούνι"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Αγριογούρουνο"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Ελέφαντας"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Χταπόδι"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Κοχύλι"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Έντομο"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Μυρμήγκι"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Μέλισσα"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Πασχαλίτσα"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Ψάρι"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Τροπικό ψάρι"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Μπαλονόψαρο"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Χελώνα"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Εκκολαπτόμενος νεοσσός"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Νεοσσός"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Νεοσσός σε ανφάς"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Πουλί"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Πιγκουίνος"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Κοάλα"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Πουντλ"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Καμήλα δρομάς"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Βακτριανή καμήλα"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Δελφίνι"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Πρόσωπο ποντικιού"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Πρόσωπο αγελάδας"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Πρόσωπο τίγρης"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Πρόσωπο κουνελιού"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Πρόσωπο γάτας"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Πρόσωπο δράκου"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Φάλαινα που εκτοξεύει νερό"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Πρόσωπο αλόγου"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Πρόσωπο μαϊμούς"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Πρόσωπο σκύλου"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Πρόσωπο γουρουνιού"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Πρόσωπο βατράχου"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Πρόσωπο χάμστερ"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Πρόσωπο λύκου"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Πρόσωπο αρκούδας"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Πρόσωπο πάντα"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Μουσούδι γουρουνιού"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Αποτυπώματα πατούσας ζώου"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Μάτια"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Αυτί"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Μύτη"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Στόμα"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Γλώσσα"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Λευκός δείκτης χεριού που δείχνει προς τα επάνω"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Λευκός δείκτης χεριού που δείχνει προς τα κάτω"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Λευκός δείκτης χεριού που δείχνει προς τα αριστερά"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Λευκός δείκτης χεριού που δείχνει προς τα δεξιά"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Σήμα γροθιάς"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Σήμα χεριού που χαιρετάει"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Σήμα χεριού που λέει \"OK\""</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Σήμα \"Μου αρέσει\""</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Σήμα \"Δεν μου αρέσει\""</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Σήμα χεριών που χειροκροτούν"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Σήμα ανοιχτών χεριών"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Κορώνα"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Γυναικείο καπέλο"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Γυαλιά όρασης"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Γραβάτα"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Μπλουζάκι"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Τζιν"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Φόρεμα"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Κιμονό"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Μπικίνι"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Γυναικεία ρούχα"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Γυναικείο τσαντάκι"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Τσάντα"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Τσαντάκι"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Ανδρικό παπούτσι"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Αθλητικό παπούτσι"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Ψηλοτάκουνο παπούτσι"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Γυναικείο σανδάλι"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Γυναικείες μπότες"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Αποτυπώματα"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Περίγραμμα άνω κορμού"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Περίγραμμα άνω κορμών"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Αγόρι"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Κορίτσι"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Άνδρας"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Γυναίκα"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Οικογένεια"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Άνδρας και γυναίκα χέρι-χέρι"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Δύο άνδρες χέρι-χέρι"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Δύο γυναίκες χέρι-χέρι"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Αστυνομικός"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Γυναίκα με αυτιά κουνελιού"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Νύφη με πέπλο"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Ξανθό άτομο"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Άνδρας με κασκέτο gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Άνδρας με τουρμπάνι"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Ηλικιωμένος άνδρας"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Ηλικιωμένη γυναίκα"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Μωρό"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Οικοδόμος"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Πριγκίπισσα"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ιαπωνικός δράκος"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Ιαπωνικός καλικάντζαρος"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Φάντασμα"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Αγγελάκι"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Εξωγήινος"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Εξωγήινο τέρας"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Διαβολάκι"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Νεκροκεφαλή"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Ρεσεψιονίστ"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Φύλακας"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Χορευτής"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Κραγιόν"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Βερνίκι νυχιών"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Μασάζ προσώπου"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Κούρεμα"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Σήμα κουρείου"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Σύριγγα"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Χάπι"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Αποτύπωμα χειλιών"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Ερωτική επιστολή"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Δαχτυλίδι"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Πολύτιμος λίθος"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Φιλί"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Μπουκέτο"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Ζευγάρι με καρδιά"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Γάμος"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Καρδιά που πάλλεται"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Ραγισμένη καρδιά"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Δύο καρδιές"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Απαστράπτουσα καρδιά"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Καρδιά που μεγαλώνει"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Καρδιά με βέλος"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Μπλε καρδιά"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Πράσινη καρδιά"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Κίτρινη καρδιά"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Μωβ καρδιά"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Καρδιά με κορδέλα"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Καρδούλες που στριφογυρίζουν"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Διακοσμητική καρδιά"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Σχήμα διαμαντιού με τελεία"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Ηλεκτρικός λαμπτήρας"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Σύμβολο θυμού"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Βόμβα"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Σύμβολο ύπνου"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Σύμβολο σύγκρουσης"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Σύμβολο πιτσιλίσματος ιδρώτα"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Σταγονίδιο"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Σύμβολο παύλας"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Σωρός από κακά"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Δικέφαλος σε κάμψη"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Σύμβολο ζαλάδας"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Συννεφάκι ομιλίας"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Συννεφάκι σκέψης"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Λευκό λουλούδι"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Σύμβολο εκατό βαθμών"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Σάκος χρημάτων"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Συνάλλαγμα"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Έντονο σήμα δολαρίου"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Πιστωτική κάρτα"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Χαρτονόμισμα με σήμα γεν"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Χαρτονόμισμα με σήμα δολαρίου"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Χαρτονόμισμα με σήμα ευρώ"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Χαρτονόμισμα με σήμα στερλίνας"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Χρήματα με φτερά"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Πίνακας με ανοδική τάση και σήμα γεν"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Κάθισμα"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Προσωπικός υπολογιστής"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Χαρτοφύλακας"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Μίνι δίσκος"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Δισκέτα"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Οπτικός δίσκος"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Φάκελος αρχείων"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ανοιχτός φάκελος αρχείων"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Ζαρωμένη σελίδα"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Σελίδα προς τα επάνω"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Ημερολόγιο"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Ημερολόγιο με φυλλαράκια"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Ευρετήριο καρτών"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Πίνακας με ανοδική τάση"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Πίνακας με πτωτική τάση"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Γράφημα ράβδων"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Πρόχειρο"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Πινέζα"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Στρογγυλή πινέζα"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Συνδετήρας"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Χάρακας"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Τρίγωνο"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Σελιδοδείκτες"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Λογιστικό βιβλίο"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Σημειωματάριο"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Σημειωματάριο με διακοσμητικό εξώφυλλο"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Κλειστό βιβλίο"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Ανοιχτό βιβλίο"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Πράσινο βιβλίο"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Μπλε βιβλίο"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Πορτοκαλί βιβλίο"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Βιβλία"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Καρτελάκι ονόματος"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Περγαμηνή"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Σημείωμα"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Ακουστικό τηλεφώνου"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Βομβητής"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Μηχάνημα φαξ"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Δορυφορική κεραία"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Μεγάφωνο"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ντουντούκα"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Δίσκος εξερχομένων"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Δίσκος εισερχομένων"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Πακέτο"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Σύμβολο ηλεκτρονικού ταχυδρομείου"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Εισερχόμενος φάκελος"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Φάκελος με κάτω βέλος από πάνω"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Κλειστό γραμματοκιβώτιο με κατεβασμένο σημαιάκι"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Κλειστό γραμματοκιβώτιο με κατεβασμένο σημαιάκι"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Ανοιχτό γραμματοκιβώτιο με ανεβασμένο σημαιάκι"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Ανοιχτό γραμματοκιβώτιο με κατεβασμένο σημαιάκι"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Γραμματοκιβώτιο"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Ταχυδρομική κόρνα"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Εφημερίδα"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Κινητό τηλέφωνο"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Κινητό τηλέφωνο με δεξί βέλος στα αριστερά"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Λειτουργία δόνησης"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Απενεργοποιημένο κινητό τηλέφωνο"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Δεν επιτρέπονται τα κινητά τηλέφωνα"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Κεραία με ράβδους"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Φωτογραφική μηχανή"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Βιντεοκάμερα"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Τηλεόραση"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Ραδιόφωνο"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Βιντεοκασέτα"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Στριφτά βέλη προς τα δεξιά"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Δεξιόστροφο αριστερό και δεξί βέλος σε ανοιχτό κύκλο"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Δεξιόστροφο αριστερό και δεξί βέλος σε ανοιχτό κύκλο με προσθήκη του αριθμού ένα εντός κύκλου"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Δεξιόστροφο κάτω και άνω βέλος σε ανοιχτό κύκλο"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Αριστερόστροφο κάτω και άνω βέλος σε ανοιχτό κύκλο"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Σύμβολο χαμηλής φωτεινότητας"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Σύμβολο υψηλής φωτεινότητας"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Ηχείο με διαγραφή"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Ηχείο"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Ηχείο με ένα ηχητικό κύμα"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Ηχείο με τρία ηχητικά κύματα"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Μπαταρία"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Πρίζα"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Μεγεθυντικός φακός που δείχνει προς τα αριστερά"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Μεγεθυντικός φακός που δείχνει προς τα δεξιά"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Κλειδαριά με κονδυλοφόρο"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Κλειστή κλειδαριά με κλειδί"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Κλειδί"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Κλειδαριά"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Ανοιχτή κλειδαριά"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Καμπανάκι"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Καμπανάκι με διαγραφή"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Σελιδοδείκτης"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Σύμβολο σύνδεσης"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Κουμπί επιλογής"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Ένδειξη \"Back\" με βέλος προς τα αριστερά από πάνω"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Ένδειξη \"End\" με βέλος προς τα αριστερά από πάνω"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Ένδειξη \"On\" με θαυμαστικό με αριστερό-δεξί βέλος από πάνω"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Ένδειξη \"Soon\" με βέλος προς τα δεξιά από πάνω"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Ένδειξη \"Top\" με άνω βέλος από πάνω"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Σύμβολο απαγόρευσης κάτω των δεκαοκτώ"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Πλήκτρο με τον αριθμό 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Σύμβολο εισαγωγής για λατινικά κεφαλαία γράμματα"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Σύμβολο εισαγωγής για λατινικά μικρά γράμματα"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Σύμβολο εισαγωγής για αριθμούς"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Σύμβολο εισαγωγής συμβόλων"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Σύμβολο εισαγωγής για λατινικά γράμματα"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Φωτιά"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Φακός"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Γαλλικό κλειδί"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Σφυρί"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Παξιμάδι και μπουλόνι"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Μαχαίρι Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Πιστόλι"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Μικροσκόπιο"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Τηλεσκόπιο"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Κρυστάλλινη σφαίρα"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Αστέρι με έξι μύτες και τελεία στη μέση"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Ιαπωνικό σύμβολο για αρχάριο"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Έμβλημα τρίαινας"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Μαύρο τετράγωνο κουμπί"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Λευκό τετράγωνο κουμπί"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Μεγάλος κόκκινος κύκλος"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Μεγάλος μπλε κύκλος"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Μεγάλος πορτοκαλί ρόμβος"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Μεγάλος μπλε ρόμβος"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Μικρός πορτοκαλί ρόμβος"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Μικρός μπλε ρόμβος"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Κόκκινο τρίγωνο που δείχνει προς τα επάνω"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Κόκκινο τρίγωνο που δείχνει προς τα κάτω"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Μικρό κόκκινο τρίγωνο που δείχνει προς τα επάνω"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Μικρό κόκκινο τρίγωνο που δείχνει προς τα κάτω"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Μπροστινή όψη ρολογιού μία η ώρα"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Μπροστινή όψη ρολογιού δύο η ώρα"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Μπροστινή όψη ρολογιού τρεις η ώρα"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Μπροστινή όψη ρολογιού τέσσερις η ώρα"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Μπροστινή όψη ρολογιού πέντε η ώρα"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Μπροστινή όψη ρολογιού έξι η ώρα"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Μπροστινή όψη ρολογιού επτά η ώρα"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Μπροστινή όψη ρολογιού οκτώ η ώρα"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Μπροστινή όψη ρολογιού εννέα η ώρα"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Μπροστινή όψη ρολογιού δέκα η ώρα"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Μπροστινή όψη ρολογιού έντεκα η ώρα"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Μπροστινή όψη ρολογιού δώδεκα η ώρα"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Μπροστινή όψη ρολογιού μία και μισή"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Μπροστινή όψη ρολογιού δύο και μισή"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Μπροστινή όψη ρολογιού τρεις και μισή"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Μπροστινή όψη ρολογιού τέσσερις και μισή"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Μπροστινή όψη ρολογιού πέντε και μισή"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Μπροστινή όψη ρολογιού έξι και μισή"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Μπροστινή όψη ρολογιού επτά και μισή"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Μπροστινή όψη ρολογιού οκτώ και μισή"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Μπροστινή όψη ρολογιού εννέα και μισή"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Μπροστινή όψη ρολογιού δέκα και μισή"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Μπροστινή όψη ρολογιού έντεκα και μισή"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Μπροστινή όψη ρολογιού δώδεκα και μισή"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Όρος Φούτζι"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Πύργος του Τόκιο"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Άγαλμα της Ελευθερίας"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Περίγραμμα της Ιαπωνίας"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Πέτρινο άγαλμα Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Γελαστό πρόσωπο"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Γελαστό πρόσωπο με χαμογελαστά μάτια"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Πρόσωπο γάτας με δάκρυα χαράς"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Χαμογελαστό πρόσωπο με ανοιχτό στόμα"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Χαμογελαστό πρόσωπο με ανοιχτό στόμα και χαμογελαστά μάτια"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Χαμογελαστό πρόσωπο με ανοιχτό στόμα και κρύο ιδρώτα"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Χαμογελαστό πρόσωπο με ανοιχτό στόμα και ερμητικά κλειστά μάτια"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Χαμογελαστό πρόσωπο με φωτοστέφανο"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Χαμογελαστό πρόσωπο με κερατάκια"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Πρόσωπο που κλείνει το μάτι"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Χαμογελαστό πρόσωπο με χαμογελαστά μάτια"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Πρόσωπο που δοκιμάζει νόστιμο φαγητό"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Ανακουφισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Χαμογελαστό πρόσωπο με μάτια-καρδούλες"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Χαμογελαστό πρόσωπο με γυαλιά ηλίου"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Πρόσωπο με επιτηδευμένο χαμόγελο"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Ουδέτερο πρόσωπο"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Ανέκφραστο πρόσωπο"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Πρόσωπο που δεν δείχνει να διασκεδάζει"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Πρόσωπο με κρύο ιδρώτα"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Σκεπτικό πρόσωπο"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Μπερδεμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Αποσβολωμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Πρόσωπο που δίνει φιλί"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Πρόσωπο που στέλνει φιλί"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Πρόσωπο που δίνει φιλί με χαμογελαστά μάτια"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Πρόσωπο που δίνει φιλί με κλειστά μάτια"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Πρόσωπο με τη γλώσσα έξω"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Πρόσωπο που κλείνει το μάτι με τη γλώσσα έξω"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Πρόσωπο με ερμητικά κλειστά μάτια και τη γλώσσα έξω"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Απογοητευμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Ανήσυχο πρόσωπο"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Θυμωμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Μουτρωμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Πρόσωπο που κλαίει"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Καρτερικό πρόσωπο"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Πρόσωπο με βλέμμα θριάμβου"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Απογοητευμένο αλλά ανακουφισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Σκυθρωπό πρόσωπο με ανοιχτό στόμα"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Πρόσωπο αγωνίας"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Φοβισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Εξαντλημένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Νυσταγμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Κουρασμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Πρόσωπο που κάνει γκριμάτσα"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Πρόσωπο που κλαίει δυνατά"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Πρόσωπο με ανοιχτό στόμα"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Σιωπηλό πρόσωπο"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Πρόσωπο με ανοιχτό στόμα και κρύο ιδρώτα"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Πρόσωπο που ουρλιάζει από φόβο"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Κατάπληκτο πρόσωπο"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Αναψοκοκκινισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Κοιμισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Ζαλισμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Πρόσωπο χωρίς στόμα"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Πρόσωπο με ιατρική μάσκα"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Γελαστό πρόσωπο γάτας με χαμογελαστά μάτια"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Πρόσωπο γάτας με δάκρυα χαράς"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Χαμογελαστό πρόσωπο γάτας με ανοιχτό στόμα"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Χαμογελαστό πρόσωπο γάτας με μάτια-καρδούλες"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Πρόσωπο γάτας με πικρό χαμόγελο"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Πρόσωπο γάτας που δίνει φιλί με κλειστά μάτια"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Μουτρωμένο πρόσωπο γάτας"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Πρόσωπο γάτας που κλαίει"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Εξαντλημένο πρόσωπο γάτας"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Πρόσωπο με χειρονομία \"Δεν είναι καλό\""</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Πρόσωπο με χειρονομία \"OK\""</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Άτομο που υποκλίνεται βαθιά"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Μαϊμού \"Δεν είδα τίποτα\""</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Μαϊμού \"Δεν άκουσα τίποτα\""</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Μαϊμού \"Δεν λέω τίποτα\""</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Χαρούμενο άτομο που σηκώνει ένα χέρι"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Άτομο που σηκώνει και τα δύο χέρια σε σήμα εορτασμού"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Άτομο που κατσουφιάζει"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Άτομο με μουτρωμένο πρόσωπο"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Άτομο με σταυρωμένα χέρια"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Πύραυλος"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Ελικόπτερο"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Ατμομηχανή"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Βαγόνι τρένου"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Τρένο υψηλής ταχύτητας"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Τρένο υψηλής ταχύτητας με μυτερή πρόσοψη"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Τρένο"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Μετρό"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Ελαφρύς σιδηρόδρομος"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Σταθμός"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Τραμ"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Βαγόνι τραμ"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Λεωφορείο"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Ερχόμενο λεωφορείο"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Τρόλεϊ"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Στάση λεωφορείου"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Μικρό λεωφορείο"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ασθενοφόρο"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Πυροσβεστικό"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Περιπολικό"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Ερχόμενο περιπολικό"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Ταξί"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Ερχόμενο ταξί"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Αυτοκίνητο"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Ερχόμενο αυτοκίνητο"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Τροχόσπιτο"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Φορτηγό μεταφορών"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Αρθρωτό φορτηγό"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Τρακτέρ"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Μονοτρόχιος σιδηρόδρομος"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ορεινή σιδηροδρομική γραμμή"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Σιδηρόδρομος με σύστημα ανάρτησης"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Τελεφερίκ"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Εναέριο τραμ"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Πλοίο"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Βάρκα με κουπιά"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Ταχύπλοο"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Οριζόντιος φωτεινός σηματοδότης"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Κάθετος φωτεινός σηματοδότης"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Ταμπέλα έργων"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Σειρήνα περιπολικών"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Τριγωνική σημαία σε ιστό"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Πόρτα"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Σήμα \"Απαγορεύεται η είσοδος\""</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Σύμβολο \"Επιτρέπεται το κάπνισμα\""</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Σύμβολο \"Απαγορεύεται το κάπνισμα\""</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Σύμβολο \"Πετάξτε τα απορρίμματα στους κάδους\""</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Σύμβολο \"Μην πετάτε σκουπίδια\""</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Σύμβολο πόσιμου νερού"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Σύμβολο μη πόσιμου νερού"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Ποδήλατο"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Δεν επιτρέπονται τα ποδήλατα"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ποδηλάτης"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ποδηλάτης ορεινής ποδηλασίας"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Πεζός"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Δεν επιτρέπονται οι πεζοί"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Διασχίζουν παιδιά"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Σύμβολο ανδρών"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Σύμβολο γυναικών"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Τουαλέτες"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Σύμβολο μωρού"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Τουαλέτα"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Αποχωρητήριο"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Ντους"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Μπάνιο"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Μπανιέρα"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Έλεγχος διαβατηρίων"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Τελωνείο"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Παραλαβή αποσκευών"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Απολεσθείσες αποσκευές"</string>
+</resources>
diff --git a/java/res/values-el/strings-talkback-descriptions.xml b/java/res/values-el/strings-talkback-descriptions.xml
index 10df02f..29c9303 100644
--- a/java/res/values-el/strings-talkback-descriptions.xml
+++ b/java/res/values-el/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Δεν υπάρχει κείμενο"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> διορθώνει το <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> σε <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> εκτελεί αυτόματη διόρθωση"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Καμία πρόταση"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Άγνωστος χαρακτήρας"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Περισσότερα σύμβολα"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Κεφαλαίο I, κουκκίδα από πάνω"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Άγνωστο σύμβολο"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Άγνωστο emoticon"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Πρόσωπο που βαριέται"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Αμήχανο πρόσωπο"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Πρόσωπο που φορά γυαλιά ηλίου"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Έκπληκτο πρόσωπο"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Πρόσωπο που δίνει φιλί"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Συνοφρυωμένο πρόσωπο"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Διατίθενται εναλλακτικοί χαρακτήρες"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Παράβλεψη εναλλακτικών χαρακτήρων"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Διατίθενται εναλλακτικές προτάσεις"</string>
diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml
index 5cf14b5..72ecb6c 100644
--- a/java/res/values-el/strings.xml
+++ b/java/res/values-el/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Δόνηση κατά το πάτημα πλήκτρων"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Ήχος κατά το πάτημα πλήκτρων"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Εμφάνιση με το πάτημα πλήκτρου"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Προτιμήσεις"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Λογαριασμοί και απόρρητο"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Εμφάνιση και διάταξη"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Πληκτρολόγηση με κίνηση"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Διόρθωση κειμένου"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Σύνθετες"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Θέμα"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Ενεργοποίηση διαχωρισμού πληκτρολογίου"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Συγχρονισμός Πληκτρολογίου Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Ο συγχρονισμός είναι ενεργοποιημένος"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Συγχρονισμός του προσωπικού λεξικού σας σε όλες τις συσκευές"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Συγχρονισμός τώρα"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Διαγραφή δεδομένων cloud"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Διαγράφει τα συγχρονισμένα δεδομένα σας από το Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Διαγραφή συγχρονισμένων δεδομένων από το cloud. Είστε βέβαιοι;"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Διαγραφή"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Ακύρωση"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Θα γίνει συγχρονισμός και δημιουργία αντιγράφων ασφαλείας του προσωπικού σας λεξικού στους διακομιστές της Google. Ενδέχεται να γίνεται συλλογή στατιστικών στοιχείων σχετικά με τη συχνότητα των λέξεων για τη βελτίωση των προϊόντων μας. Η συλλογή και χρήση όλων των πληροφοριών θα συμμορφώνεται με την "<a href="https://www.google.com/policies/privacy">"Πολιτική Απορρήτου της Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Προσθέσετε Λογαριασμό Google για να ενεργοποιήσετε τη λειτουργία"</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">"Το κλειδί αλλαγής γλώσσας καλύπτει και άλλες μεθόδους εισόδου"</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">"Εμφάνιση δείκτη ολίσθησης"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Εμφ.ένδειξης κατά την ολίσθηση από το Shift ή τα πλήκτρα συμβόλων"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Κλειδί φωνητικής εξόδου"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Δεν έχουν ενεργοποιηθεί μέθοδοι φωνητικής εισαγωγής. Ελέγξτε τις Ρυθμίσεις Γλώσσας και εισαγωγής."</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="language_selection_title" msgid="3666971864764478269">"Γλώσσες"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Βοήθεια και σχόλια"</string>
+    <string name="select_language" msgid="5709487854987078367">"Γλώσσες"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Αγγίξτε ξανά για αποθήκευση"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Αγγίξτε εδώ για αποθήκευση"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Θέμα πληκτρολογίου"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Εναλλαγή λογαριασμών"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Δεν έχει επιλεγεί κανένας λογαριασμός"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Προς το παρόν, χρησιμοποιείτε τη διεύθυνση <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ΟΚ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Ακύρωση"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Έξοδος"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Επιλέξτε λογαριασμό για χρήση"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Αγγλικά (Η.Β.)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Αγγλικά (Η.Π.Α)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Ισπανικά (ΗΠΑ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Σερβικά (Λατινικά)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Αγγλικά (Ηνωμένο Βασίλειο) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Αγγλικά (ΗΠΑ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ισπανικά (ΗΠΑ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Σερβικά (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Παραδοσιακά)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Κυριλλικά)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Λατινικά)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Συμπαγές)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Καμία γλώσσα (Αλφάβητο)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Αλφάβητο (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Αλφάβητο (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Αλφάβητο (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Αλφάβητο (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoticon"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Θέμα πληκτρολογίου"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Προσαρμοσ. στυλ εισαγ."</string>
     <string name="add_style" msgid="6163126614514489951">"Προσθ. στυλ"</string>
     <string name="add" msgid="8299699805688017798">"Προσθήκη"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"Εγκατάσταση αυτού του αρχείου για τα <xliff:g id="LANGUAGE_NAME">%s</xliff:g>;"</string>
-    <string name="error" msgid="8940763624668513648">"Παρουσιάστηκε σφάλμα."</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Καθυστέρηση παρατεταμένου πατήματος πλήκτρου"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Πλέον μπορείτε να πληκτρολογήσετε όλες τις αγαπημένες σας εφαρμογές με το <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">"Εμφάνιση εικονιδίου εφαρμογής στο πρόγραμμα εκκίνησης"</string>
     <string name="app_name" msgid="6320102637491234792">"Παροχέας λεξικού"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Παροχέας λεξικού"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Υπηρεσία λεξικού"</string>
diff --git a/java/res/values-en-rAU/strings-action-keys.xml b/java/res/values-en-rAU/strings-action-keys.xml
new file mode 100644
index 0000000..e401cae
--- /dev/null
+++ b/java/res/values-en-rAU/strings-action-keys.xml
@@ -0,0 +1,31 @@
+<?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="label_go_key" msgid="4033615332628671065">"Go"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"Next"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"Prev"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Done"</string>
+    <string name="label_send_key" msgid="482252074224462163">"Send"</string>
+    <string name="label_search_key" msgid="7965186050435796642">"Search"</string>
+    <string name="label_pause_key" msgid="2225922926459730642">"Pause"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"Wait"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings-appname.xml b/java/res/values-en-rAU/strings-appname.xml
new file mode 100644
index 0000000..5ad5eae
--- /dev/null
+++ b/java/res/values-en-rAU/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<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 Keyboard (AOSP)"</string>
+    <string name="spell_checker_service_name" msgid="1254221805440242662">"Android Spell Checker (AOSP)"</string>
+    <string name="english_ime_settings" msgid="5760361067176802794">"Android Keyboard Settings (AOSP)"</string>
+    <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android Spell Checker Settings (AOSP)"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings-config-important-notice.xml b/java/res/values-en-rAU/strings-config-important-notice.xml
new file mode 100644
index 0000000..80ddd3e
--- /dev/null
+++ b/java/res/values-en-rAU/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"Learn from your communications and typed data to improve suggestions"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings-emoji-descriptions.xml b/java/res/values-en-rAU/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..2ac73fc
--- /dev/null
+++ b/java/res/values-en-rAU/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyright sign"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registered sign"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Double exclamation mark"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Exclamation question mark"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Trade mark sign"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Information source"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Left right arrow"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Up down arrow"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"North west arrow"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"North east arrow"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"South east arrow"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"South west arrow"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Leftwards arrow with hook"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Rightwards arrow with hook"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Watch"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Hourglass"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Black right-pointing double triangle"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Black left-pointing double triangle"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Black up-pointing double triangle"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Black down-pointing double triangle"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Alarm clock"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Hourglass with flowing sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Circled latin capital letter m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Black small square"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"White small square"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Black right-pointing triangle"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Black left-pointing triangle"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"White medium square"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Black medium square"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"White medium small square"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Black medium small square"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Black sun with rays"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Cloud"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Black telephone"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Ballot box with tick"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Umbrella with rain drops"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Hot beverage"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"White up pointing index"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"White smiling face"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taurus"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gemini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpio"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittarius"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquarius"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Pisces"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Black spade suit"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Black club suit"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Black heart suit"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Black diamond suit"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Hot springs"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Black universal recycling symbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Wheelchair symbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anchor"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Warning sign"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"High voltage sign"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Medium white circle"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Medium black circle"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Football"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snowman without snow"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sun behind cloud"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"No entry"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Church"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fountain"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Flag in hole"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Sailing boat"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tent"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Fuel pump"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Black scissors"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"White heavy tick"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Aeroplane"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Envelope"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Raised fist"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Raised hand"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Victory hand"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Pencil"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Black nib"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Heavy tick"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Heavy multiplication x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Sparkles"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Eight spoked asterisk"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Eight pointed black star"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snowflake"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Sparkle"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Cross mark"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negative squared cross mark"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Black question mark ornament"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"White question mark ornament"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"White exclamation mark ornament"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Heavy exclamation mark symbol"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Heavy black heart"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Heavy plus sign"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Heavy minus sign"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Heavy division sign"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Black rightwards arrow"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Curly loop"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Double curly loop"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Arrow pointing rightwards then curving upwards"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Arrow pointing rightwards then curving downwards"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Leftwards black arrow"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Upwards black arrow"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Downwards black arrow"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Black large square"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"White large square"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"White medium star"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Heavy large circle"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Wavy dash"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Part alternation mark"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Circled ideograph congratulation"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Circled ideograph secret"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong tile red dragon"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Playing card black joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blood type A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blood type B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blood type O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Car park"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blood type AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Squared CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Squared cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Squared free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Squared ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Squared new"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Squared N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Squared OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Squared SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Squared up with exclamation mark"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Squared vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Squared katakana here"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Squared katakana service"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Squared ideograph charge-free"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Squared ideograph reserved-seat"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Squared ideograph prohibitation"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Squared ideograph vacancy"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Squared ideograph acceptance"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Squared ideograph full occupancy"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Squared ideograph paid"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Squared ideograph monthly"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Squared ideograph application"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Squared ideograph discount"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Squared ideograph in business"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Circled ideograph advantage"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Circled ideograph accept"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Foggy"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Closed umbrella"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Night with stars"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sunrise over mountains"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sunrise"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Cityscape at dusk"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Sunset over buildings"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Rainbow"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Bridge at night"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Water wave"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcano"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Milky way"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Earth globe Europe-Africa"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Earth globe Americas"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Earth globe Asia-Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globe with meridians"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"New moon symbol"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Waxing crescent moon symbol"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"First quarter moon symbol"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Waxing gibbous moon symbol"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Full moon symbol"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Waning gibbous moon symbol"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Last quarter moon symbol"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Waning crescent moon symbol"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Crescent moon"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"New moon with face"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"First quarter moon with face"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Last quarter moon with face"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Full moon with face"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sun with face"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Glowing star"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Shooting star"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Chestnut"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Seedling"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Evergreen tree"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Deciduous tree"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palm tree"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Cherry blossom"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sunflower"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blossom"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Ear of maize"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Ear of rice"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herb"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Four leaf clover"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Maple leaf"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Fallen leaf"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Leaf fluttering in wind"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Mushroom"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomato"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Grapes"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Watermelon"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tangerine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Lemon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Pineapple"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Red apple"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Green apple"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pear"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Peach"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cherries"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Strawberry"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Slice of pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Meat on bone"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Poultry leg"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rice cracker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rice ball"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Cooked rice"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry and rice"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Steaming bowl"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Bread"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"French fries"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Roasted sweet potato"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Fried shrimp"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fish cake with swirl design"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Soft ice cream"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Shaved ice"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Ice cream"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Doughnut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chocolate bar"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Candy"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Custard"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honey pot"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Shortcake"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento box"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Pot of food"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Cooking"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Fork and knife"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Teacup without handle"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake bottle and cup"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wine glass"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktail glass"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropical drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Beer mug"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Clinking beer mugs"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Baby bottle"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Ribbon"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Wrapped present"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Birthday cake"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Jack-o-lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Christmas tree"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Father christmas"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fireworks"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Firework sparkler"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balloon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Party popper"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Confetti ball"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata tree"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Crossed flags"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Pine decoration"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanese dolls"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Carp streamer"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Wind chime"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Moon viewing ceremony"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"School satchel"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Graduation cap"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Carousel horse"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ferris wheel"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Roller coaster"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Fishing pole and fish"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microphone"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Movie camera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Headphone"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Artist palette"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Top hat"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Circus tent"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ticket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Clapper board"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Performing arts"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video game"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Direct hit"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Slot machine"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billiards"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Game die"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Flower playing cards"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musical note"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Multiple musical notes"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Musical keyboard"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trumpet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violin"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Musical score"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Running shirt with sash"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennis racquet and ball"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski and ski boot"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball and hoop"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Chequered flag"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Runner"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trophy"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Horse racing"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"American football"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby football"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Swimmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"House building"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"House with garden"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Office building"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japanese post office"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"European post office"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Automated teller machine"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Convenience store"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"School"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Department store"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Factory"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya lantern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japanese castle"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"European castle"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rat"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mouse"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Ox"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Water buffalo"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Cow"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Rabbit"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Cat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodile"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Whale"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Snail"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Snake"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Horse"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ram"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Goat"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Sheep"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Monkey"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Rooster"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Chicken"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Dog"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Pig"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Boar"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elephant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Octopus"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiral shell"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Bug"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Ant"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Honeybee"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Lady beetle"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fish"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropical fish"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Blowfish"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Turtle"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Hatching chick"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Baby chick"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Front-facing baby chick"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Bird"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Penguin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poodle"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedary camel"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Bactrian camel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dolphin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mouse face"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cow face"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tiger face"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Rabbit face"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cat face"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Dragon face"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Spouting whale"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Horse face"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Monkey face"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Dog face"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Pig face"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Frog face"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamster face"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wolf face"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Bear face"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda face"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Pig nose"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Paw prints"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Eyes"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ear"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nose"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mouth"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tongue"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"White up pointing backhand index"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"White down pointing backhand index"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"White left pointing backhand index"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"White right pointing backhand index"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Fisted hand sign"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Waving hand sign"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK hand sign"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Thumbs up sign"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Thumbs down sign"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Clapping hands sign"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Open hands sign"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Crown"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Womans hat"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Eyeglasses"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Necktie"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Dress"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Womans clothes"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Purse"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handbag"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pouch"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Mans shoe"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Athletic shoe"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"High-heeled shoe"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Womans sandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Womans boots"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Footprints"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Bust in silhouette"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Busts in silhouette"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Boy"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Girl"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Man"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Woman"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Family"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Man and woman holding hands"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Two men holding hands"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Two women holding hands"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Police officer"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Woman with bunny ears"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Bride with veil"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Person with blond hair"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Man with gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Man with turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Older man"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Older woman"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Construction worker"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princess"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanese ogre"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanese goblin"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Ghost"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Baby angel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestrial alien"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Alien monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Imp"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Skull"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Information desk person"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardsman"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dancer"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lipstick"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nail polish"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Face massage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Haircut"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barber pole"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Syringe"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pill"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kiss mark"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Love letter"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Gem stone"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kiss"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Couple with heart"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Wedding"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Beating heart"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Broken heart"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Two hearts"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Sparkling heart"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Growing heart"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Heart with arrow"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blue heart"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Green heart"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Yellow heart"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Purple heart"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Heart with ribbon"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Revolving hearts"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Heart decoration"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamond shape with a dot inside"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Electric light bulb"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Anger symbol"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomb"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Sleeping symbol"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Collision symbol"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Splashing sweat symbol"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Droplet"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Dash symbol"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Pile of poo"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Flexed biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Dizzy symbol"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Speech balloon"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Thought balloon"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"White flower"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Hundred points symbol"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Money bag"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Currency exchange"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Heavy pound sign"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Credit card"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknote with yen sign"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknote with pound sign"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknote with euro sign"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknote with pound sign"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Money with wings"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Chart with upwards trend and yen sign"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Seat"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personal computer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Briefcase"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppy disk"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optical disc"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"File folder"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Open file folder"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Page with curl"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Page facing up"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendar"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Tear-off calendar"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Card index"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Chart with upwards trend"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Chart with downwards trend"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Bar chart"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Clipboard"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pushpin"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Round pushpin"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Paperclip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Straight ruler"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Triangular ruler"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Bookmark tabs"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ledger"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notebook"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notebook with decorative cover"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Closed book"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Open book"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Green book"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blue book"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Orange book"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Books"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Name badge"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Scroll"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telephone receiver"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax machine"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellite antenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Public address loudspeaker"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Cheering megaphone"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Outbox tray"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Inbox tray"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Package"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mail symbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Incoming envelope"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Envelope with downwards arrow above"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Closed mailbox with lowered flag"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Closed mailbox with raised flag"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Open mailbox with raised flag"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Open mailbox with lowered flag"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postbox"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Postal horn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Newspaper"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobile phone"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobile phone with rightwards arrow at left"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibration mode"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobile phone off"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"No mobile phones"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna with bars"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Camera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Video camera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Television"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Twisted rightwards arrows"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Clockwise rightwards and leftwards open circle arrows"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Clockwise rightwards and leftwards open circle arrows with circled one overlay"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Clockwise downwards and upwards open circle arrows"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Anticlockwise downwards and upwards open circle arrows"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Low brightness symbol"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"High brightness symbol"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Speaker with cancellation stroke"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Speaker"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Speaker with one sound wave"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Speaker with three sound waves"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Battery"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Electric plug"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Left-pointing magnifying glass"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Right-pointing magnifying glass"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lock with ink pen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Closed lock with key"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Key"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lock"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Open lock"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Bell"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Bell with cancellation stroke"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bookmark"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Link symbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radio button"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back with leftwards arrow above"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End with leftwards arrow above"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On with exclamation mark with left right arrow above"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon with rightwards arrow above"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top with upwards arrow above"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"No one under eighteen symbol"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Keycap ten"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Input symbol for latin capital letters"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Input symbol for latin small letters"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Input symbol for numbers"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Input symbol for symbols"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Input symbol for latin letters"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fire"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Electric torch"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Wrench"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Nut and bolt"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscope"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescope"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Crystal ball"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Six pointed star with middle dot"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japanese symbol for beginner"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trident emblem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Black square button"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"White square button"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Large red circle"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Large blue circle"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Large orange diamond"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Large blue diamond"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Small orange diamond"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Small blue diamond"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Up-pointing red triangle"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Down-pointing red triangle"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Up-pointing small red triangle"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Down-pointing small red triangle"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Clock face one o\'clock"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Clock face two o\'clock"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Clock face three o\'clock"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Clock face four o\'clock"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Clock face five o\'clock"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Clock face six o\'clock"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Clock face seven o\'clock"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Clock face eight o\'clock"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Clock face nine o\'clock"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Clock face ten o\'clock"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Clock face eleven o\'clock"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Clock face twelve o\'clock"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Clock face one-thirty"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Clock face two-thirty"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Clock face three-thirty"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Clock face four-thirty"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Clock face five-thirty"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Clock face six-thirty"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Clock face seven-thirty"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Clock face eight-thirty"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Clock face nine-thirty"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Clock face ten-thirty"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Clock face eleven-thirty"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Clock face twelve-thirty"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mount Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statue of Liberty"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhouette of Japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Grinning face"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Grinning face with smiling eyes"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Face with tears of joy"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Smiling face with open mouth"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Smiling face with open mouth and smiling eyes"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Smiling face with open mouth and cold sweat"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Smiling face with open mouth and tightly-closed eyes"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Smiling face with halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Smiling face with horns"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Winking face"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Smiling face with smiling eyes"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Face savouring delicious food"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Relieved face"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Smiling face with heart-shaped eyes"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Smiling face with sunglasses"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Smirking face"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutral face"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Expressionless face"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Unamused face"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Face with cold sweat"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Pensive face"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Confused face"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Confounded face"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kissing face"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Face throwing a kiss"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kissing face with smiling eyes"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kissing face with closed eyes"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Face with stuck-out tongue"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Face with stuck-out tongue and winking eye"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Face with stuck-out tongue and tightly-closed eyes"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Disappointed face"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Worried face"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Angry face"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Pouting face"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Crying face"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Persevering face"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Face with look of triumph"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Disappointed but relieved face"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Frowning face with open mouth"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Anguished face"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Fearful face"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Weary face"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Sleepy face"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Tired face"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimacing face"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Loudly crying face"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Face with open mouth"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Hushed face"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Face with open mouth and cold sweat"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Face screaming in fear"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Astonished face"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Flushed face"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Sleeping face"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Dizzy face"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Face without mouth"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Face with medical mask"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Grinning cat face with smiling eyes"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cat face with tears of joy"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Smiling cat face with open mouth"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Smiling cat face with heart-shaped eyes"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cat face with wry smile"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kissing cat face with closed eyes"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Pouting cat face"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Crying cat face"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Weary cat face"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Face with no good gesture"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Face with OK gesture"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Person bowing deeply"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"See-no-evil monkey"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Hear-no-evil monkey"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Speak-no-evil monkey"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Happy person raising one hand"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person raising both hands in celebration"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Person frowning"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Person with pouting face"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person with folded hands"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rocket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Steam locomotive"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Railway car"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"High-speed train"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"High-speed train with bullet nose"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Train"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Light rail"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Station"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tram"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tram car"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Oncoming bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Tram"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bus stop"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Fire engine"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Police car"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Oncoming police car"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Oncoming taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobile"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Oncoming automobile"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Recreational vehicle"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Delivery truck"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Articulated lorry"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Mountain railway"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Suspension railway"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Mountain cableway"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Aerial tramway"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Ship"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Rowing boat"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedboat"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontal traffic light"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertical traffic light"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Construction sign"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Police cars revolving light"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Triangular flag on post"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Door"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"No entry sign"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Smoking symbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"No smoking symbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Put litter in its place symbol"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Do not litter symbol"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Drinking water symbol"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Non-drinking water symbol"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicycle"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"No bicycles"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cyclist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountain cyclist"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pedestrian"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"No pedestrians"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Children crossing"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Mens symbol"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Womens symbol"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Restroom"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Baby symbol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Water closet"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Shower"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bath"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bathtub"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Passport control"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Customs"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Baggage claim"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Left luggage"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings-letter-descriptions.xml b/java/res/values-en-rAU/strings-letter-descriptions.xml
new file mode 100644
index 0000000..514bc6c
--- /dev/null
+++ b/java/res/values-en-rAU/strings-letter-descriptions.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These accented letters (spoken_accented_letter_*) are unsupported by TTS.
+    These symbols (spoken_symbol_*) are also unsupported by TTS.
+    TODO: Remove these string resources when TTS/TalkBack support these letters.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_accented_letter_00AA" msgid="4374325261868451570">"Feminine ordinal indicator"</string>
+    <string name="spoken_accented_letter_00B5" msgid="9031387673828823891">"Micro sign"</string>
+    <string name="spoken_accented_letter_00BA" msgid="5045198452071207437">"Masculine ordinal indicator"</string>
+    <string name="spoken_accented_letter_00DF" msgid="2260098367028134281">"Sharp S"</string>
+    <string name="spoken_accented_letter_00E0" msgid="2234515772182387086">"A, grave"</string>
+    <string name="spoken_accented_letter_00E1" msgid="7780174500802535063">"A, acute"</string>
+    <string name="spoken_accented_letter_00E2" msgid="7054108480488102631">"A, circumflex"</string>
+    <string name="spoken_accented_letter_00E3" msgid="8252569677935693343">"A, tilde"</string>
+    <string name="spoken_accented_letter_00E4" msgid="6610118430986969466">"A, diaeresis"</string>
+    <string name="spoken_accented_letter_00E5" msgid="7630449270070348394">"A, ring above"</string>
+    <string name="spoken_accented_letter_00E6" msgid="701838036007000032">"A, E, ligature"</string>
+    <string name="spoken_accented_letter_00E7" msgid="2991289211702135310">"C, cedilla"</string>
+    <string name="spoken_accented_letter_00E8" msgid="2080035251848179782">"E, grave"</string>
+    <string name="spoken_accented_letter_00E9" msgid="2708473976407506968">"E, acute"</string>
+    <string name="spoken_accented_letter_00EA" msgid="1898848081635119449">"E, circumflex"</string>
+    <string name="spoken_accented_letter_00EB" msgid="8318942663983499634">"E, diaeresis"</string>
+    <string name="spoken_accented_letter_00EC" msgid="7643810590358306098">"I, grave"</string>
+    <string name="spoken_accented_letter_00ED" msgid="8288035355103120759">"I, acute"</string>
+    <string name="spoken_accented_letter_00EE" msgid="1137417730211688894">"I, circumflex"</string>
+    <string name="spoken_accented_letter_00EF" msgid="8993714322731956785">"I, diaeresis"</string>
+    <string name="spoken_accented_letter_00F0" msgid="3427567511221967857">"Eth"</string>
+    <string name="spoken_accented_letter_00F1" msgid="6983294908255378605">"N, tilde"</string>
+    <string name="spoken_accented_letter_00F2" msgid="2623804069332183695">"O, grave"</string>
+    <string name="spoken_accented_letter_00F3" msgid="8945987631729216917">"O, acute"</string>
+    <string name="spoken_accented_letter_00F4" msgid="2415494299699717276">"O, circumflex"</string>
+    <string name="spoken_accented_letter_00F5" msgid="7320512716652765243">"O, tilde"</string>
+    <string name="spoken_accented_letter_00F6" msgid="9101179351242478555">"O, diaeresis"</string>
+    <string name="spoken_accented_letter_00F8" msgid="1488324280918884122">"O, stroke"</string>
+    <string name="spoken_accented_letter_00F9" msgid="2823570256527173278">"U, grave"</string>
+    <string name="spoken_accented_letter_00FA" msgid="6883092085077298608">"U, acute"</string>
+    <string name="spoken_accented_letter_00FB" msgid="4948239400399514418">"U, circumflex"</string>
+    <string name="spoken_accented_letter_00FC" msgid="2496066211694000442">"U, diaeresis"</string>
+    <string name="spoken_accented_letter_00FD" msgid="2400529610834233890">"Y, acute"</string>
+    <string name="spoken_accented_letter_00FE" msgid="8788160115017853040">"Thorn"</string>
+    <string name="spoken_accented_letter_00FF" msgid="5225610161025124830">"Y, diaeresis"</string>
+    <string name="spoken_accented_letter_0101" msgid="5573209280917268157">"A, macron"</string>
+    <string name="spoken_accented_letter_0103" msgid="2469151120095164730">"A, breve"</string>
+    <string name="spoken_accented_letter_0105" msgid="8312689789855786427">"A, ogonek"</string>
+    <string name="spoken_accented_letter_0107" msgid="5708507895287798642">"C, acute"</string>
+    <string name="spoken_accented_letter_0109" msgid="7008112603489583335">"C, circumflex"</string>
+    <string name="spoken_accented_letter_010B" msgid="5641359473019753216">"C, dot above"</string>
+    <string name="spoken_accented_letter_010D" msgid="1048661826408437168">"C, caron"</string>
+    <string name="spoken_accented_letter_010F" msgid="603374318657992205">"D, caron"</string>
+    <string name="spoken_accented_letter_0111" msgid="5517997642285938260">"D, stroke"</string>
+    <string name="spoken_accented_letter_0113" msgid="2326009009311798997">"E, macron"</string>
+    <string name="spoken_accented_letter_0115" msgid="3964545407091037747">"E, breve"</string>
+    <string name="spoken_accented_letter_0117" msgid="8799753183781089777">"E, dot above"</string>
+    <string name="spoken_accented_letter_0119" msgid="3772451226935709136">"E, ogonek"</string>
+    <string name="spoken_accented_letter_011B" msgid="7663481332351461288">"E, caron"</string>
+    <string name="spoken_accented_letter_011D" msgid="1181326600595482369">"G, circumflex"</string>
+    <string name="spoken_accented_letter_011F" msgid="6843415389823096647">"G, breve"</string>
+    <string name="spoken_accented_letter_0121" msgid="6205288708713306903">"G, dot above"</string>
+    <string name="spoken_accented_letter_0123" msgid="2394277128105386261">"G, cedilla"</string>
+    <string name="spoken_accented_letter_0125" msgid="6575866461277751345">"H, circumflex"</string>
+    <string name="spoken_accented_letter_0127" msgid="1316971762214091641">"H, stroke"</string>
+    <string name="spoken_accented_letter_0129" msgid="7824912405885325754">"I, tilde"</string>
+    <string name="spoken_accented_letter_012B" msgid="6772690258769905270">"I, macron"</string>
+    <string name="spoken_accented_letter_012D" msgid="2933871131556503448">"I, breve"</string>
+    <string name="spoken_accented_letter_012F" msgid="1340511254985181663">"I, ogonek"</string>
+    <string name="spoken_accented_letter_0131" msgid="5635600720566083969">"Dotless I"</string>
+    <string name="spoken_accented_letter_0133" msgid="7593704176516791941">"I, J, ligature"</string>
+    <string name="spoken_accented_letter_0135" msgid="4521109674238248436">"J, circumflex"</string>
+    <string name="spoken_accented_letter_0137" msgid="5886444641003852175">"K, cedilla"</string>
+    <string name="spoken_accented_letter_0138" msgid="4200294389170924853">"Kra"</string>
+    <string name="spoken_accented_letter_013A" msgid="3558015385412543517">"L, acute"</string>
+    <string name="spoken_accented_letter_013C" msgid="1853639924813858734">"L, cedilla"</string>
+    <string name="spoken_accented_letter_013E" msgid="7489345561739421886">"L, caron"</string>
+    <string name="spoken_accented_letter_0140" msgid="7946718707268270589">"L, middle dot"</string>
+    <string name="spoken_accented_letter_0142" msgid="752931798111122240">"L, stroke"</string>
+    <string name="spoken_accented_letter_0144" msgid="201843550323875352">"N, acute"</string>
+    <string name="spoken_accented_letter_0146" msgid="3403847152606051818">"N, cedilla"</string>
+    <string name="spoken_accented_letter_0148" msgid="9215300786722209338">"N, caron"</string>
+    <string name="spoken_accented_letter_0149" msgid="3191850286630154063">"N, preceded by apostrophe"</string>
+    <string name="spoken_accented_letter_014B" msgid="8503022408522837410">"Eng"</string>
+    <string name="spoken_accented_letter_014D" msgid="4452323602550610641">"O, macron"</string>
+    <string name="spoken_accented_letter_014F" msgid="2795957717094385336">"O, breve"</string>
+    <string name="spoken_accented_letter_0151" msgid="8013704745216410244">"O, double acute"</string>
+    <string name="spoken_accented_letter_0153" msgid="8410582495993285221">"O, E, ligature"</string>
+    <string name="spoken_accented_letter_0155" msgid="7601517174689798560">"R, acute"</string>
+    <string name="spoken_accented_letter_0157" msgid="9071455715455643810">"R, cedilla"</string>
+    <string name="spoken_accented_letter_0159" msgid="7726911392381543439">"R, caron"</string>
+    <string name="spoken_accented_letter_015B" msgid="1854129531164494117">"S, acute"</string>
+    <string name="spoken_accented_letter_015D" msgid="4743571603550582530">"S, circumflex"</string>
+    <string name="spoken_accented_letter_015F" msgid="1519945638631588761">"S, cedilla"</string>
+    <string name="spoken_accented_letter_0161" msgid="7493478552029144246">"S, caron"</string>
+    <string name="spoken_accented_letter_0163" msgid="9103547637928833069">"T, cedilla"</string>
+    <string name="spoken_accented_letter_0165" msgid="7306159398214872062">"T, caron"</string>
+    <string name="spoken_accented_letter_0167" msgid="5578767705098672443">"T, stroke"</string>
+    <string name="spoken_accented_letter_0169" msgid="413046581387735371">"U, tilde"</string>
+    <string name="spoken_accented_letter_016B" msgid="3209778874978859441">"U, macron"</string>
+    <string name="spoken_accented_letter_016D" msgid="2983326533258602840">"U, breve"</string>
+    <string name="spoken_accented_letter_016F" msgid="4416532499516387231">"U, ring above"</string>
+    <string name="spoken_accented_letter_0171" msgid="3435171971353200807">"U, double acute"</string>
+    <string name="spoken_accented_letter_0173" msgid="4494154432483553480">"U, ogonek"</string>
+    <string name="spoken_accented_letter_0175" msgid="2154545579611918513">"W, circumflex"</string>
+    <string name="spoken_accented_letter_0177" msgid="4034463827306904781">"Y, circumflex"</string>
+    <string name="spoken_accented_letter_017A" msgid="3368292232292925369">"Z, acute"</string>
+    <string name="spoken_accented_letter_017C" msgid="2834484584505860430">"Z, dot above"</string>
+    <string name="spoken_accented_letter_017E" msgid="1209240442434887098">"Z, caron"</string>
+    <string name="spoken_accented_letter_017F" msgid="317501463253362415">"Long S"</string>
+    <string name="spoken_accented_letter_01A1" msgid="630186564859044196">"O, horn"</string>
+    <string name="spoken_accented_letter_01B0" msgid="8544012177684640443">"U, horn"</string>
+    <string name="spoken_accented_letter_0219" msgid="1960371842020076066">"S, comma below"</string>
+    <string name="spoken_accented_letter_021B" msgid="1398418662032919032">"T, comma below"</string>
+    <string name="spoken_accented_letter_0259" msgid="2464085263158415898">"Schwa"</string>
+    <string name="spoken_accented_letter_1EA1" msgid="688124877202887630">"A, dot below"</string>
+    <string name="spoken_accented_letter_1EA3" msgid="327960130366386256">"A, hook above"</string>
+    <string name="spoken_accented_letter_1EA5" msgid="637406363453769610">"A, circumflex and acute"</string>
+    <string name="spoken_accented_letter_1EA7" msgid="1419591804181615409">"A, circumflex and grave"</string>
+    <string name="spoken_accented_letter_1EA9" msgid="6068887382734896756">"A, circumflex and hook above"</string>
+    <string name="spoken_accented_letter_1EAB" msgid="7236523151662538333">"A, circumflex and tilde"</string>
+    <string name="spoken_accented_letter_1EAD" msgid="2363364864106332076">"A, circumflex and dot below"</string>
+    <string name="spoken_accented_letter_1EAF" msgid="1576329511464272935">"A, breve and acute"</string>
+    <string name="spoken_accented_letter_1EB1" msgid="4634735072816076592">"A, breve and grave"</string>
+    <string name="spoken_accented_letter_1EB3" msgid="2325245849038771534">"A, breve and hook above"</string>
+    <string name="spoken_accented_letter_1EB5" msgid="3720427596242746295">"A, breve and tilde"</string>
+    <string name="spoken_accented_letter_1EB7" msgid="700415535653646695">"A, breve and dot below"</string>
+    <string name="spoken_accented_letter_1EB9" msgid="3901338692305890487">"E, dot below"</string>
+    <string name="spoken_accented_letter_1EBB" msgid="4028688699415417302">"E, hook above"</string>
+    <string name="spoken_accented_letter_1EBD" msgid="181253633045931897">"E, tilde"</string>
+    <string name="spoken_accented_letter_1EBF" msgid="3309618845007944963">"E, circumflex and acute"</string>
+    <string name="spoken_accented_letter_1EC1" msgid="8139046749226332542">"E, circumflex and grave"</string>
+    <string name="spoken_accented_letter_1EC3" msgid="3239674223053133383">"E, circumflex and hook above"</string>
+    <string name="spoken_accented_letter_1EC5" msgid="2216559244705714587">"E, circumflex and tilde"</string>
+    <string name="spoken_accented_letter_1EC7" msgid="9012731468253986792">"E, circumflex and dot below"</string>
+    <string name="spoken_accented_letter_1EC9" msgid="2901917620195717034">"I, hook above"</string>
+    <string name="spoken_accented_letter_1ECB" msgid="5470387489820034621">"I, dot below"</string>
+    <string name="spoken_accented_letter_1ECD" msgid="1340122876914839806">"O, dot below"</string>
+    <string name="spoken_accented_letter_1ECF" msgid="2326921263882559755">"O, hook above"</string>
+    <string name="spoken_accented_letter_1ED1" msgid="2885683296042774958">"O, circumflex and acute"</string>
+    <string name="spoken_accented_letter_1ED3" msgid="6857664926477376178">"O, circumflex and grave"</string>
+    <string name="spoken_accented_letter_1ED5" msgid="2015209467290624062">"O, circumflex and hook above"</string>
+    <string name="spoken_accented_letter_1ED7" msgid="7924481354960306389">"O, circumflex and tilde"</string>
+    <string name="spoken_accented_letter_1ED9" msgid="7023315590332365554">"O, circumflex and dot below"</string>
+    <string name="spoken_accented_letter_1EDB" msgid="2379438944917634496">"O, horn and acute"</string>
+    <string name="spoken_accented_letter_1EDD" msgid="8107077534204404085">"O, horn and grave"</string>
+    <string name="spoken_accented_letter_1EDF" msgid="1846880105528347966">"O, horn and hook above"</string>
+    <string name="spoken_accented_letter_1EE1" msgid="1520037313389776718">"O, horn and tilde"</string>
+    <string name="spoken_accented_letter_1EE3" msgid="907964027171008963">"O, horn and dot below"</string>
+    <string name="spoken_accented_letter_1EE5" msgid="1522024630360038700">"U, dot below"</string>
+    <string name="spoken_accented_letter_1EE7" msgid="7815412228302952637">"U, hook above"</string>
+    <string name="spoken_accented_letter_1EE9" msgid="4219119671251485651">"U, horn and acute"</string>
+    <string name="spoken_accented_letter_1EEB" msgid="4086009841269002231">"U, horn and grave"</string>
+    <string name="spoken_accented_letter_1EED" msgid="3528151733528719847">"U, horn and hook above"</string>
+    <string name="spoken_accented_letter_1EEF" msgid="3508548229409072119">"U, horn and tilde"</string>
+    <string name="spoken_accented_letter_1EF1" msgid="1912816350401931115">"U, horn and dot below"</string>
+    <string name="spoken_accented_letter_1EF3" msgid="7211760439435946494">"Y, grave"</string>
+    <string name="spoken_accented_letter_1EF5" msgid="8998864482764007384">"Y, dot below"</string>
+    <string name="spoken_accented_letter_1EF7" msgid="922043627252869200">"Y, hook above"</string>
+    <string name="spoken_accented_letter_1EF9" msgid="6213977100552260366">"Y, tilde"</string>
+    <string name="spoken_symbol_00A1" msgid="4281758332905123408">"Inverted exclamation mark"</string>
+    <string name="spoken_symbol_00AB" msgid="4093069643313064892">"Left-pointing double angle quotation mark"</string>
+    <string name="spoken_symbol_00B7" msgid="2447718728927874920">"Middle dot"</string>
+    <string name="spoken_symbol_00B9" msgid="8026257165451461231">"Superscript one"</string>
+    <string name="spoken_symbol_00BB" msgid="1102740075655373928">"Right-pointing double angle quotation mark"</string>
+    <string name="spoken_symbol_00BF" msgid="6233794752573788098">"Inverted question mark"</string>
+    <string name="spoken_symbol_2018" msgid="4886476295598930225">"Left single quotation mark"</string>
+    <string name="spoken_symbol_2019" msgid="8892530161598134083">"Right single quotation mark"</string>
+    <string name="spoken_symbol_201A" msgid="2072987157683446644">"Single low-9 quotation mark"</string>
+    <string name="spoken_symbol_201C" msgid="4588048378803665427">"Left double quotation mark"</string>
+    <string name="spoken_symbol_201D" msgid="1642776849495925895">"Right double quotation mark"</string>
+    <string name="spoken_symbol_2020" msgid="9084628638189344431">"Dagger"</string>
+    <string name="spoken_symbol_2021" msgid="5081396468559426475">"Double dagger"</string>
+    <string name="spoken_symbol_2030" msgid="9068837172419431755">"Per mille sign"</string>
+    <string name="spoken_symbol_2032" msgid="3014506329156664396">"Prime"</string>
+    <string name="spoken_symbol_2033" msgid="1251022699713475088">"Double prime"</string>
+    <string name="spoken_symbol_2039" msgid="6989616457213775957">"Single left-pointing angle quotation mark"</string>
+    <string name="spoken_symbol_203A" msgid="31245095449823701">"Single right-pointing angle quotation mark"</string>
+    <string name="spoken_symbol_2074" msgid="2116717717093306894">"Superscript four"</string>
+    <string name="spoken_symbol_207F" msgid="1706731172134246659">"Superscript latin small letter n"</string>
+    <string name="spoken_symbol_20B1" msgid="2159994270622444689">"Peso sign"</string>
+    <string name="spoken_symbol_2105" msgid="7289404939366976829">"Care of"</string>
+    <string name="spoken_symbol_2192" msgid="827804523596125414">"Rightwards arrow"</string>
+    <string name="spoken_symbol_2193" msgid="2659541693445985717">"Downwards arrow"</string>
+    <string name="spoken_symbol_2205" msgid="4457188084269117343">"Empty set"</string>
+    <string name="spoken_symbol_2206" msgid="4856786565708380687">"Increment"</string>
+    <string name="spoken_symbol_2264" msgid="5092061257745123554">"Less than or equal to"</string>
+    <string name="spoken_symbol_2265" msgid="1907966479878036357">"Greater than or equal to"</string>
+    <string name="spoken_symbol_2605" msgid="5202920479405857753">"Black star"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings-talkback-descriptions.xml b/java/res/values-en-rAU/strings-talkback-descriptions.xml
new file mode 100644
index 0000000..78c2905
--- /dev/null
+++ b/java/res/values-en-rAU/strings-talkback-descriptions.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="spoken_use_headphones" msgid="4313642710742229868">"Plug in a headset to hear password keys spoken aloud."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"Current text is %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"No text entered"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrects <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> to <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> performs auto-correction"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No suggestion"</string>
+    <string name="spoken_description_unknown" msgid="5139930082759824442">"Unknown character"</string>
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"More symbols"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shift"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Symbols"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shift"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"Delete"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Symbols"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Letters"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Numbers"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Settings"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Tab"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Space"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Voice input"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Emoji"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Return"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Search"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Full stop"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Switch language"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Next"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Previous"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Shift enabled"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"Caps lock enabled"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Symbols mode"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"More symbols mode"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Letters mode"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Phone mode"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Phone symbols mode"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Keyboard hidden"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"Showing <xliff:g id="KEYBOARD_MODE">%s</xliff:g> keyboard"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"date"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"date and time"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"email"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"messaging"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"number"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"phone"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"text"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"time"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Recents"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"People"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Objects"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Nature"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Places"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Symbols"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Emoticons"</string>
+    <string name="spoken_description_upper_case" msgid="4904835255229433916">"Capital <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
+    <string name="spoken_letter_0049" msgid="4743162182646977944">"Capital I"</string>
+    <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
+    <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unknown symbol"</string>
+    <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unknown emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Bored face"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassed face"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Face wearing sunglasses"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surprised face"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kissing face"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Frowning face"</string>
+    <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative characters are available"</string>
+    <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative characters are dismissed"</string>
+    <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative suggestions are available"</string>
+    <string name="spoken_close_more_suggestions" msgid="9118455416075032839">"Alternative suggestions are dismissed"</string>
+</resources>
diff --git a/java/res/values-en-rAU/strings.xml b/java/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..332e01e
--- /dev/null
+++ b/java/res/values-en-rAU/strings.xml
@@ -0,0 +1,207 @@
+<?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">"Input options"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Look up contact names"</string>
+    <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Spell checker uses entries from your contact list"</string>
+    <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
+    <string name="sound_on_keypress" msgid="6093592297198243644">"Sound on keypress"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Accounts &amp; Privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Appearance &amp; Layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Gesture Typing"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Text correction"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Advanced"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Theme"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Enable split keyboard"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Keyboard Sync"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sync is turned on"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sync your personal dictionary across devices"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sync now"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Delete cloud data"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Deletes your synced data from Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Your synced data will be deleted from the cloud. Are you sure?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Delete"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancel"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Your personal dictionary will be synced and backed up to Google servers. The statistical information of word frequency may be collected to help improve our products. The collection and usage of all the information will be compliant with "<a href="https://www.google.com/policies/privacy">"Google\'s Privacy Policy"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Please add a Google account to this device to enable this feature"</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key also covers other input methods"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"Language switch key"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Show when multiple input languages are enabled"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
+    <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
+    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
+    <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g>ms"</string>
+    <string name="settings_system_default" msgid="6268225104743331821">"System default"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Suggest Contact names"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Use names from Contacts for suggestions and corrections"</string>
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"Personalised suggestions"</string>
+    <string name="enable_metrics_logging" msgid="5506372337118822837">"Improve <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="use_double_space_period" msgid="8781529969425082860">"Double-space full stop"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Double tap on spacebar inserts a full stop followed by a space"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"Auto-capitalisation"</string>
+    <string name="auto_cap_summary" msgid="7934452761022946874">"Capitalise the first word of each sentence"</string>
+    <string name="edit_personal_dictionary" msgid="3996910038952940420">"Personal dictionary"</string>
+    <string name="configure_dictionaries_title" msgid="4238652338556902049">"Add-on dictionaries"</string>
+    <string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
+    <string name="prefs_show_suggestions" msgid="8026799663445531637">"Show correction suggestions"</string>
+    <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Display suggested words while typing"</string>
+    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Block offensive words"</string>
+    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Do not suggest potentially offensive words"</string>
+    <string name="auto_correction" msgid="7630720885194996950">"Auto-correction"</string>
+    <string name="auto_correction_summary" msgid="5625751551134658006">"Correct mistyped words automatically with spacebar and punctuation"</string>
+    <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Off"</string>
+    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"Modest"</string>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Aggressive"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Very aggressive"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"Next-word suggestions"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"Use the previous word when making suggestions"</string>
+    <string name="gesture_input" msgid="826951152254563827">"Enable gesture typing"</string>
+    <string name="gesture_input_summary" msgid="9180350639305731231">"Input a word by sliding through the letters"</string>
+    <string name="gesture_preview_trail" msgid="3802333369335722221">"Show gesture trail"</string>
+    <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Dynamic floating preview"</string>
+    <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"See the suggested word while gesturing"</string>
+    <string name="gesture_space_aware" msgid="2078291600664682496">"Phrase gesture"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Input spaces during gestures by gliding to the space key"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No voice input methods enabled. Check Language &amp; input settings."</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Languages"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help &amp; feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Languages"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touch here to save"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Change accounts"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"No accounts selected"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Currently using <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancel"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Sign out"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Select an account to use"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbian (Latin)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"English (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"English (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
+    <string name="subtype_no_language" msgid="7137390094240139495">"No language (Alphabet)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Alphabet (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Alphabet (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alphabet (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet (PC)"</string>
+    <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"Keyboard theme"</string>
+    <string name="custom_input_styles_title" msgid="8429952441821251512">"Customised input styles"</string>
+    <string name="add_style" msgid="6163126614514489951">"Add style"</string>
+    <string name="add" msgid="8299699805688017798">"Add"</string>
+    <string name="remove" msgid="4486081658752944606">"Remove"</string>
+    <string name="save" msgid="7646738597196767214">"Save"</string>
+    <string name="subtype_locale" msgid="8576443440738143764">"Language"</string>
+    <string name="keyboard_layout_set" msgid="4309233698194565609">"Layout"</string>
+    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Your customised input style needs to be enabled before you start using it. Do you want to enable it now?"</string>
+    <string name="enable" msgid="5031294444630523247">"Enable"</string>
+    <string name="not_now" msgid="6172462888202790482">"Not now"</string>
+    <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Keypress vibration duration"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Keypress sound volume"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
+    <string name="button_default" msgid="3988017840431881491">"Default"</string>
+    <string name="setup_welcome_title" msgid="6112821709832031715">"Welcome to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_welcome_additional_description" msgid="8150252008545768953">"with Gesture Typing"</string>
+    <string name="setup_start_action" msgid="8936036460897347708">"Get started"</string>
+    <string name="setup_next_action" msgid="371821437915144603">"Next step"</string>
+    <string name="setup_steps_title" msgid="6400373034871816182">"Setting up <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_step1_title" msgid="3147967630253462315">"Enable <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_step1_instruction" msgid="2578631936624637241">"Please tick \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" in your Language &amp; input settings. This will authorise it to run on your device."</string>
+    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> is already enabled in your Language &amp; input settings, so this step is done. On to the next one!"</string>
+    <string name="setup_step1_action" msgid="4366513534999901728">"Enable in Settings"</string>
+    <string name="setup_step2_title" msgid="6860725447906690594">"Switch to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_step2_instruction" msgid="9141481964870023336">"Next, select \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" as your active text-input method."</string>
+    <string name="setup_step2_action" msgid="1660330307159824337">"Switch input methods"</string>
+    <string name="setup_step3_title" msgid="3154757183631490281">"Congratulations, you\'re all set!"</string>
+    <string name="setup_step3_instruction" msgid="8025981829605426000">"Now you can type in all your favourite apps with <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
+    <string name="setup_step3_action" msgid="600879797256942259">"Configure additional languages"</string>
+    <string name="setup_finish_action" msgid="276559243409465389">"Finished"</string>
+    <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Dictionary Service"</string>
+    <string name="download_description" msgid="6014835283119198591">"Dictionary update information"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Add-on dictionaries"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Dictionary available"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Settings for dictionaries"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"User dictionaries"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"User dictionary"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Dictionary available"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Currently downloading"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"Installed"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"Installed, disabled"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Problem connecting to dictionary service"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"No dictionaries available"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Refresh"</string>
+    <string name="last_update" msgid="730467549913588780">"Last updated"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Checking for updates"</string>
+    <string name="message_loading" msgid="5638680861387748936">"Loading…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Main dictionary"</string>
+    <string name="cancel" msgid="6830980399865683324">"Cancel"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"Settings"</string>
+    <string name="install_dict" msgid="180852772562189365">"Install"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Cancel"</string>
+    <string name="delete_dict" msgid="756853268088330054">"Delete"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"The selected language on your mobile device has an available dictionary.&lt;br/&gt; We recommend &lt;b&gt;downloading&lt;/b&gt; the <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> dictionary to improve your typing experience.&lt;br/&gt; &lt;br/&gt; The download could take a minute or two over 3G. Charges may apply if you don\'t have an &lt;b&gt;unlimited data plan&lt;/b&gt;.&lt;br/&gt; If you are not sure which data plan you have, we recommend finding a Wi-Fi connection to start the download automatically.&lt;br/&gt; &lt;br/&gt; Tip: You can download and remove dictionaries by going to &lt;b&gt;Language &amp; input&lt;/b&gt; in the &lt;b&gt;Settings&lt;/b&gt; menu of your mobile device."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Download now (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Download over Wi-Fi"</string>
+    <string name="dict_available_notification_title" msgid="4583842811218581658">"A dictionary is available for <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Press to review and download"</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Downloading: suggestions for <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> will be ready soon."</string>
+    <string name="version_text" msgid="2715354215568469385">"Version <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
+    <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Add"</string>
+    <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Add to dictionary"</string>
+    <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Phrase"</string>
+    <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"More options"</string>
+    <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Fewer options"</string>
+    <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OK"</string>
+    <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"Word:"</string>
+    <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Shortcut:"</string>
+    <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Language:"</string>
+    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Type a word"</string>
+    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Optional shortcut"</string>
+    <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Edit word"</string>
+    <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Edit"</string>
+    <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Delete"</string>
+    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"You don\'t have any words in the user dictionary. Add a word by touching the Add (+) button."</string>
+    <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"For all languages"</string>
+    <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"More languages…"</string>
+    <string name="user_dict_settings_delete" msgid="110413335187193859">"Delete"</string>
+    <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+</resources>
diff --git a/java/res/values-en-rGB/strings-action-keys.xml b/java/res/values-en-rGB/strings-action-keys.xml
index 6514e85..e401cae 100644
--- a/java/res/values-en-rGB/strings-action-keys.xml
+++ b/java/res/values-en-rGB/strings-action-keys.xml
@@ -23,7 +23,7 @@
     <string name="label_go_key" msgid="4033615332628671065">"Go"</string>
     <string name="label_next_key" msgid="5586407279258592635">"Next"</string>
     <string name="label_previous_key" msgid="1421141755779895275">"Prev"</string>
-    <string name="label_done_key" msgid="7564866296502630852">"Finished"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Done"</string>
     <string name="label_send_key" msgid="482252074224462163">"Send"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Search"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pause"</string>
diff --git a/java/res/values-en-rGB/strings-talkback-descriptions.xml b/java/res/values-en-rGB/strings-talkback-descriptions.xml
index e209b54..78c2905 100644
--- a/java/res/values-en-rGB/strings-talkback-descriptions.xml
+++ b/java/res/values-en-rGB/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"No text entered"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrects <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> to <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> performs auto-correction"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No suggestion"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Unknown character"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"More symbols"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unknown symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unknown emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Bored face"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassed face"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Face wearing sunglasses"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surprised face"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kissing face"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Frowning face"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative characters are available"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative characters are dismissed"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative suggestions are available"</string>
diff --git a/java/res/values-en-rGB/strings.xml b/java/res/values-en-rGB/strings.xml
index 04056c2..332e01e 100644
--- a/java/res/values-en-rGB/strings.xml
+++ b/java/res/values-en-rGB/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sound on keypress"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Input preferences"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Appearance"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Multilingual options"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Gesture typing preferences"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Accounts &amp; Privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Appearance &amp; Layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Gesture Typing"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Text correction"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Advanced"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Theme"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Enable split keyboard"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Keyboard Sync"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sync is turned on"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sync your personal dictionary across devices"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sync now"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Delete cloud data"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Deletes your synced data from Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Your synced data will be deleted from the cloud. Are you sure?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Delete"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancel"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Your personal dictionary will be synced and backed up to Google servers. The statistical information of word frequency may be collected to help improve our products. The collection and usage of all the information will be compliant with "<a href="https://www.google.com/policies/privacy">"Google\'s Privacy Policy"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Please add a Google account to this device to enable this feature"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key also covers other input methods"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Language switch key"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Show when multiple input languages are enabled"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Show slide indicator"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Display visual cue while sliding from Shift or Symbol keys"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Show correction suggestions"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Display suggested words while typing"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Always show"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Show in portrait mode"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Block offensive words"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Do not suggest potentially offensive words"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Auto-correction"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No voice input methods enabled. Check Language &amp; input settings."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Languages"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help &amp; feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Languages"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touch here to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Change accounts"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"No accounts selected"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Currently using <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancel"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Sign out"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Select an account to use"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbian (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"English (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"English (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"No language (Alphabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Keyboard theme"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Holo White"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Holo Blue"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Material Dark"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Material Light"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Customised input styles"</string>
     <string name="add_style" msgid="6163126614514489951">"Add style"</string>
     <string name="add" msgid="8299699805688017798">"Add"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Enable"</string>
     <string name="not_now" msgid="6172462888202790482">"Not now"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Keypress vibration duration"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Keypress sound volume"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Read external dictionary file"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No dictionary files in the Downloads folder"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Select a dictionary file to install"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Really install this file for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"There was an error"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Welcome to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"with Gesture Typing"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Now you can type in all your favourite apps with <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configure additional languages"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Finished"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Show app icon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Display application icon in the launcher"</string>
     <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Dictionary Service"</string>
diff --git a/java/res/values-en-rIN/strings-action-keys.xml b/java/res/values-en-rIN/strings-action-keys.xml
index 6514e85..e401cae 100644
--- a/java/res/values-en-rIN/strings-action-keys.xml
+++ b/java/res/values-en-rIN/strings-action-keys.xml
@@ -23,7 +23,7 @@
     <string name="label_go_key" msgid="4033615332628671065">"Go"</string>
     <string name="label_next_key" msgid="5586407279258592635">"Next"</string>
     <string name="label_previous_key" msgid="1421141755779895275">"Prev"</string>
-    <string name="label_done_key" msgid="7564866296502630852">"Finished"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Done"</string>
     <string name="label_send_key" msgid="482252074224462163">"Send"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Search"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Pause"</string>
diff --git a/java/res/values-en-rIN/strings-talkback-descriptions.xml b/java/res/values-en-rIN/strings-talkback-descriptions.xml
index e209b54..78c2905 100644
--- a/java/res/values-en-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-en-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"No text entered"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrects <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> to <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> performs auto-correction"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No suggestion"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Unknown character"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"More symbols"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Unknown symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Unknown emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Bored face"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassed face"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Face wearing sunglasses"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surprised face"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kissing face"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Frowning face"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative characters are available"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative characters are dismissed"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative suggestions are available"</string>
diff --git a/java/res/values-en-rIN/strings.xml b/java/res/values-en-rIN/strings.xml
index 04056c2..332e01e 100644
--- a/java/res/values-en-rIN/strings.xml
+++ b/java/res/values-en-rIN/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrate on keypress"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sound on keypress"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up on key press"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Input preferences"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Appearance"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Multilingual options"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Gesture typing preferences"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Accounts &amp; Privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Appearance &amp; Layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Gesture Typing"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Text correction"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Advanced"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Theme"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Enable split keyboard"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Keyboard Sync"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sync is turned on"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sync your personal dictionary across devices"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sync now"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Delete cloud data"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Deletes your synced data from Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Your synced data will be deleted from the cloud. Are you sure?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Delete"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancel"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Your personal dictionary will be synced and backed up to Google servers. The statistical information of word frequency may be collected to help improve our products. The collection and usage of all the information will be compliant with "<a href="https://www.google.com/policies/privacy">"Google\'s Privacy Policy"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Please add a Google account to this device to enable this feature"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Switch to other input methods"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Language switch key also covers other input methods"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Language switch key"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Show when multiple input languages are enabled"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Show slide indicator"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Display visual cue while sliding from Shift or Symbol keys"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Key pop-up dismiss delay"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"No delay"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Main dictionary"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Show correction suggestions"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Display suggested words while typing"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Always show"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Show in portrait mode"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Always hide"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Block offensive words"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Do not suggest potentially offensive words"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Auto-correction"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No voice input methods enabled. Check Language &amp; input settings."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Input languages"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Languages"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help &amp; feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Languages"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Touch again to save"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touch here to save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Keyboard theme"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Change accounts"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"No accounts selected"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Currently using <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancel"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Sign out"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Select an account to use"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"English (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbian (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"English (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"English (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"No language (Alphabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Keyboard theme"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Holo White"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Holo Blue"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Material Dark"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Material Light"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Customised input styles"</string>
     <string name="add_style" msgid="6163126614514489951">"Add style"</string>
     <string name="add" msgid="8299699805688017798">"Add"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Enable"</string>
     <string name="not_now" msgid="6172462888202790482">"Not now"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Keypress vibration duration"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Keypress sound volume"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Read external dictionary file"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No dictionary files in the Downloads folder"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Select a dictionary file to install"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Really install this file for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"There was an error"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Welcome to <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"with Gesture Typing"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Now you can type in all your favourite apps with <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configure additional languages"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Finished"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Show app icon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Display application icon in the launcher"</string>
     <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Dictionary Service"</string>
diff --git a/java/res/values-es-rUS/strings-emoji-descriptions.xml b/java/res/values-es-rUS/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..e671540
--- /dev/null
+++ b/java/res/values-es-rUS/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Signo de derechos de autor"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Signo de marca registrada"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Doble signo de exclamación"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Signos de exclamación y de interrogación"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Símbolo de marca registrada"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Fuente de información"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Flecha izquierda y derecha"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Flecha arriba y abajo"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Flecha hacia el noroeste"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Flecha hacia el noreste"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Flecha hacia el sudeste"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Flecha hacia el sudoeste"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Flecha hacia la izquierda con gancho"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Flecha hacia la derecha con gancho"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Reloj"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Reloj de arena"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Dos triángulos negros hacia la derecha"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Dos triángulos negros hacia la izquierda"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Dos triángulos negros hacia arriba"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Dos triángulos negros hacia abajo"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Despertador"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Reloj de arena con la arena cayendo"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Letra m mayúscula en un círculo"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Cuadrado negro pequeño"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Cuadrado blanco pequeño"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triángulo negro hacia la derecha"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triángulo negro hacia la izquierda"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Cuadrado mediano blanco"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Cuadrado mediano negro"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Cuadrado mediano pequeño blanco"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Cuadrado mediano pequeño negro"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sol negro con rayos"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nube"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Teléfono negro"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Casilla con marca de verificación"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraguas con gotas de lluvia"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Bebida caliente"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Dedo índice blanco apuntando hacia arriba"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Cara blanca sonriente"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tauro"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Géminis"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cáncer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Escorpio"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagitario"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricornio"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Acuario"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Piscis"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Palo de pica negra"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Palo de trébol negro"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Palo de corazón negro"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Palo de diamante negro"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Aguas termales"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Símbolo universal de reciclaje en negro"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Símbolo de silla de ruedas"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ancla"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Señal de advertencia"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Señal de alto voltaje"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Círculo mediano blanco"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Círculo mediano negro"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Balón de fútbol"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Béisbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Muñeco de nieve sin nieve"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol detrás de una nube"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ofiuco"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Prohibido entrar"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Iglesia"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fuente"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandera en agujero"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Velero"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tienda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bomba de combustible"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Tijeras negras"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Marca de verificación blanca gruesa"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avión"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Sobre"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Puño levantado"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Mano levantada"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Mano haciendo la señal de la victoria"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Lápiz"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Plumín negro"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Marca de verificación gruesa"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Signo de multiplicación x grueso"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Chispas"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisco de ocho puntas"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Estrella negra de ocho puntas"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Copo de nieve"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Chispa"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Marca de tachado"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Marca de tachado en negativo encuadrada"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Signo de interrogación negro ornamental"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Signo de interrogación blanco ornamental"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Signo de exclamación blanco ornamental"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Signo de exclamación grueso"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Corazón negro sólido"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signo más grueso"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signo menos grueso"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signo de división grueso"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Flecha negra hacia la derecha"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Bucle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Bucle doble"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Flecha hacia la derecha con curva hacia arriba"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Flecha hacia la derecha con curva hacia abajo"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Flecha negra hacia la izquierda"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Flecha negra hacia arriba"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Flecha negra hacia abajo"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Cuadrado negro grande"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Cuadrado blanco grande"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Estrella mediana blanca"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Círculo grande grueso"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Guion ondulado"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Marca de cambio de parte"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograma de felicitaciones en un círculo"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograma de secreto en un círculo"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Ficha de mahjong del dragón rojo"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Carta de comodín negro"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Grupo sanguíneo A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Grupo sanguíneo B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Grupo sanguíneo O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Estacionamiento"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Tipo sanguíneo AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Cuadrado con símbolo de borrar"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cuadrado con símbolo de interesante"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Cuadrado con símbolo de gratis"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Cuadrado con símbolo de identidad"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Cuadrado con símbolo de nuevo"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Símbolo de no vale la pena encuadrado"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Símbolo de OK encuadrado"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Símbolo de SOS encuadrado"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Símbolo de novedad encuadrado"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Símbolo de versus encuadrado"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Carácter japonés para \"aquí\" encuadrado"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Carácter japonés para \"servicio\" encuadrado"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideograma japonés para \"sin cargo\" encuadrado"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideograma japonés para \"asiento reservado\" encuadrado"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideograma japonés para \"prohibición\" encuadrado"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideograma japonés para \"libre\" encuadrado"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideograma japonés para \"aceptación\" encuadrado"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideograma japonés para \"completo\" encuadrado"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideograma japonés para \"pagado\" encuadrado"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideograma japonés para \"mensual\" encuadrado"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideograma japonés para \"aplicación\" encuadrado"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideograma japonés para \"descuento\" encuadrado"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideograma japonés \"abierto\" encuadrado"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideograma japonés para \"ventaja\" en un círculo"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideograma japonés para \"aceptar\" en un círculo"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Huracán"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Niebla"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Paraguas cerrado"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Noche estrellada"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Amanecer en las montañas"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Amanecer"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Paisaje urbano al atardecer"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Atardecer entre los edificios"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arcoíris"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Puente de noche"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Ola"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcán"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Vía láctea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globo terráqueo con Europa y África"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globo terráqueo con América"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globo terráqueo con Asia y Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo terráqueo con meridianos"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Símbolo de luna nueva"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Símbolo de luna nueva visible"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Símbolo de luna en cuarto creciente"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Símbolo de luna gibosa creciente"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Símbolo de luna llena"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Símbolo de luna gibosa menguante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Símbolo de cuarto menguante"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Símbolo de luna menguante"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Luna creciente"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Luna nueva con cara"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Cuarto creciente con cara"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Cuarto menguante con cara"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Luna llena con cara"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol con cara"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Estrella brillante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Estrella fugaz"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Castaña"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Brote"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Árbol de hoja perenne"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Árbol de hoja caduca"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmera"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Flor de cerezo"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisco"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Girasol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Flor"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Espiga de maíz"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Espiga de arroz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Hierba"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trébol de cuatro hojas"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Hoja de arce"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Hoja caída"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Hoja flotando en el viento"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Hongo"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Berenjena"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uvas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melón"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Sandía"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limón"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananá"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Manzana roja"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Manzana verde"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Durazno"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cerezas"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Frutilla"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburguesa"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Porción de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Carne con hueso"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Pata de pollo"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galleta de arroz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Bola de arroz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arroz cocido"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry y arroz"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Tazón humeante"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Espaguetis"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pan"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Papas fritas"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Batata asada"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Camarón frito"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Croqueta de pescado con forma de espiral"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Cono de helado"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Hielo triturado"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Helado"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Dona"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Galleta"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barra de chocolate"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Dulces"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Paleta"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Flan"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Tarro de miel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Rebanada de pastel"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Caja bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Tazón con comida"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Sartén"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Tenedor y cuchillo"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Taza de té sin mango"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Botella y pocillo de sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Copa de vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Copa de cóctel"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Bebida tropical"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Jarro de cerveza"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Brindar con jarros de cerveza"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberón"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Cinta"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Regalo envuelto"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Pastel de cumpleaños"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Linterna de Halloween"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Árbol de Navidad"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Papá Noel"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fuegos artificiales"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Bengala"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Globo"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Cotillón"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Lluvia de papel picado"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Árbol de tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Banderas cruzadas"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Adorno de pino"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Muñecas japonesas"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Banderas en forma de carpa"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Campanilla de viento"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Ceremonia de contemplación de la luna"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Mochila"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Birrete"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Caballo de carrusel"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Vuelta al mundo"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Montaña rusa"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Caña y pescados"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Micrófono"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Cámara cinematográfica"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cine"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Auriculares"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta de artista"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Sombrero de copa"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Carpa de circo"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Boleto"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Claqueta"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Artes escénicas"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videojuego"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Dar en el blanco"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Máquinas tragamonedas"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dado"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bolos"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Naipes japoneses tradicionales"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota musical"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Varias notas musicales"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofón"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Teclado musical"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violín"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitura"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Camiseta deportiva con banda"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Pelota y raqueta de tenis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Bota de esquiar y esquí"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Pelota y aro de básquet"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandera a cuadros"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Practicante de snowboard"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Corredor"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfista"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofeo"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Carrera de caballos"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Fútbol americano"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Balón de rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nadador"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Construcción de casas"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa con jardín"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Edificio de oficinas"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Oficina postal japonesa"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Oficina postal europea"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banco"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Cajero automático"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel de citas"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Minimercado"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Escuela"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Centro comercial"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fábrica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Linterna izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Castillo japonés"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castillo europeo"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rata"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Ratón"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Buey"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Búfalo de agua"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vaca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Conejo"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gato"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragón"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Cocodrilo"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Ballena"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Caracol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serpiente"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Caballo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Carnero"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Cabra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Oveja"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Mono"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gallo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Gallina"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Perro"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cerdo"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Jabalí"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pulpo"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Concha en espiral"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Bicho"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Hormiga"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abeja"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Mariquita"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Pez"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Pez tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Pez globo"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tortuga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pollito saliendo del huevo"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pollito"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pollito de frente"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Pájaro"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingüino"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Camello dromedario"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Camello bactriano"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfín"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Cabeza de ratón"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cabeza de vaca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Cabeza de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Cabeza de conejo"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cabeza de gato"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Cabeza de dragón"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Ballena expulsando un chorro de agua"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Cabeza de caballo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Cabeza de mono"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Cabeza de perro"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cabeza de cerdo"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Cabeza de rana"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Cara de hámster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Cabeza de lobo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Cabeza de oso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Cabeza de panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nariz de cerdo"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Huellas de patas"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ojos"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Orejas"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nariz"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Boca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lengua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Dorso de dedo índice blanco apuntando hacia arriba"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Dorso de dedo índice blanco apuntando hacia abajo"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Dorso de dedo índice blanco apuntando hacia la izquierda"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Dorso de dedo índice blanco apuntando hacia la derecha"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Símbolo de puño"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Signo de saludo con la mano"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Signo de OK con la mano"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Signo de pulgar hacia arriba"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Signo de pulgar hacia abajo"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Signo de manos aplaudiendo"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Signo de manos abiertas"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Corona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Sombrero de mujer"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Anteojos"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Corbata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Camiseta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Vestido"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Vestimenta de mujer"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Monedero"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Bolso de mano"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Estuche"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Zapato de hombre"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Calzado deportivo"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Zapato de taco alto"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandalia de mujer"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Botas de mujer"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Huellas de pie"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta de un busto"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silueta de dos bustos"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Niño"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Niña"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Hombre"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Mujer"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Hombre y mujer de la mano"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dos hombres de la mano"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dos mujeres de la mano"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policía"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Mujer con orejas de conejo"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Novia con velo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persona con cabello rubio"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Hombre con gorro gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Hombre con turbante"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Anciano"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Anciana"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bebé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Obrero"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogro japonés"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Duende japonés"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Ángel bebé"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Alienígena extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstruo de otro planeta"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Diablillo"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Calavera"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Persona del centro de información"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardia"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Bailarín"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lápiz labial"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Esmalte de uñas"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masaje facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Corte de cabello"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Poste de barbero"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Jeringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Píldora"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Marca de beso"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Carta de amor"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anillo"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Piedra preciosa"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Beso"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Buqué"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pareja con un corazón"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Boda"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Corazón latiendo"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Corazón roto"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dos corazones"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Corazón chispeante"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Corazón creciente"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Corazón con flecha"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Corazón azul"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Corazón verde"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Corazón amarillo"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Corazón púrpura"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Corazón con cinta"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Corazones rotando"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Adorno con corazón"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Rombo con un punto en el interior"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Bombilla eléctrica"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Símbolo de ira"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Símbolo de sueño"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Símbolo de choque"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Símbolo de gotas de sudor"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Gotita"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Símbolo de guion"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Montaña de caca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bíceps flexionados"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Símbolo de mareo"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Globo de conversación"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Globo de pensamiento"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Flor blanca"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Símbolo de cien puntos"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Bolso de dinero"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Cambio de moneda"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Símbolo de dólar grueso"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Tarjeta de crédito"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billete con símbolo de yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billete con signo de dólar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billete con símbolo de euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billete con símbolo de libra"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Dinero con alas"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Tabla con tendencia ascendente y símbolo de yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Asiento"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Computadora personal"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Maletín"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisco"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquete"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disco óptico"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Carpeta de archivos"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Carpeta de archivos abierta"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Página doblada"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Página hacia arriba"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendario"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendario exfoliador"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Fichero"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Gráfico con tendencia ascendente"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Gráfico con tendencia descendente"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Gráfico de barras"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Portapapeles"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Chinche"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Chinche redonda"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Sujetapapeles"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Regla recta"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Regla triangular"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Señaladores"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Libro mayor"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Cuaderno"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Cuaderno con tapa decorada"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Libro cerrado"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Libro abierto"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Libro verde"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Libro azul"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Libro naranja"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Libros"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Distintivo con nombre"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Desplazamiento"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Nota"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Receptor del teléfono"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Localizador"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Máquina de fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena parabólica"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Altoparlante para anuncios"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megáfono para alentar"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Bandeja de salida"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Bandeja de entrada"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paquete"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Símbolo de correo electrónico"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Sobre de mensaje entrante"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Sobre con una flecha hacia abajo"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Buzón cerrado con bandera bajada"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Buzón cerrado con bandera levantada"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Buzón abierto con bandera levantada"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Buzón abierto con bandera baja"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Buzón"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Corneta de posta"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Periódico"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Teléfono celular"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Teléfono celular con flecha hacia la derecha en el lado izquierdo"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Modo vibración"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Teléfono celular apagado"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Teléfonos celulares prohibidos"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena con barras"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Cámara"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videocámara"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocasete"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Flechas cruzadas hacia la derecha"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Flechas hacia la izquierda y hacia la derecha en un círculo abierto en sentido horario"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Flechas hacia la izquierda y hacia la derecha en un círculo abierto en sentido horario con un número uno superpuesto"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Flechas hacia arriba y hacia abajo en un círculo abierto en sentido horario"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Flechas hacia arriba y hacia abajo en círculo abierto en sentido antihorario"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Símbolo de brillo tenue"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Símbolo de brillo intenso"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altavoz tachado"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altavoz"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altavoz con una onda de sonido"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altavoz con tres ondas de sonido"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batería"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Enchufe eléctrico"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa hacia la izquierda"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa hacia la derecha"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Candado con pluma"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Candado cerrado con llave"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Llave"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Candado"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Candado abierto"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Campana"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Campana tachada"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Señalador"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Símbolo de vínculo"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Botón de radio"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Atrás con flecha hacia la izquierda encima"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Fin con flecha hacia la izquierda encima"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Activado con signo de exclamación y con flecha hacia la izquierda y la derecha encima"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Próximamente con flecha hacia la derecha encima"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Arriba con flecha hacia arriba encima"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Símbolo de prohibido para menores de 18 años"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Diez con forma de tecla"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Símbolo para ingresar letras latinas mayúsculas"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Símbolo para ingresar letras latinas minúsculas"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Símbolo para ingresar números"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Símbolos"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Símbolo para ingresar letras latinas"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fuego"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Linterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Llave inglesa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martillo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Tuerca y tornillo"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Cuchillo"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscopio"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescopio"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bola de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Estrella de seis puntas con punto central"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Símbolo japonés para principiante"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblema con tridente"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botón cuadrado negro"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botón cuadrado blanco"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Círculo rojo grande"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Círculo azul grande"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Rombo naranja grande"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Rombo azul grande"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Rombo naranja pequeño"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Rombo azul pequeño"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triángulo rojo hacia arriba"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triángulo rojo hacia abajo"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triángulo rojo pequeño hacia arriba"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triángulo rojo pequeño hacia abajo"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Cara del reloj con la una en punto"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Cara del reloj con las dos en punto"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Cara del reloj con las tres en punto"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Cara del reloj con las cuatro en punto"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Cara del reloj con las cinco en punto"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Cara del reloj con las seis en punto"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Cara del reloj con las siete en punto"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Cara del reloj con las ocho en punto"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Cara del reloj con las nueve en punto"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Cara del reloj con las diez en punto"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Cara del reloj con las once en punto"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Cara del reloj con las doce en punto"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Cara del reloj con la una y media"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Cara del reloj con las dos y media"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Cara del reloj con las tres y media"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Cara del reloj con las cuatro y media"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Cara del reloj con las cinco y media"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Cara del reloj con las seis y media"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Cara del reloj con las siete y media"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Cara del reloj con las ocho y media"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Cara del reloj con las nueve y media"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Cara del reloj con las diez y media"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Cara del reloj con las once y media"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Cara del reloj con las doce y media"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Monte Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Torre de Tokio"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Estatua de la Libertad"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silueta de Japón"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moái"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Cara con una gran sonrisa"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Cara con una gran sonrisa y ojos alegres"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Cara con lágrimas de alegría"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Cara sonriente con la boca abierta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Cara sonriente con la boca abierta y ojos alegres"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Cara sonriente con la boca abierta y sudor frío"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Cara sonriente con la boca abierta y ojos bien cerrados"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Cara sonriente con halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Cara sonriente con cuernos"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Guiño"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Cara sonriente con ojos alegres"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Cara saboreando comida deliciosa"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Cara de alivio"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Cara sonriente con ojos en forma de corazón"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Cara sonriente con anteojos de sol"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Cara sonriente con ojos hacia un costado"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Cara neutral"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Cara inexpresiva"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Cara poco divertida"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Cara con sudor frío"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Cara pensativa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Cara confundida"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Cara frustrada"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Cara dando un beso"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Cara tirando un beso"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Beso con ojos alegres"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Beso con ojos cerrados"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Cara con la lengua afuera"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Cara con la lengua afuera y guiño"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Cara con la lengua afuera y ojos bien cerrados"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Cara de decepción"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Cara de preocupación"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Cara enojada"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Cara de descontento"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Cara llorando"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Cara perseverante"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Cara con expresión de triunfo"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Cara decepcionada pero aliviada"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Cara con ceño fruncido y boca abierta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Cara de angustia"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Cara de miedo"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Cara de sufrimiento"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Cara de sueño"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Cara de cansancio"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Muecas"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Cara llorando a gritos"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Cara con la boca abierta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Cara perpleja"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Cara con la boca abierta y sudor frío"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Grito de miedo"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Cara de asombro"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Cara sonrojada"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Cara durmiendo"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Cara mareada"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Cara sin boca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Cara con mascarilla"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Cara de gato con una gran sonrisa y ojos alegres"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cara de gato con lágrimas de alegría"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Cara de gato sonriente con la boca abierta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Cara de gato sonriente con ojos en forma de corazón"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cara de gato con sonrisa irónica"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Cara de gato dando un beso con los ojos cerrados"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Cara de gato descontento"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Cara de gato llorando"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Cara de gato sufriendo"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Cara con gesto de no bueno"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Cara con gesto de aceptación"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persona haciendo una reverencia"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Mono que no ve maldades"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Mono que no escucha maldades"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Mono que no dice maldades"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Persona feliz con una mano arriba"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persona con ambas manos arriba en celebración"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persona con el ceño fruncido"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persona con cara de descontento"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persona con las manos juntas"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Cohete"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicóptero"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotora a vapor"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Coche de ferrocarril"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tren de alta velocidad"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Tren bala de alta velocidad"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Subterráneo"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tren ligero"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Estación"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tranvía"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Coche de tranvía"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobús"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobús próximo"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolebús"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Parada de autobús"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibús"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulancia"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camión de bomberos"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Patrulla de policía"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Patrulla de policía próxima"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi próximo"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automóvil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automóvil próximo"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Vehículo de uso recreativo"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camión de reparto"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camión articulado"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monocarril"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ferrocarril de montaña"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Ferrocarril de suspensión"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Teleférico de montaña"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Tranvía aéreo"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Barco"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Bote de remos"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Lancha"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semáforo horizontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semáforo vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Señal de obra en construcción"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Luz de patrulla de policía"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bandera triangular en un poste"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Puerta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Señal de prohibido entrar"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Símbolo de permitido fumar"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Símbolo de prohibido fumar"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Símbolo de arrojar la basura en su sitio"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Símbolo de no arrojar basura al piso"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Símbolo de agua potable"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Símbolo de agua no potable"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Prohibido andar en bicicleta"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista de montaña"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Peatón"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Prohibido para peatones"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Niños cruzando"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Símbolo de baño para hombres"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Símbolo de baño para mujeres"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Baños"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Símbolo de bebé"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Inodoro"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Retrete"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Ducha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Baño"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bañera"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Control de pasaporte"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Aduana"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Reclamo de equipajes"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Consigna"</string>
+</resources>
diff --git a/java/res/values-es-rUS/strings-talkback-descriptions.xml b/java/res/values-es-rUS/strings-talkback-descriptions.xml
index 0bde67e..7b5da26 100644
--- a/java/res/values-es-rUS/strings-talkback-descriptions.xml
+++ b/java/res/values-es-rUS/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"No se ingresó texto."</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> por <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrige automáticamente."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No hay sugerencias."</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Carácter desconocido"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Mayúsculas"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Más símbolos"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I mayúscula, con punto superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconocido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconocido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara de aburrimiento"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara de vergüenza"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara con anteojos de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara de sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara dando un beso"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara con el ceño fruncido"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Hay caracteres alternativos disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Los caracteres alternativos se descartan."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Hay sugerencias alternativas disponibles."</string>
diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml
index 9959278..3cb2982 100644
--- a/java/res/values-es-rUS/strings.xml
+++ b/java/res/values-es-rUS/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar teclas"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sonar al pulsar las teclas"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Aviso emergente al pulsar tecla"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferencias"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Cuentas y privacidad"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Apariencia y diseños"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escritura gestual"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Corrección ortográfica"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avanzada"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Habilitar teclado dividido"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronizar el Teclado de Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sincronización activada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincroniza tu diccionario personal en distintos dispositivos."</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizar ahora"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Eliminar datos de la nube"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Elimina los datos sincronizados de Google."</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Se eliminarán los datos sincronizados de la nube. ¿Estás seguro?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Eliminar"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancelar"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Se creará una copia de tu diccionario personal y se sincronizará con los servidores de Google. Es posible que se recopile información estadística de la frecuencia de palabras para mejorar nuestros productos. La recopilación y el uso de toda la información se realizará conforme a la "<a href="https://www.google.com/policies/privacy">"Política de privacidad de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Para habilitar esta función, agrega una cuenta de Google."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma abarca otros métodos de entrada."</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla de selección de idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostrar cuando se habiliten varios idiomas de entrada"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador p. deslizar"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar indic. visual al deslizar de teclas símbolo o mayúscula"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Demora para ignorar tecla emergente"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin demora"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminada"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugerencias de correcciones"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Mostrar palabras sugeridas al escribir"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar en modo de retrato"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palabras ofensivas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"No sugerir posibles palabras ofensivas"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Corrección automática"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada por voz"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"No hay métodos de entrada de voz habilitados. Comprueba la configuración de Teclado e idioma."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ayuda y comentarios"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Vuelve a tocar para guardar."</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tocar aquí para guardar."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema del teclado"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Cambiar cuentas"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"No hay cuentas seleccionadas."</string>
+    <string name="account_selected" msgid="2846876462199625974">"En uso actualmente: <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Aceptar"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancelar"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Salir"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Seleccionar una cuenta para usar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EE.UU.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EE.UU.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbio (latino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés, Reino Unido (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés, EE. UU. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español, EE. UU. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latinoamérica)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema del teclado"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
     <string name="add_style" msgid="6163126614514489951">"Agr. estilo"</string>
     <string name="add" msgid="8299699805688017798">"Agregar"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activar"</string>
     <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Demora de presión prolongada"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durac. vibrac. al presionar"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Vol. sonido al presionar tecla"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leer archivo de diccionario externo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hay archivos de diccionario en la carpeta de descargas."</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleccionar archivo de diccionario para instalar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"¿Realmente quieres instalar este archivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Se produjo un error."</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Demora de presión prolongada"</string>
     <string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Te damos la bienvenida a <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"con escritura gestual"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Ahora puedes escribir en todas las aplicaciones que quieras con <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurar otros idiomas"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Listo"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostrar ícono de aplicación"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostrar ícono de aplicación en el selector"</string>
     <string name="app_name" msgid="6320102637491234792">"Proveedor de diccionarios"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveedor de diccionarios"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Servicio de diccionarios"</string>
diff --git a/java/res/values-es/strings-emoji-descriptions.xml b/java/res/values-es/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..315654e
--- /dev/null
+++ b/java/res/values-es/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Signo de copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Signo de marca registrada"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Signo de exclamación doble"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Signos de exclamación e interrogación"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Signo de marca comercial"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Punto de información"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Flecha hacia izquierda y derecha"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Flecha hacia arriba y abajo"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Flecha hacia el noroeste"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Flecha hacia el nordeste"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Flecha hacia el sureste"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Flecha hacia el suroeste"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Flecha hacia la izquierda con gancho"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Flecha hacia la derecha con gancho"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Reloj de pulsera"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Reloj de arena"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Triángulo doble negro hacia la derecha"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Triángulo doble negro hacia la izquierda"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Triángulo doble negro hacia arriba"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Triángulo doble negro hacia abajo"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Despertador"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Reloj de arena con la arena cayendo"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Letra M mayúscula en un círculo"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Cuadrado negro pequeño"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Cuadrado blanco pequeño"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triángulo negro hacia la derecha"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triángulo negro hacia la izquierda"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Cuadrado mediano blanco"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Cuadrado mediano negro"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Cuadrado pequeño-mediano blanco"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Cuadrado pequeño-mediano negro"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sol negro con rayos"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nube"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Teléfono negro"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Casilla con marca de verificación"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Sombrilla con gotas de lluvia"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Bebida caliente"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Dedo índice hacia arriba"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Cara sonriendo"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tauro"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Géminis"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cáncer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Escorpio"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagitario"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricornio"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Acuario"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Piscis"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Palo de espadas negro"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Palo de tréboles negro"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Palo de corazones negro"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Palo de diamantes negro"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Manantial termal"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Símbolo de reciclaje universal negro"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Símbolo de silla de ruedas"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ancla"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Signo de advertencia"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Signo de alto voltaje"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Círculo blanco mediano"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Círculo negro mediano"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Balón de fútbol"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Pelota de béisbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Hombre de nieve sin nieve"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol detrás de una nube"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ofiuco"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Prohibida la entrada"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Iglesia"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fuente"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Banderín en agujero"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Barco de vela"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tienda de campaña"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bomba de gasolinera"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Tijeras negras"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Marca de verificación blanca"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avión"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Sobre"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Puño alzado"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Mano alzada"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Mano haciendo la señal de la victoria"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Lápiz"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Pluma estilográfica negra"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Marca de verificación"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Signo de multiplicación"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Chispas"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisco de ocho puntas"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Estrella negra de ocho puntas"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Copo de nieve"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Chispa"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Marcha de tachado"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Marca de tachado en cuadrado negativo"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Signo de interrogación negro ornamental"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Signo de interrogación blanco ornamental"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Signo de exclamación blanco ornamental"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Signo de exclamación"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Corazón negro sólido"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signo más"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signo menos"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signo de división"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Flecha negra hacia la derecha"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Bucle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Bucle doble"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Flecha hacia la derecha con curva hacia arriba"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Flecha hacia la derecha con curva hacia abajo"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Flecha negra hacia la izquierda"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Flecha negra hacia arriba"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Flecha negra hacia abajo"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Cuadrado grande negro"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Cuadrado grande blanco"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Estrella mediana blanca"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Círculo grande"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Guión ondulado"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Marca de turno en una canción"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograma de enhorabuena en un círculo"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograma de secreto en un círculo"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Ficha de mahjong del dragón rojo"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Carta de joker negro"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Grupo sanguíneo A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Grupo sanguíneo B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Grupo sanguíneo O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Aparcamiento"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Tipo sanguíneo AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Cuadrado con símbolo de borrar"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cuadrado con símbolo de interesante"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Cuadrado con símbolo de gratis"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Cuadrado con símbolo de identidad"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Cuadrado con símbolo de nuevo"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Cuadrado con símbolo de no bueno"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Cuadrado con símbolo de OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Cuadrado con símbolo de SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Cuadrado con símbolo de novedad"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Cuadrado con símbolo de versus"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Cuadrado con ideograma japonés para \"aquí\""</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Cuadrado con ideograma japonés para \"servicio\""</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Cuadrado con ideograma japonés para \"libre de cargo\""</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Cuadrado con ideograma japonés para \"asiento reservado\""</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Cuadrado con ideograma japonés para \"prohibición\""</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Cuadrado con ideograma japonés para \"libre\""</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Cuadrado con ideograma japonés para \"aceptación\""</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Cuadrado con ideograma japonés para \"ocupación completa\""</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Cuadrado con ideograma japonés para \"pagado\""</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Cuadrado con ideograma japonés para \"mensual\""</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Cuadrado con ideograma japonés para \"aplicación\""</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Cuadrado con ideograma japonés para \"descuento\""</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Cuadrado con ideograma japonés para \"negocio\""</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Círculo con ideograma japonés para \"ventaja\""</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Círculo con ideograma japonés para \"ocupación completa\""</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciclón"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Niebla"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Paraguas cerrado"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Noche con estrellas"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Amanecer entre montañas"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Amanecer"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Ciudad al atardecer"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Puesta de sol sobre edificios"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arcoíris"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Puente de noche"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Ola de mar"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcán"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Vía Láctea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globo terráqueo con Europa-África"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globo terráqueo con América"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globo terráqueo con Asia-Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo terráqueo con meridianos"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Símbolo de luna nueva"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Símbolo de luna nueva visible"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Símbolo de luna en cuarto creciente"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Símbolo de luna gibosa creciente"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Símbolo de luna nueva"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Símbolo de luna gibosa menguante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Símbolo de luna en cuarto menguante"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Símbolo de luna menguante"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Luna creciente"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Luna nueva con cara"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Luna en cuarto creciente con cara"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Luna en cuarto menguante con cara"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Luna llena con cara"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol con cara"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Estrella brillante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Estrella fugaz"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Castaña"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Planta joven"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Árbol de hoja perenne"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Árbol de hoja caduca"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmera"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Flor de cerezo"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisco"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Girasol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Flor"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Mazorca de maíz"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Mazorca de arroz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Hierba"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trébol de cuatro hojas"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Hoja de arce"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Hojas caídas"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Hojas al viento"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Seta"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Berenjena"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uvas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melón"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Sandía"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Naranja"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limón"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Plátano"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Piña"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Manzana roja"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Manzana verde"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Melocotón"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cerezas"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Fresa"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburguesa"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Trozo de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Carne con hueso"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Muslo de pollo"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galleta de arroz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Bola de arroz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arroz cocido"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Arroz con curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Tazón de fideos"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Espaguetis"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pan"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patatas fritas"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Patata asada"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Mochi"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Gamba frita"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Pastel de pescado con forma de espiral"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Helado suave"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Granizado"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Helado"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Dónut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barra de chocolate"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Caramelo"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Piruleta"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Flan"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Tarro de miel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Pedazo de tarta"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Caja de bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Guiso"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Sartén"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Cuchillo y tenedor"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Taza de té sin mango"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Botella y tazón de sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vaso de vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Vaso de cóctel"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Bebida tropical"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Jarra de cerveza"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Jarras de cerveza brindando"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberón"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Lazo"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Regalo envuelto"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Tarta de cumpleaños"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Linterna de Halloween"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Árbol de Navidad"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Papá Noel"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fuegos artificiales"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Luz de bengala"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Globo"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Lanzador de confeti"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Lluvia de confeti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Árbol de Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Banderas cruzadas"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Decoración de pino"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Muñecas japonesas"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Banderín de carpas"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Campanilla de viento"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Ceremonia de contemplación de la luna"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Mochila escolar"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Birrete de graduado"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Caballito de tiovivo"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Noria de feria"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Montaña rusa"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Caña pescar con pez"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Micrófono"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Cámara cinematográfica"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cine"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Auriculares"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta de pintor"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Sombrero de copa"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Carpa de circo"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Entrada"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Claqueta"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Artes escénicas"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videojuego"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Diana"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Máquina tragaperras"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dado"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bolos"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Naipes de flor"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota musical"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Varias notas musicales"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofón"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Teclado musical"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violín"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Pentagrama musical"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Camiseta con banda"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Pelota y raqueta de tenis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Esquíes y bastones"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Balón de baloncesto y canasta"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandera a cuadros"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Practicante de snowboard"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Corredor"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfero"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofeo"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Carrera de caballos"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Fútbol americano"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Balón de rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nadador"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Casa"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa con jardín"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Edificio de oficinas"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Oficina de correos japonesa"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Oficina de correos europea"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banco"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Cajero automático"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel del amor"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Tienda de 24 horas"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Colegio"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Centro comercial"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Factoría"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Linterna de izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Castillo japonés"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castillo europeo"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rata"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Ratón"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Buey"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Búfalo de agua"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vaca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Conejo"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gato"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragón"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Cocodrilo"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Ballena"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Caracol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serpiente"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Caballo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Carnero"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Cabra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Oveja"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Mono"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gallo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Gallina"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Perro"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cerdo"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Jabalí"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pulpo"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Concha de caracol"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Error"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Hormiga"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abeja"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Mariquita"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Pez"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Pez tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Pez globo"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tortuga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pollito rompiendo el cascarón"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pollito"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pollito de frente"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Pájaro"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingüino"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedario"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Camello bactriano"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfín"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Cara de ratón"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cara de vaca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Cara de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Cara de conejo"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cara de gato"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Cara de dragón"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Ballena soltando chorro"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Cara de caballo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Cara de mono"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Cara de perro"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cara de cerdo"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Cara de rana"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Cara de hámster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Cara de lobo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Cara de oso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Cara de panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nariz de cerdo"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Huellas de pezuñas"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ojos"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Oreja"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nariz"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Boca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lengua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Dedo índice apuntando hacia arriba"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Dedo índice apuntando hacia abajo"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Dedo índice apuntando hacia la izquierda"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Dedo índice apuntando hacia la derecha"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Signo de puño con la mano"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Signo de agitar la mano"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Signo de OK con la mano"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Signo de pulgar hacia arriba"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Signo de pulgar hacia abajo"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Signo de manos haciendo palmas"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Signo de manos abiertas"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Corona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Sombrero de mujer"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Anteojos"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Nudo de corbata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Camiseta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Vaqueros"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Vestido"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Ropa de mujer"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Monedero"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Bolso"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Bolso de mano"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Zapato de hombre"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Zapatilla deportiva"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Zapato de tacón"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandalia de mujer"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Botas de mujer"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Huellas de pies"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta de torso"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silueta de torsos"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Niño"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Niña"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Hombre"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Mujer"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Hombre y mujer de la mano"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dos hombres de la mano"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dos mujeres de la mano"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Agente de policía"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Mujer con orejas de conejo"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Novia con velo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persona con pelo rubio"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Hombre con gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Hombre con turbante"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Hombre mayor"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Mujer mayor"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bebé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Obrero de la construcción"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogro japonés"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Duende japonés"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Angelito"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Alienígena extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstruo alienígena"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Diablillo"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Calavera"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Empleada del centro de información"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardia"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Bailarina"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lápiz de labios"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Esmalte de uñas"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masaje facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Corte de pelo"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Poste de barbero"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Jeringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Píldora"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Marca de labios"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Carta de amor"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anillo"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Piedra preciosa"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Beso"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Ramo de flores"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pareja con corazón"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Boda"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Corazón palpitante"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Corazón partido"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dos corazones"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Corazón brillante"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Corazón creciente"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Corazón con una fecha"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Corazón azul"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Corazón verde"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Corazón amarillo"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Corazón morado"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Corazón con lazo"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Corazones dando vueltas"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Decoración de corazón"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Rombo con un punto en el interior"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Bombilla eléctrica"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Símbolo de enfado"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Símbolo de sueño"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Símbolo de colisión"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Símbolo de gotas de sudor"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Gota"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Símbolo de correr"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Caca con ojos"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bíceps flexionado"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Símbolo de mareo"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bocadillo de conversación"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bocadillo de pensamiento"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Flor blanca"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Símbolo de cien puntos"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Bolsa de dinero"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Cambio de divisas"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Símbolo de dólar"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Tarjeta de crédito"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billete con símbolo de yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billete con el signo de dólar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billete con símbolo de euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billete con símbolo de libra"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Dinero con alas"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Gráfico con símbolos de yen y tendencia ascendente"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Asiento"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Ordenador personal"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Maletín"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquete"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disco óptico"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Carpeta de archivos"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Carpeta de archivos abierta"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Página doblada"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Página hacia arriba"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendario"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendario con anillas"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Tarjetero"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Gráfico con tendencia ascendente"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Gráfico con tendencia descendente"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Gráfico de barras"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Tabla sujetapapeles"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Chincheta"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Chincheta redonda"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Sujetapapeles"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Regla recta"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Regla triangular"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Marcadores"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Libro de contabilidad"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Cuaderno"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Cuaderno con portada decorada"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Libro cerrado"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Libro abierto"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Libro verde"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Libro azul"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Libro naranja"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Libros"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Etiqueta identificativa"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Pergamino"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Nota"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Auricular de teléfono"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Busca"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Máquina de fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena de satélite"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Altavoz de mano"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megáfono"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Bandeja de salida"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Bandeja de entrada"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paquete"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Símbolo de correo electrónico"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Sobre de correo entrante"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Sobre con flecha hacia abajo encima"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Buzón cerrado con bandera bajada"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Buzón cerrado con bandera levantada"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Buzón abierto con bandera levantada"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Buzón abierto con bandera bajada"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Buzón"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Cometa de posta"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Periódico"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Teléfono móvil"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Teléfono móvil con flecha hacia la derecha a la izquierda"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Modo vibración"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Teléfono móvil apagado"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Teléfonos móviles prohibidos"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena con barras"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Cámara"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videocámara"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisión"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocasete"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Flechas entrecruzadas hacia la derecha"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Flechas hacia la izquierda y hacia la derecha formando un círculo abierto en sentido horario"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Flechas hacia la izquierda y hacia la derecha formando un círculo abierto en sentido horario con un número uno en un círculo"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Flechas hacia arriba y hacia abajo formando un círculo abierto en sentido horario"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Flechas hacia arriba y hacia abajo formando un círculo abierto en sentido antihorario"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Símbolo de brillo bajo"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Símbolo de brillo alto"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altavoz con marca de cancelación"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altavoz"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altavoz con una onda de sonido"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altavoz con tres ondas de sonido"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batería"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Enchufe eléctrico"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa hacia la izquierda"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa hacia la derecha"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Candado con pluma estilográfica"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Candado cerrado con llave"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Llave"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Candado"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Candado abierto"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Campana"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Campana con signo de cancelación"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Marcador"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Símbolo de enlace"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Botón de opción"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Atrás con flecha hacia la izquierda encima"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Final con flecha hacia la izquierda encima"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Adelante con signo de exclamación y flecha hacia la izquierda encima"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Pronto con flecha hacia la derecha encima"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Arriba con flecha hacia arriba encima"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Prohibido menores de 18"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tecla 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Símbolo de letras mayúsculas latinas"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Símbolo de letras minúsculas latinas"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Símbolo de números"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Símbolos"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Símbolo de letras latinas"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fuego"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Linterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Llave inglesa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martillo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Tornillo y tuerca"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Cuchillo de cocina"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscopio"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescopio"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bola de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Estrella de seis puntas con punto central"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Símbolo japonés para principiante"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblema con tridente"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botón cuadrado negro"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botón cuadrado blanco"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Círculo rojo grande"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Círculo azul grande"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Rombo naranja grande"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Rombo azul grande"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Rombo naranja pequeño"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Rombo azul pequeño"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triángulo rojo hacia arriba"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triángulo rojo hacia abajo"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triángulo rojo pequeño hacia arriba"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triángulo rojo pequeño hacia abajo"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Esfera de reloj con la uno en punto"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Esfera de reloj con las dos en punto"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Esfera de reloj con las tres en punto"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Esfera de reloj con las cuatro en punto"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Esfera de reloj con las cinco en punto"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Esfera de reloj con las seis en punto"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Esfera de reloj con las siete en punto"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Esfera de reloj con las ocho en punto"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Esfera de reloj con las nueve en punto"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Esfera de reloj con las diez en punto"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Esfera de reloj con las once en punto"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Esfera de reloj con las doce en punto"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Esfera de reloj con la una y media"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Esfera de reloj con las dos y media"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Esfera de reloj con las tres y media"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Esfera de reloj con las cuatro y media"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Esfera de reloj con las cinco y media"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Esfera de reloj con las seis y media"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Esfera de reloj con las siete y media"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Esfera de reloj con las ocho y media"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Esfera de reloj con las nueve y media"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Esfera de reloj con las diez y media"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Esfera de reloj con las once y media"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Esfera de reloj con las doce y media"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Monte Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Torre de Tokio"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Estatua de la Libertad"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silueta de Japón"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moái"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Cara sonriente"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Cara sonriente con ojos sonrientes"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Cara con lágrimas de alegría"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Cara sonriente con boca abierta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Cara sonriente con boca abierta y ojos sonrientes"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Cara sonriente con boca abierta y sudor frío"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Cara sonriente con boca abierta y ojos muy cerrados"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Cara sonriente con aureola"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Cara sonriente con cuernos"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Cara guiñando un ojo"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Cara sonriente con ojos sonrientes"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Cara saboreando una comida deliciosa"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Cara de alivio"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Cara sonriente con corazones en los ojos"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Cara sonriente con gafas de sol"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Cara sonriendo con superioridad"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Cara neutral"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Cara inexpresiva"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Cara poco divertida"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Cara con sudor frío"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Cara pensativa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Cara confusa"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Cara frustrada"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Cara dando un beso"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Cara lanzando un beso"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Cara dando un beso con ojos sonrientes"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Cara dando un beso con ojos cerrados"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Cara sacando la lengua"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Cara sacando la lengua y guiñando un ojo"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Cara sacando la lengua con los ojos cerrados"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Cara decepcionada"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Cara preocupada"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Cara enfadada"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Cara enojada"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Cara llorando"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Cara perseverante"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Cara con mirada de triunfo"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Cara decepcionada pero aliviada"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Cara con el ceño fruncido y la boca abierta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Cara angustiada"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Cara asustada"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Cara cansada"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Cara con sueño"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Cara cansada"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Cara haciendo una mueca"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Cara llorando fuerte"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Cara con la boca abierta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Cara estupefacta"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Cara con la boca abierta y sudor frío"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Cara gritando de miedo"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Cara de asombro"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Cara sonrojada"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Cara durmiendo"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Cara mareada"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Cara sin boca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Cara con mascarilla"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Cara de gato sonriente con ojos sonrientes"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cara de gato con lágrimas de alegría"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Cara de gato sonriente con la boca abierta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Cara de gato con corazones en los ojos"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cara de gato con sonrisa irónica"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Cara de gato dando un beso con los ojos cerrados"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Cara de gato enojada"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Cara de gato llorando"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Cara de gato cansada"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Cara con gesto de no está bien"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Cara con gesto de OK"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persona haciendo una reverencia"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Mono que no ve el mal"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Mono que no oye el mal"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Mono que no dice el mal"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Persona feliz levantando una mano"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persona levantando ambas manos en celebración"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persona frunciendo el ceño"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persona con cara enojada"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persona con las manos en oración"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Cohete"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicóptero"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotora de vapor"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Tren eléctrico"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tren de alta velocidad"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Tren de alta velocidad con punta de bala"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tren ligero"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Estación"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tranvía"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagón de tranvía"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobús"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobús próximo"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolebús"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Parada de autobús"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibús"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulancia"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Coche de bomberos"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Coche de policía"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Coche de policía próximo"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi próximo"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automóvil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automóvil próximo"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Autocaravana"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camión de reparto"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camión articulado"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorraíl"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ferrocarril de montaña"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Ferrocarril de suspensión"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Telecabina de montaña"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Telecabina"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Barco"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Barca de remos"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Lancha motora"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semáforo horizontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semáforo vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Signo de construcción"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Sirena de la policía"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bandera de localización triangular"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Puerta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Señal de prohibida la entrada"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Símbolo de fumar"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Símbolo de no fumar"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Símbolo de tirar la basura en su sitio"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Símbolo de no tirar basura"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Símbolo de agua potable"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Símbolo de agua no potable"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Prohibido montar en bicicleta"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista de montaña"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Peatón"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Prohibido el paso de peatones"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Niños cruzando"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Símbolo de aseos para hombres"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Símbolo de aseos para mujeres"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Aseos"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Símbolo de bebé"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Retrete"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Servicios"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Ducha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Baño"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bañera"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Control de pasaportes"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Aduanas"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Recogida de equipaje"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Consigna"</string>
+</resources>
diff --git a/java/res/values-es/strings-talkback-descriptions.xml b/java/res/values-es/strings-talkback-descriptions.xml
index ef95901..d80d25c 100644
--- a/java/res/values-es/strings-talkback-descriptions.xml
+++ b/java/res/values-es/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"No se ha introducido texto"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> a <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corregirá la palabra automáticamente"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"No hay sugerencias"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Carácter desconocido"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Mayús"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Más símbolos"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maýuscula, punto superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconocido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconocido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara aburrida"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara avergonzada"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara con gafas de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara sorprendida"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara dando un beso"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara con el ceño fruncido"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Caracteres alternativos disponibles"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Los caracteres alternativos se descartarán"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sugerencias alternativas disponibles"</string>
diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml
index a385f9e..dceecc7 100644
--- a/java/res/values-es/strings.xml
+++ b/java/res/values-es/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar al pulsar tecla"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sonar al pulsar tecla"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Ampliar al pulsar tecla"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferencias"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Cuentas y privacidad"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aspecto y diseño"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escritura gestual"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Corrección ortográfica"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Opciones avanzadas"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Habilitar teclado dividido"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronización Teclado de Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sincronización activada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronizar el diccionario personal en diferentes dispositivos"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizar"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Eliminar datos de la nube"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Elimina tus datos sincronizados de Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Los datos sincronizados se eliminarán de la nube. ¿Continuar?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Eliminar"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancelar"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"El diccionario personal se sincroniza con los servidores de Google, donde se crea una copia de seguridad. Se puede recopilar información estadística sobre frecuencia de palabras para mejorar nuestros productos. Toda la información se recopila y se utiliza siguiendo las disposiciones de la "<a href="https://www.google.com/policies/privacy">"Política de privacidad de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Añade una cuenta de Google al dispositivo para activar la función"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de introducción"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla para cambiar de idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostrar cuando haya varios idiomas de introducción habilitados"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador deslizante"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar pista visual al deslizar desde la tecla Mayús o la tecla de símbolos"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso para ampliar tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sin retraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Diccionario principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Sugerencias de correcciones"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Muestra las palabras sugeridas mientras se escribe."</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar siempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar en modo vertical"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar siempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palabras ofensivas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"No sugerir palabras potencialmente ofensivas"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autocorrección"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada de voz"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Sin métodos de introducción de voz habilitados. Comprueba ajustes de Idioma e introducción de texto."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Danos tu opinión"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomas de introducción"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ayuda y sugerencias"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema de teclado"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Cambiar de cuenta"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Ninguna cuenta seleccionada"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> actualmente en uso"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Aceptar"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancelar"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Cerrar sesión"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecciona la cuenta que quieras usar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglés (EE.UU.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EE.UU.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbio (latino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés (EE.UU.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español (EE.UU.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latinoamérica)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema de teclado"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
     <string name="add_style" msgid="6163126614514489951">"Añadir estilo"</string>
     <string name="add" msgid="8299699805688017798">"Añadir"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Habilitar"</string>
     <string name="not_now" msgid="6172462888202790482">"Ahora no"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ya existe el estilo de entrada <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso de pulsación prolongada"</string>
-    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duración vibración al pulsar"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duración de vibración al pulsar"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volumen sonido al pulsar tecla"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leer archivo de diccionario externo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"No hay archivos de diccionario en la carpeta de descargas."</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecciona un archivo de diccionario para instalar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"¿Seguro que quieres instalar este archivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Se ha producido un error"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso de pulsación prolongada"</string>
     <string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Te damos la bienvenida a <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"con escritura gestual"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Ahora puedes escribir en todas tus aplicaciones favoritas con <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configura otros idiomas"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Listo"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostrar icono de aplicación"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostrar icono de aplicación en menú de aplicaciones"</string>
     <string name="app_name" msgid="6320102637491234792">"Proveedor del diccionario"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Proveedor del diccionario"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Servicio de diccionario"</string>
@@ -173,7 +170,7 @@
     <string name="no_dictionaries_available" msgid="8039920716566132611">"No hay diccionarios"</string>
     <string name="check_for_updates_now" msgid="8087688440916388581">"Actualizar"</string>
     <string name="last_update" msgid="730467549913588780">"Última actualización"</string>
-    <string name="message_updating" msgid="4457761393932375219">"Buscando actualizaciones"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Buscando actualizaciones..."</string>
     <string name="message_loading" msgid="5638680861387748936">"Cargando…"</string>
     <string name="main_dict_description" msgid="3072821352793492143">"Diccionario principal"</string>
     <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
@@ -198,7 +195,7 @@
     <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Acceso directo:"</string>
     <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Idioma:"</string>
     <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"Escribe una palabra"</string>
-    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Acceso directo opcional"</string>
+    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Introducir"</string>
     <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"Editar palabra"</string>
     <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Editar"</string>
     <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"Eliminar"</string>
diff --git a/java/res/values-et-rEE/strings-emoji-descriptions.xml b/java/res/values-et-rEE/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..499a04d
--- /dev/null
+++ b/java/res/values-et-rEE/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Autoriõiguse märk"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registreeritud märk"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Kahekordne hüüumärk"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Hüüu- ja küsimärk"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Kaubamärgisümbol"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Teabeallikas"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Vasak-paremnool"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Üles-allanool"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Loodenool"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Kirdenool"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Kagunool"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Edelanool"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Konksuga vasaknool"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Konksuga paremnool"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Käekell"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Liivakell"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Must paremale suunatud topeltkolmnurk"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Must vasakule suunatud topeltkolmnurk"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Must ülessuunatud topeltkolmnurk"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Must allasuunatud topeltkolmnurk"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Äratuskell"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Voolava liivaga liivakell"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Ringis ladina suurtäht M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Väike must ruut"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Väike valge ruut"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Must paremale suunatud kolmnurk"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Must vasakule suunatud kolmnurk"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Valge keskmine ruut"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Must keskmine ruut"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Valge keskmisest väiksem ruut"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Must keskmisest väiksem ruut"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Must päike kiirtega"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Pilv"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Must telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Linnukesega märkeruut"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Vihmapiiskadega vihmavari"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Kuum jook"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Valge ülessuunatud nimetissõrm"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Valge naerunägu"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Jäär"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Sõnn"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Kaksikud"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Vähk"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lõvi"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Neitsi"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Kaalud"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Ambur"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Kaljukits"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Veevalaja"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Kalad"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Must poti"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Must risti"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Must ärtu"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Must ruutu"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Kuumaveeallikad"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Must universaalne taaskasutussümbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Ratastoolisümbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ankur"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Hoiatusmärk"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Kõrgepingemärk"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Keskmine valge ring"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Keskmine must ring"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Jalgpall"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Pesapall"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Lumememm ilma lumeta"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Päike pilve taga"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Maokandja"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Sissepääsu pole"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kirik"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Purskkaev"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Lipp augus"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Purjekas"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Telk"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Kütusepump"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Mustad käärid"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Valge paks linnukesemärk"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Lennuk"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Ümbrik"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Tõstetud rusikas"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Tõstetud käsi"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Võidukäsi"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Pliiats"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Must sulg"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Must linnukesemärk"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Paks korrutusmärk x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Sädemed"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Kaheksaotsaline tärn"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Kaheksaotsaline must tärn"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Lumehelves"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Säde"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Rist"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Eitav rist ruudus"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Must ornament-küsimärk"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Valge ornament-küsimärk"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Valge ornament-hüüumärk"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Paks hüüumärk"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Paks must süda"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Raske plussmärk"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Paks miinusmärk"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Paks jagamismärk"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Must paremnool"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Aas"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Topeltaas"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Paremale suunatud, seejärel üles kaarduv nool"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Paremale suunatud, seejärel alla kaarduv nool"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Must vasaknool"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Must ülesnool"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Must allanool"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Must suur ruut"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Valge suur ruut"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Valge keskmine tärn"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Paks suur ring"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Lainetav kriips"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Osamuutmismärk"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ringis idiogramm „õnnitlus”"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ringis idiogramm „saladus”"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjongi klots Punane draakon"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Mängukaart Must jokker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Veretüüp A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Veretüüp B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Veretüüp O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkla"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Veretüüp AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Ruudus „CL”"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Ruudus „cool”"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Ruudus „free”"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Ruudus „ID”"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Ruudus „new”"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Ruudus „NG”"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Ruudus „OK”"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Ruudus „SOS”"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Ruudus „up” koos hüüumärgiga"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Ruudus „vs”"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Ruudus katakana „siin”"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Ruudus katakana „teenus”"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ruudus ideogramm „tasuta”"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ruudus ideogramm „reserveeritud iste”"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ruudus ideogramm „keeld”"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ruudus ideogramm „vabad kohad”"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ruudus ideogramm „heakskiit”"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ruudus ideogramm „täiesti täis”"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ruudus ideogramm „tasuline”"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ruudus ideogramm „igakuine”"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ruudus ideogramm „avaldus”"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ruudus ideogramm „allahindlus”"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ruudus ideogramm „tööaeg”"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ringis ideogramm „eelis”"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ringis ideogramm „tunnustus”"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Tsüklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Udune"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Kokkupandud vihmavari"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Tähine öö"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Päikesetõus mägede kohal"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Päikesetõus"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Linnavaade videvikus"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Päikeseloojang hoonete kohal"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Vikerkaar"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Öine sild"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Veelaine"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkaan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Linnutee"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Maakera: Euroopa ja Aafrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Maakera: Ameerikad"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Maakera: Aasia ja Austraalia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Maakera meridiaanidega"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Noorkuu sümbol"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Kasvava poolkuu sümbol"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Poolkuu sümbol (esimene veerand)"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Kasvava kuu sümbol (kolmas veerand)"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Täiskuu sümbol"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Kahaneva kuu sümbol (kolmas veerand)"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Poolkuu sümbol (viimane veerand)"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Vanakuu sümbol"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Poolkuu"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Näoga noorkuu"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Näoga poolkuu (esimene veerand)"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Näoga vanakuu"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Näoga täiskuu"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Näoga päike"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Helendav täht"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Langev täht"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastan"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Võrse"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Igihaljas puu"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Lehtpuu"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmipuu"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulp"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kirsiõis"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Roos"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisk"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Päevalill"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Õis"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Maisitõlvik"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Riisitõlvik"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Taim"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Neljaleheline ristik"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Vahtraleht"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Mahalangenud leht"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Tuules lendlev leht"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Seen"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Baklažaan"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Viinamarjad"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Arbuus"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandariin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Sidrun"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banaan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananass"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Punane õun"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Roheline õun"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pirn"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Virsik"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kirsid"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Maasikas"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pitsalõik"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Lihaga kont"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Kanakoib"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Riisiküpsis"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Riisipall"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Keedetud riis"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Karri ja riis"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Aurav pott"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagetid"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Leib"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Friikartulid"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Röstitud bataat"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Praetud krevetid"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Spiraalne kalapirukas"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Pehme jäätis"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Kraabitud jää"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Jäätis"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Sõõrik"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Küpsis"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Šokolaadibatoon"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Kompvek"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Pulgakomm"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Puding"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Meepott"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Tordilõik"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento-karp"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Toidupott"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Küpsetamine"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Kahvel ja nuga"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Kõrvata teetass"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakepudel ja -pits"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Veiniklaas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kokteiliklaas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Troopikajook"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Õllekapp"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Kokkulöödavad õllekapad"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Lutipudel"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Lipsuke"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Pakitud kingitus"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Sünnipäevatort"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Kõrvitsalatern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Jõulupuu"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Jõuluvana"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Ilutulestik"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Säraküünal"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Õhupall"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfetid"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfetikuul"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabatapuu"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Ristatud lipud"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Männikaunistus"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Jaapani nukud"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Tuulelipp"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Tuulekell"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Kuuvaatamise pidu"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Ranits"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Akadeemiline müts"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karussellihobune"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Vaateratas"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Ameerika mäed"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Õng ja kala"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmikaamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Kõrvaklapid"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Värvipalett"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Kõvakübar"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Tsirkusetelk"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Pilet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Võtteklapp"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Näitekunst"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videomäng"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Otsetabamus"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Mänguautomaat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Piljard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Täring"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Keegel"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Lillekaardid"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Noot"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Noodid"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Kitarr"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klahvid"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Viiul"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Noodijooned"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Jooksusärk koos särbiga"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisereket ja -pall"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Suusk ja suusasaabas"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Korvpall ja rõngas"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Ruudulipp"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Lumelaudur"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Jooksja"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfaja"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Karikas"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Kappav hobune"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Ameerika jalgpall"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Ujuja"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Maja"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Maja koos aiaga"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kontorihoone"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Jaapani postkontor"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Euroopa postkontor"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Haigla"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Pank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Pangaautomaat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotell"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Armuhotell"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Esmatarbekaupade kauplus"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Kool"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Kaubamaja"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Tehas"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Baarilatern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Jaapani loss"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Euroopa loss"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rott"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Hiir"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Härg"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vesipühvel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Lehm"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Küülik"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kass"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Draakon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodill"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Vaal"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Tigu"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Madu"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Hobune"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Jäär"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Kits"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Lammas"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Ahv"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Kukk"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kana"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Koer"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Siga"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Kult"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elevant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Kaheksajalg"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiraalne teokarp"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Putukas"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Sipelgas"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Mesilane"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Lepatriinu"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Kala"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Troopikakala"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Kerakala"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Kilpkonn"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kooruv tibu"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Tibu"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Tibu küljelt"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Lind"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingviin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koaala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Puudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Üksküürkaamel"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kaksküürkaamel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfiin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Hiire nägu"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Lehma nägu"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tiigri nägu"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Küüliku nägu"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kassi nägu"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Draakoni nägu"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Vettpurskav vaal"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Hobuse nägu"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Ahvi nägu"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Koera nägu"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Sea nägu"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Konna nägu"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamstri nägu"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Hundi nägu"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Karu nägu"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda nägu"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Seanina"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Käpajäljed"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Silmad"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Kõrv"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nina"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Suu"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Keel"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Valge ülessuunatud nimetissõrm"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Valge allasuunatud nimetisõrm"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Valge vasakule suunatud nimetisõrm"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Valge paremale suunatud nimetisõrm"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Rusikas käemärk"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Lehvitav käemärk"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Käemärk OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Ülessuunatud pöial"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Allasuunatud pöial"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Käeplaksutus"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Avatud käed"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Kroon"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Kübar"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Prillid"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Lips"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-särk"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Teksad"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Kleit"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikiinid"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Naisterõivad"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Mündikott"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Käekott"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Kott"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Meesteking"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Spordijalats"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Kõrge kontsaga king"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Naistesandaal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Naistesaabas"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Jalajäljed"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Büsti siluett"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Büstisiluetid"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Poiss"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Tüdruk"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mees"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Naine"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Perekond"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Mees ja naine käsikäes"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Kaks meest käsikäes"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Kaks naist käsikäes"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Politseinik"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Jänesekõrvadega naine"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Looriga pruut"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Blond inimene"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Murumütsiga mees"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Turbaniga mees"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Eakas mees"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Eakas naine"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Beebi"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Ehitustööline"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Printsess"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Jaapani ogre"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Jaapani goblin"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Vaim"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Inglilaps"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Tulnukas"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Tulnukkoletis"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Paharet"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Pealuu"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Infotöötaja"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Valvur"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Tantsija"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Huulepulk"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Küünelakk"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Näomassaaž"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Soeng"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Juuksurimärk"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Süstal"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Tablett"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Suudluse märk"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Armastuskiri"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Sõrmus"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Kalliskivi"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Suudlus"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Lillekimp"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Paar koos südamega"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Pulm"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Tuksuv süda"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Purunenud süda"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Kaks südant"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Sätendav süda"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Kasvav süda"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Noolega süda"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Sinine süda"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Roheline süda"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Kollane süda"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lilla süda"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Paelaga süda"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Pöörlevad südamed"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Südamega kaunistus"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Täpiga teemandikuju"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektripirn"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Vihasümbol"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Pomm"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Magamissümbol"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Kokkupõrkesümbol"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Pritsiva higi sümbol"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Piisk"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Sööstmissümbol"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kakahunnik"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Painutatud biitseps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Pöörlemissümbol"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Jutumull"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Mõttemull"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Valge lill"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"100 punkti sümbol"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Rahakott"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valuutavahetus"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dollarimärk"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Krediitkaart"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Jeenitähisega rahatäht"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Dollaritähisega rahatäht"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Eurotähisega rahatäht"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Naelatähisega rahatäht"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Tiibadega raha"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Diagramm tõusva trendi ja jeenitähisega"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Iste"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personaalarvuti"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Kohver"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Miniketas"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Flopiketas"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optiline ketas"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Failikaust"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Avatud failikaust"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Kooldus leht"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Esiküljega leht"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Rebitav kalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kaardiregister"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Tõusva trendiga diagramm"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Langeva trendiga diagramm"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Tulpdiagramm"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Kirjutusalus"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Knopka"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Ümara peaga knopka"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Kirjaklamber"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Sirge joonlaud"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Kolmnurkjoonlaud"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Järjehoidjakaardid"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Pearaamat"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Märkmik"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Dekoratiivse kaanega märkmik"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Suletud raamat"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Avatud raamat"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Roheline raamat"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Sinine raamat"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranž raamat"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Raamatud"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Nimesilt"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Paberirull"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonitoru"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Piipar"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faksimasin"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelliitantenn"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Avalik valjuhääldi"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ruupor"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Väljundkast"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Sisendkast"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakk"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Meilisümbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Saabuv ümbrik"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Ümbrik, mille kohal on allanool"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Suletud postkast koos langetatud lipuga"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Suletud postkast koos tõstetud lipuga"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Avatud postkast koos tõstetud lipuga"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Avatud postkast koos langetatud lipuga"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postkast"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Postipasun"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Ajaleht"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiiiltelefon, millest vasakul on paremnool"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Värinarežiim"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiiltelefon väljas"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobiiltelefonid pole lubatud"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antennipostid"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kaamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokaamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisioon"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Raadio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokassett"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Keerdus paremnooled"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Päripäeva ringlevad parem- ja vasaknool"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Päripäeva ringlevad parem- ja vasaknool, mille peal on ringis number üks"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Päripäeva ringlevad üles- ja allanool"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Vastupäeva ringlevad üles- ja allanool"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Madal heledus"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Kõrge heledus"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Keelamiskriipsuga kõlar"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Kõlar"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Ühe helilainega kõlar"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Kolme helilainega kõlar"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Patarei"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektripistik"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Vasakule suunatud suurendusklaas"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Paremale suunatud suurendusklaas"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lukk koos kirjutussulega"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Suletud lukk koos võtmega"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Võti"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lukk"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Avatud lukk"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Kell"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Keelamiskriipsuga kell"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Järjehoidja"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Ahelasümbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Raadionupp"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Tagasinupp vasaknoolega"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"„End”, mille kohal on vasaknool"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"„On” koos hüüumärgiga, mille kohal on vasak-paremnool."</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"„Soon”, mille kohal on paremnool"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"„Top”, mille kohal on ülesnool"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Sümbol „alla 18 keelatud”"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Klahvimärk 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Ladina suurtähtede sisestussümbol"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Ladina väiketähtede sisestussümbol"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Numbrite sisestussümbol"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Sümbolite sisestussümbol"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Ladina tähtede sisestussümbol"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Tulekahju"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elektritõrvik"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Mutrivõti"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Haamer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Mutter ja polt"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Püstol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskoop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskoop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristallkuul"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Kuueotsaline tärn keskpunktiga"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Jaapani sümbol algaja kohta"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Kolmhargiembleem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Must ruudukujuline nupp"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Valge ruudukujuline nupp"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Suur punane ring"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Suur sinine ring"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Suur oranž romb"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Suur sinine romb"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Väike oranž romb"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Väike sinine romb"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Ülessuunatud punane kolmnurk"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Allasuunatud punane kolmnurk"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Ülessuunatud väike punane kolmnurk"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Allasuunatud väike punane kolmnurk"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Kella numbrilaud: kell üks"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Kella numbrilaud: kell kaks"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Kella numbrilaud: kell kolm"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Kella numbrilaud: kell neli"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Kella numbrilaud: kell viis"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Kella numbrilaud: kell kuus"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Kella numbrilaud: kell seitse"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Kella numbrilaud: kell kaheksa"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Kella numbrilaud: kell üheksa"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Kella numbrilaud: kell kümme"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Kella numbrilaud: kell ükteist"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Kella numbrilaud: kell kaksteist"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Kella numbrilaud: kell pool kaks"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Kella numbrilaud: kell pool kolm"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Kella numbrilaud: kell pool neli"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Kella numbrilaud: kell pool viis"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Kella numbrilaud: kell pool kuus"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Kella numbrilaud: kell pool seitse"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Kella numbrilaud: kell pool kaheksa"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Kella numbrilaud: kell pool üheksa"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Kella numbrilaud: kell pool kümme"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Kella numbrilaud: kell pool üksteist"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Kella numbrilaud: kell pool kaksteist"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Kella numbrilaud: kell pool üks"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji mägi"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo torn"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Vabadussammas"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Jaapani siluett"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Naeratav nägu"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Naeratav nägu naerusilmadega"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Rõõmupisarates nägu"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Laia naeratusega nägu"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Laia naeratuse ja rõõmsate silmadega nägu"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Laia naeratuse ja külma higiga nägu"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Laia naeratuse ja kinnipigistatud silmadega nägu"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Naerunägu koos aupaistega"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Naerunägu koos sarvedega"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Silmapilgutav nägu"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Rõõmsate silmadega naerunägu"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Maitsvat toitu nautiv nägu"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lõõgastunud nägu"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Südamekujuliste silmadega nägu"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Päikeseprillidega nägu"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Irvitav nägu"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutraalne nägu"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Ilmetu nägu"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Halvatujuline nägu"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Külma higiga nägu"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Mõtlik nägu"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Hämmingus nägu"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Segaduses nägu"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Suudlev nägu"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Õhusuudlust saatev nägu"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Naerusilmadega suudlev nägu"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Suletud silmadega suudlev nägu"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Väljaaetud keelega nägu"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Väljaaetud keelega silmapilgutav nägu"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Väljaaetud keele ja kinnipigistatud silmadega nägu"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Pettunud nägu"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Murelik nägu"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Vihane nägu"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Mossitav nägu"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Nuttev nägu"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Krimpsutav nägu"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Võidukas nägu"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Pettunud, kuid rahulik nägu"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Kulmukortsutav nägu lahtise suuga"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Ahastav nägu"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Hirmunud nägu"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Tüdinenud nägu"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Unine nägu"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Väsinud nägu"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimassitav nägu"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Valjult nuttev nägu"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Lahtise suuga nägu"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Vaikseks jäänud nägu"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Lahtise suu ja külma higiga nägu"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Hirmust karjuv nägu"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Üllatunud nägu"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Punastav nägu"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Magav nägu"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Uimane nägu"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Ilma suuta nägu"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Arstimaskiga nägu"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Naeratav kassinägu naerusilmadega"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Rõõmupisaratega kassinägu"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Lahtise suuga naeratav kassinägu"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Südamekujuliste silmadega naeratav kassinägu"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Virila naeratusega kassinägu"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Suletud silmadega naeratav kassinägu"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Mossitav kassinägu"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Nuttev kassinägu"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Tüdinud kassinägu"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Eitava žestiga nägu"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OK-žestiga nägu"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Sügavalt kummardav inimene"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Silmipeitev ahv"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Kõrvupeitev ahv"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Suudpeitev ahv"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Üht kätt tõstev õnnelik inimene"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Mõlemat kätt hõiskeks tõstev inimene"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Kulmukortsutav inimene"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Mossitava näoga inimene"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Kokkupandud kätega inimene"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rakett"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Auruvedur"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagun"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Kiirrong"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Kuuljas kiirrong"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Rong"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metroo"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Kergraudtee"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Jaam"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramm"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Trammivagun"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Buss"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Saabuv buss"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trollibuss"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bussipeatus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Pisibuss"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Kiirabiauto"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Tuletõrjeauto"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Politseiauto"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Saabuv politseiauto"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Takso"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Saabuv takso"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Auto"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Saabuv auto"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Haagissuvila"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Kaubik"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Liigendveok"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Üherööpmeline raudtee"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Mägiraudtee"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Rippraudtee"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Mägiraudtee"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Õhutrammitee"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Laev"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Aerupaat"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Kiirpaat"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horisontaalne valgusfoor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikaalne valgusfoor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Ehitusmärgid"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Politseiauto pöörlev vilkur"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Kolmnurkne lipp postil"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Uks"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Sissepääs keelatud"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Suitsetamiskoha sümbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Suitsetamise keelamise sümbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Prügipaneku koha sümbol"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Prügi mahapanek keelatud"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Joogivee sümbol"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Mittejoogivee sümbol"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Jalgratas"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Jalgrattad pole lubatud"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Jalgrattur"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mägijalgrattur"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Jalakäija"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Jalakäijad pole lubatud"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Teed ületavad lapsed"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Meestesümbol"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Naistesümbol"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Puhkeruum"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Beebisümbol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Tualett"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dušš"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Vannituba"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Vann"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Passikontroll"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Toll"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Pagasi andmine"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Leitud esemed"</string>
+</resources>
diff --git a/java/res/values-et-rEE/strings-talkback-descriptions.xml b/java/res/values-et-rEE/strings-talkback-descriptions.xml
index b47df1b..ad57715 100644
--- a/java/res/values-et-rEE/strings-talkback-descriptions.xml
+++ b/java/res/values-et-rEE/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Teksti ei ole sisestatud"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> parandab sõna <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> järgmiselt: <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> teeb automaatse paranduse"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Soovitusi pole"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Tundmatu tähemärk"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Tõstuklahv"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Rohkem sümboleid"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Suurtäht I, ülapunkt"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Tundmatu sümbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Tundmatu emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Igavlev nägu"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Piinlikkust tundev nägu"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Päikseprillidega nägu"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Üllatunud nägu"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Suudlev nägu"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Kulmu kortsutav nägu"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatiivsed tähemärgid on saadaval"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatiivsed tähemärgid eemaldatakse"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatiivsed soovitused on saadaval"</string>
diff --git a/java/res/values-et-rEE/strings.xml b/java/res/values-et-rEE/strings.xml
index d57126d..15620af 100644
--- a/java/res/values-et-rEE/strings.xml
+++ b/java/res/values-et-rEE/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibreeri klahvivajutusel"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Heli klahvivajutusel"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Klahvivajutusel kuva hüpik"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Eelistused"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Kontod ja privaatsus"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Välimus ja paigutused"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Joonistusega sisestamine"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Tekstiparandus"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Täpsem"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Teema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Luba kaheks jaotatud klaviatuur"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sünkrooni Google\'i klaviatuur"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sünkroonimine on sisse lülitatud"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Isikliku kataloogi sünkroonimine kõigis seadmetes"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sünkrooni kohe"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Pilveandmete kustutamine"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Kustutab sünkroonitud andmed Google\'ist"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Teie sünkroonitud andmed kustutatakse pilvest. Kas olete kindel?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Kustuta"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Tühista"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Teie isiklik sõnastik sünkroonitakse ja varundatakse Google\'i serveritesse. Meie toodete parandamiseks võidakse koguda sõna esinemissageduse statistikat. Kogu teabe kogumine ja kasutamine toimub "<a href="https://www.google.com/policies/privacy">"Google\'i privaatsuseeskirjade"</a>" järgi."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Lisage selle funktsiooni lubamiseks seadmesse Google\'i konto"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Vaheta sisestusmeetodit"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Keelevahetuse võti hõlmab ka muid sisestusmeetodeid"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Keelevahetuse nupp"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Kuva, kui lubatud on mitu sisendkeelt"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Kuva lohistamisnäidik"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Tõstu- või sümboliklahvidelt lohistades anna visuaalselt märku"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Hüpiku loobumisviivitus"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Viivituseta"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Vaikeseade"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Peamine sõnaraamat"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Kuva parandussoovitusi"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Kuva sisestamise ajal sõnasoovitusi"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Kuva alati"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Kuva vertikaalrežiimis"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Peida alati"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokeeri solvavad sõnad"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ära soovita potentsiaals. solvavaid sõnu"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automaatparandus"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Häälesisendi klahv"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ühtegi häälsisendmeetodit pole lubatud. Kontrollige keele- ja sisendiseadeid."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Saatke tagasisidet"</string>
-    <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Keeled"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Abi ja tagasiside"</string>
+    <string name="select_language" msgid="5709487854987078367">"Keeled"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Salvestamiseks puudutage uuesti"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Salvestamiseks puudutage siin"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatuuri teema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Konto vahetamine"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Ühtegi kontot pole valitud"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Praegu kasutatakse e-posti aadressi <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Tühista"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Logi välja"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Kasutatava konto valimine"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglise (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglise (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"hispaania (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi-inglise"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbia (ladina)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglise (Ühendk.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglise (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Hispaania (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-inglise (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditsiooniline)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirillitsa)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ladina)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktne)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Keel puudub (tähestik)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Tähestik (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Tähestik (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Tähestik (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Tähestik (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emotikon"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Klaviatuuriteema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Kohandage sisendlaadid"</string>
     <string name="add_style" msgid="6163126614514489951">"Lisage laad"</string>
     <string name="add" msgid="8299699805688017798">"Lisa"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Luba"</string>
     <string name="not_now" msgid="6172462888202790482">"Mitte kohe"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama sisendstiil on juba olemas: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Pika klahvivajutuse viide"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Klahvivajutuse vibreerimise kestus"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Klahvivajutuse helitugevus"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Välise sõnastikufaili lugemine"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Kaustas Allalaadimised pole ühtegi sõnastikufaili"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Installitava sõnastikufaili valimine"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Kas soovite tõesti installida faili <xliff:g id="LANGUAGE_NAME">%s</xliff:g> keele jaoks?"</string>
-    <string name="error" msgid="8940763624668513648">"Ilmnes viga"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Pika klahvivajutuse viide"</string>
     <string name="button_default" msgid="3988017840431881491">"Vaikeväärtus"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Tere tulemast rakendusse <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"joonistusega sisestamisega"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nüüd saate rakendusega <xliff:g id="APPLICATION_NAME">%s</xliff:g> sisestada kõikides oma lemmikrakendustes."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Seadista lisakeeled"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Lõpetatud"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Kuva rakenduse ikoon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Rakenduse ikooni kuvamine käivitajas"</string>
     <string name="app_name" msgid="6320102637491234792">"Sõnastikupakkuja"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Sõnastikupakkuja"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Sõnastikuteenus"</string>
diff --git a/java/res/values-eu-rES/strings-emoji-descriptions.xml b/java/res/values-eu-rES/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..49cf216
--- /dev/null
+++ b/java/res/values-eu-rES/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyright-ikurra"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Erregistratze-ikurra"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Bi harridura-ikur"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Harridura-ikurra eta galdera-ikurra"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Marka erregistratuaren ikurra"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informazioaren ikurra"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Ezkerrera eta eskuinera gezia"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Gora eta behera gezia"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Ipar-mendebaldera gezia"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Ipar-ekialdera gezia"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Hego-ekialdera gezia"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Hego-mendebaldera gezia"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Ezkerrerantz gezia kakoarekin"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Eskuinerantz gezia kakoarekin"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Eskumuturreko erlojua"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Harea-erlojua"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Eskuinerantz begira dauden bi triangelu beltz"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Ezkerrerantz begira dauden bi triangelu beltz"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Gorantz begira dauden bi triangelu beltz"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Beherantz begira dauden bi triangelu beltz"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Iratzargailua"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Harea-erlojua eta harea erortzen"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"M letra larri latindarra zirkulu batean"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Karratu beltz txikia"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Karratu zuri txikia"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triangelu beltza gorantz begira"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triangelu beltza ezkerrerantz begira"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Karratu zuri ertaina"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Karratu beltz ertaina"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Karratu zuri txiki-ertaina"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Karratu beltz txiki-ertaina"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Eguzki beltza izpiekin"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Hodeia"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telefono beltza"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Bozketa-koadroa hauta-markarekin"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Euritakoa euri-tantekin"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Edari beroa"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Hatz erakusle zuria altxatuta"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Aurpegi irribarretsu zuria"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aharia"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Zezena"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Bikiak"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Karramarroa"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lehoia"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Birjina"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Balantza"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Eskorpioia"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Arkularia"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Ureko ahuntza"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Akuario"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Arrainak"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Pika beltza kolorea"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Hirusta beltza kolorea"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Bihotz beltza kolorea"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Diamante beltza kolorea"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Ur termalak"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Birziklatzearen ikur beltz unibertsala"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Gurpildun aulkiaren ikurra"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Aingura"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Abisuaren ikurra"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Tentsio handiaren ikurra"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Zirkulu zuri ertaina"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Zirkulu beltz ertaina"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futboleko baloia"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beisboleko baloia"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Elurrezko panpina elurrik gabe"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Eguzkia hodeiaren atzean"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Ez sartu"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Eliza"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Iturria"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandera zuloan"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Bela"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Kanpin-denda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Erregai-bonba"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Artazi beltzak"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Hauta-marka lodia atzealde zuriarekin"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Hegazkina"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Gutun-azala"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Ukabila gora"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Eskua gora"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Garaipen-keinua eskuarekin"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Arkatza"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Luma-mutur beltza"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Hauta-marka lodia"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Biderketa X lodia"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Distirak"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Zortzi puntako izartxoa"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Zortzi puntako izar beltza"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Elur-maluta"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Distira"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Gurutzea"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Gurutzea betegarridun karratuan"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Galdera-ikur beltz apaingarria"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Galdera-ikur zuri apaingarria"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Harridura-ikur zuri apaingarria"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Harridura-ikur lodiaren ikurra"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Bihotz lodi beltza"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Gehi ikur lodia"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Ken ikur lodia"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Zatiketa ikur lodia"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Gezi beltza eskuinerantz"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Kiribila"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Kiribil bikoitza"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Gezia eskuinerantz begira eta gero gorantz biratuta"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Gezia eskuinerantz begira eta gero beherantz biratuta"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Gezi beltza ezkerrerantz"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Gezi beltza gorantz"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Gezi beltza beherantz"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Karratu beltz handia"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Karratu zuri handia"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Izar zuri ertaina"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Zirkulu lodi handia"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Marratxo uhinduna"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Parte-alternantziaren marka"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"\"Zorionak\" esan nahi duen hitza ideograma zirkulu batean"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"\"Sekretua\" esan nahi duen ideograma zirkulu batean"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong lauza: dragoi gorria"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Joker beltzaren karta"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A motako odola"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B motako odola"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"0 motako odola"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Aparkalekua"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB motako odola"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"\"CL\" hizkiak karratu batean"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"\"Cool\" hitza karratu batean"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"\"Free\" hitza karratu batean"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"\"ID\" hizkiak karratu batean"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"\"New\" hitza karratu batean"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"\"NG\" hizkiak karratu batean"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"\"OK\" hitza karratu batean"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"\"SOS\" hizkiak karratu batean"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"\"Up\" hitza harridura-markarekin karratu batean"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"\"vs\" hizkiak karratu batean"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana silabarioko \"hemen\" esan nahi duen hitza karratu batean"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Katakana silabarioko \"zerbitzua\" esan nahi duen hitza karratu batean"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"\"Doan\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"\"Tokia erreserbatuta\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"\"Debekatuta\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"\"Toki librea\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"\"Onarpena\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"\"Guztiz beteta\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"\"Ordainduta\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"\"Hilero\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"\"Aplikazioa\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"\"Deskontua\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"\"Negozioetan\" esan nahi duen ideograma karratu batean"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"\"Abantaila\" esan nahi duen ideograma zirkulu batean"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"\"Onartu\" esan nahi duen ideograma zirkulu batean"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Zikloia"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Lainotsua"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Euritako itxia"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Gau izartsua"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Egunsentia mendi artean"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Egunsentia"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Hiria ilunabarrean"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Ilunsentia eraikinen artean"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Ortzadarra"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Zubia gauean"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Itsas olatua"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Sumendia"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Esne Bidea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Mundua - Europa eta Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Mundua - Amerikak"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Mundua - Asia eta Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Mundua meridianoekin"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Ilberriaren ikurra"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Ilgora hasi berriaren ikurra"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Ilgoraren ikurra"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Ia ilbetearen ikurra"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Ilbetearen ikurra"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Ilbehera hasi berriaren ikurra"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Ilbeheraren ikurra"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Ia ilberriaren ikurra"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Ilgora"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Ilberria aurpegiarekin"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Ilgora aurpegiarekin"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Ilbehera aurpegiarekin"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Ilbetea aurpegiarekin"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Eguzkia aurpegiarekin"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Izar distiratsua"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Izar iheskorra"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Gaztaina"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Kimua"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Hosto iraunkorreko zuhaitza"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Hosto erorkorreko zuhaitza"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmondoa"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktusa"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipa"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Gereziondo-lorea"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Arrosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskoa"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Eguzki-lorea"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Lorea"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Arto-burua"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Arroz-burua"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Usain-belarra"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Lau hostoko hirusta"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Astigar-hostoa"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Eroritako hostoa"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Hostoa haizearekin hegaka"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Perretxikoa"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomatea"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Alberjinia"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Mahatsak"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Meloia"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Angurria"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Klementina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limoia"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Anana"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Sagar gorria"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Sagar berdea"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Madaria"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Muxika"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Gereziak"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Marrubia"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hanburgesa"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizza zatia"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Haragia hezurrean"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Oilasko-izterra"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Arroz-gaileta"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Arroz-bola"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arroz egosia"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Currya eta arroza"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Bol beroa"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Espagetiak"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Ogia"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patata frijituak"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Batata egosia"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dangoa"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Odena"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushia"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Izkira frijitua"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Arrain-pastela zurrunbilo diseinuarekin"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Izozki txikia"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Izotz-edaria"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Izozkia"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donuta"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Gaileta"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Txokolate-tableta"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Gozokia"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Piruleta"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Flana"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Ezti-potea"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Frutazko tarta"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento kutxa"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Janariz betetako eltzea"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Sukaldaritza"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Sardexka eta labana"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Kikara kirtenik gabe"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake-botila eta kopa"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Ardo-kopa"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Koktel-kopa"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Edari tropikala"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Garagardo-pitxerra"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Garagardo-pitxerrak topa egiten"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberoia"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Xingola"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Oparia paperean bilduta"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Urtebetetze-pastela"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Halloween-eko kuia-lanpara"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Gabonetako zuhaitza"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Bizarzuri"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Su artifizialak"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Bengala"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Puxika"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfeti-kanoia"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfeti-eltzea"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata zuhaitza"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Banderak gurutzatuta"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Pinu apaingarria"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Panpina japoniarrak"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Karpa-serpentina"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Haize-ezkila"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Ilargia ikusteko zeremonia"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Eskolarako bizkar-zorroa"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Graduazioko kapela"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Zaldiko-maldikoa"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Noria"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Errusiar mendia"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Kanabera eta arraina"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofonoa"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Bideo-kamera profesionala"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Zinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Aurikularra"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Kapela luzea"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Zirku-karpa"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Sarrera"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klaketa"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Antzezpena"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Bideo-jokoa"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Itua"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Txanpon-makina"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billarra"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dadoa"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Boloak"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Lore-joko japoniarren kartak"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musika-nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Hainbat musika-nota"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofoia"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Musika-teklatua"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Tronpeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Biolina"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Pentagrama"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Korrika egiteko kamiseta, banda batekin"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tenis-erraketa eta -pilota"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Eskia eta eski-bota"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Saskibaloiko baloia eta saskia"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Koadrodun bandera"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboard-zalea"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Korrikalaria"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surflaria"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofeoa"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Zaldi-lasterketa"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Futbol amerikarra"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Errugbia"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Igerilaria"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Etxea"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Etxea lorategiarekin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Bulegoak"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Posta-bulego japoniarra"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Posta-bulego europarra"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Ospitalea"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bankua"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Kutxazain automatikoa"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotela"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Maitasun-hotela"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Orotarikoen denda"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Eskola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Saltoki handia"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrika"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya lanpara"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Gaztelu japoniarra"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Gaztelu europarra"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Arratoia"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Sagua"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Idia"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Asiar bufaloa"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Behia"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Lehoinabarra"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Untxia"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Katua"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragoia"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodiloa"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balea"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Barraskiloa"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Sugea"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Zaldia"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Aharia"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Ahuntza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ardia"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Tximinoa"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Oilarra"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Oiloa"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Txakurra"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Txerria"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Basurdea"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefantea"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Olagarroa"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Itsas kurkuilua"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Zomorroa"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Inurria"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Erlea"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Marigorringoa"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Arraina"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Arrain tropikala"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Puxika-arraina"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Dortoka"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Txita arrautzatik irteten"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Txita"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Txita aurrera begira"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Txoria"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pinguinoa"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poodle txakurra"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedarioa"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Gamelua"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Izurdea"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Sagu-aurpegia"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Behi-aurpegia"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigre-aurpegia"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Untxi-aurpegia"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Katu-aurpegia"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Dragoi-aurpegia"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Balea ura botatzen"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Zaldi-aurpegia"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Tximino-aurpegia"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Txakur-aurpegia"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Txerri-aurpegia"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Igel-aurpegia"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamster-aurpegia"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Otso-aurpegia"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Hartz-aurpegia"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda hartzaren aurpegia"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Txerri-muturra"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Atzapar-aztarnak"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Begiak"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Belarria"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Sudurra"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ahoa"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Mihia"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Esku zuri baten atzeko aldea, hatz erakuslearekin gorantz seinalatzen duela"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Esku zuri baten atzeko aldea, hatz erakuslearekin beherantz seinalatzen duela"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Esku zuri baten atzeko aldea, hatz erakuslearekin ezkerrerantz seinalatzen duela"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Esku zuri baten atzeko aldea, hatz erakuslearekin eskuinerantz seinalatzen duela"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Ukabila"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Eskua agurtzen"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Ados keinua eskuarekin"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Erpuruak gora"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Erpuruak behera"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Txaloak"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Eskuak zabalik"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Koroa"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Emakumezkoen txanoa"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Betaurrekoak"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Gorbata eta alkandora"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Kamiseta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Bakeroak"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Soinekoa"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimonoa"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikinia"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Emakumezkoen arropa"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Diru-zorroa"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Poltsa"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Eskuko poltsa"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Gizonezkoen zapata"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Kirol-zapatila"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Takoidun oinetakoa"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Emakumezkoen sandalia"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Emakumezkoen botak"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Oinatzak"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Bustoaren silueta"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Bustoen siluetak"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Mutila"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Neska"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Gizona"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Emakumea"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Gizona eta emakumea, eskutik helduta"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Bi gizon, eskutik helduta"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Bi emakume, eskutik helduta"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polizia"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Emakumea, untxi-belarriekin"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Emaztegaia, beloarekin"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Pertsona ilehoria"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Gizona, gua pi mao txanoarekin"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Gizona durbantearekin"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Adineko gizona"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Adineko emakumea"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Haurtxoa"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Eraikuntza-arloko langilea"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Printzesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogro japoniarra"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Iratxo japoniarra"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Mamua"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Aingerutxoa"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Estralurtarra"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Munstro estralurtarra"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Iratxoa"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Burezurra"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Informazio-guneko pertsona"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardia"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dantzaria"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Ezpainetakoa"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Azazkaletako esmaltea"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Aurpegiko masajea"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Ile-mozketa"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Bizarginen zutoina"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Xiringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilula"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Musu-marka"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Maitasun-gutuna"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Eraztuna"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Harribitxia"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Musua"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Lore sorta"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Bikotea eta bihotza"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Ezkontza"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Bihotz taupadak"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Bihotz apurtua"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Bi bihotz"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Bihotz distiratsua"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Hazten den bihotza"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Bihotza geziarekin"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Bihotz urdina"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Bihotz berdea"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Bihotz horia"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Bihotz morea"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Bihotza zintarekin"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Bihotzak biraka"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Bihotz-apaingarria"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamante-forma eta puntua erdian"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Bonbilla elektrikoa"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Haserre-ikurra"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bonba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Lotan ikurra"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Txoke-ikurra"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Izerdi-zipriztinen ikurra"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Tanta"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Korrikaldiaren ikurra"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kaka"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bizepsa markatuta"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Zorabioaren ikurra"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Hizketa-bunbuiloa"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Pentsamendu-bunbuiloa"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Lore zuria"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Ehun puntuen ikurra"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Diru-poltsa"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Moneta-trukaketa"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dolarraren ikur lodia"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditu-txartela"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billetea yenaren ikurrarekin"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billetea dolarraren ikurrarekin"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billetea euroaren ikurrarekin"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billetea libraren ikurrarekin"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Dirua hegoekin"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Goranzko joera duen diagrama eta yenaren ikurra"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Eserlekua"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Ordenagailu pertsonala"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Paper-zorroa"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidiskoa"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketea"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disko optikoa"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVDa"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Fitxategien karpeta"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Fitxategi-karpeta irekia"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Orria kizkurrarekin"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Orria ahoz gora"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Egutegia"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Orriak kentzeko egutegia"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Txartel-aurkibidea"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Goranzko joerako diagrama"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Beheranzko joerako diagrama"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Barra-diagrama"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Paperak eusteko taula"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Txintxeta"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Txintxeta biribila"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Klipa"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Erregela"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Kartaboia"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Orri-markatzaileak"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Liburu nagusia"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Koadernoa"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Koadernoa, azal apainduarekin"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Liburua itxita"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Liburua zabalik"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Liburu berdea"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Liburu urdina"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Liburu laranja"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Liburuak"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Izenaren txartela"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Pergaminoa"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Txostena"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonoaren heldulekua"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Bilagailua"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax-makina"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelite bidezko antena"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Eskuko bozgorailua"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Animatzeko bozgorailua"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Irteera-ontziaren erretilua"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Sarrera-ontziaren erretilua"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paketea"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Mezu elektronikoaren ikurra"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Jasotako mezuaren gutun-azala"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Gutun-azala eta beheranzko gezia gainean"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Postontzia itxita eta bandera jaitsita"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Postontzia itxita eta bandera altxatuta"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Postontzia irekita eta bandera jaitsita"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Postontzia irekita eta bandera altxatuta"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postontzia"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Tronpa"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Egunkaria"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Telefono mugikorra"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Telefono mugikorra eta geziak eskuinalderantz ezkerraldean"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Dardara modua"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Telefono mugikorra itzalita"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Telefono mugikorrik ez"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena barrekin"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Bideo-kamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Telebista"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Irratia"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Bideo-kasetea"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Elkar gurutzatzen diren geziak eskuinerantz"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Erlojuaren noranzkoan doazen zirkulu irekiko gezi horizontalak"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Erlojuaren noranzkoan doazen zirkulu irekiko gezi horizontalak, 1 zenbakiarekin"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Erlojuaren noranzkoan doazen zirkulu irekiko gezi bertikalak"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Erlojuaren noranzkoaren aurka doazen zirkulu irekiko gezi bertikalak"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Distira gutxi"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Distira asko"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Bozgorailua eta mutututa ikurra"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Bozgorailua"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Bozgorailua, soinu-uhin batekin"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Bozgorailua, hiru soinu-uhinekin"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Bateria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Entxufe elektrikoa"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa ezkerrerantz"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa eskuinerantz"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Giltzarrapoa eta bolaluma"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Giltzarrapoa itxita eta giltza"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Giltza"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Giltzarrapoa"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Giltzarrapoa irekita"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Kanpaia"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Kanpaia, mutututa ikurrarekin"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Orri-markatzailea"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Estekaren ikurra"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Aukera-botoia"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"Back\" hitza eta ezkerrerantz gezia gainean"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"End\" hitza eta ezkerrerantz gezia gainean"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"On\" hitza harridura markarekin eta ezkerrerantz gezia gainean"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"Soon\" hitza eta eskuinerantz gezia gainean"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"Top\" hitza eta gorantz gezia gainean"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Hemezortzi urte beherakorik ez ikurra"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Hamar tekla"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Letra larri latindarren idazketa-ikurra"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Letra xehe latindarren idazketa-ikurra"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Zenbakien idazketa-ikurra"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Ikurrak idazteko ikurra"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Letra latindarren idazketa-ikurra"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Sua"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Linterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Giltza ingelesa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Mailua"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Torlojua eta azkoina"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Labana"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskopioa"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskopioa"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristalezko bola"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sei puntako izarra eta erdian puntua"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Hasiberrien ikurra japoniarrez"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Hiruhortzekoa"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botoi karratu beltza"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botoi karratu zuria"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Zirkulu gorri handia"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Zirkulu urdin handia"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Diamante laranja handia"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Diamante urdin handia"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Diamante laranja txikia"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Diamante urdin txikia"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Gorantz begirako triangelu gorria"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Beherantz begirako triangelu gorria"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Gorantz begirako triangelu gorri txikia"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Beherantz begirako triangelu gorri txikia"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Erlojuan ordu batak"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Erlojuan ordu biak"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Erlojuan hirurak"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Erlojuan laurak"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Erlojuan bostak"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Erlojuan seiak"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Erlojuan zazpiak"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Erlojuan zortziak"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Erlojuan bederatziak"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Erlojuan hamarrak"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Erlojuan hamaikak"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Erlojuan hamabiak"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Erlojuan ordu bat eta erdiak"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Erlojuan ordu bi eta erdiak"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Erlojuan hiru eta erdiak"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Erlojuan lau eta erdiak"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Erlojuan bost eta erdiak"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Erlojuan sei eta erdiak"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Erlojuan zazpi eta erdiak"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Erlojuan zortzi eta erdiak"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Erlojuan bederatzi eta erdiak"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Erlojuan hamar eta erdiak"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Erlojuan hamaika eta erdiak"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Erlojuan hamabi eta erdiak"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji mendia"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokioko dorrea"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Askatasunaren estatua"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Japonia mapan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moaia"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Aurpegi irribarretsua"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Aurpegi irribarretsua begi irribarretsuekin"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Aurpegia poztasun-malkoekin"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Aurpegi irribarretsua, ahoa zabalik"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Aurpegi irribarretsua, ahora zabalik eta poztasun-begiekin"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Aurpegi irribarretsua, ahora zabalik eta izerdi-hotzeko tantarekin"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Aurpegi irribarretsua, ahoa zabalik eta begi itxi-itxiekin"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Aurpegi irribarretsua argi-koroarekin"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Aurpegi irribarretsua adarrekin"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Begi-keinua egiten ari den aurpegia"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Aurpegi irribarretsua poztasun-begiekin"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Janari gozoa dastatzearen aurpegia"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lasaitasun-aurpegia"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Aurpegi irribarretsua bihotz formako begiekin"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Aurpegi irribarretsua betaurrekoekin"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Konplizitate irribarreko aurpegia"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Aurpegi neutroa"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Sentimendurik adierazten ez duen aurpegia"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Zerbait dibertigarria ez deneko aurpegia"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Aurpegia izerdi hotzeko tantarekin"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Aurpegi pentsakorra"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Ulertu ez izanaren aurpegia"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Nahasmendu-aurpegia"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Musu emateko aurpegia"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Aurpegia musua botatzen"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Musu emateko aurpegia poztasun-begiekin"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Musu emateko aurpegia begi itxiekin"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Aurpegia mihia aterata"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Aurpegia mihia aterata eta begi-keinua egiten"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Aurpegia mihia aterata eta begi itxi-itxiekin"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Desengainu-aurpegia"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Kezka-aurpegia"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Haserre-aurpegia"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Oso haserre-aurpegia"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Aurpegi negartia"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Pertseberantzia-aurpegia"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Aurpegia garaipen begiradarekin"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Desengainu- eta lasaitasun-aurpegia aldi berean"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Aurpegia bekokia zimurtuta eta ahoa zabalik"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Estutasun-aurpegia"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Beldur-aurpegia"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Aspertu-aurpegia"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Logura-aurpegia"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Neke-aurpegia"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Imintzio-aurpegia"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Aurpegia negar-malkotan"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Aurpegia ahoa zabalik"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Isiltasun-aurpegia"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Aurpegia ahoa zabalik eta izerdi hotzaren tantarekin"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Aurpegia izuz oihuka"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Harridura-aurpegia"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Aurpegi gorrituta"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Aurpegia lotan"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Zorabio-aurpegia"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Aurpegia ahorik gabe"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Aurpegia mediku-maskararekin"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Katu-aurpegi irribarretsua poztasun-begiekin"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Katu-aurpegia poztasun-malkoekin"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Katu-aurpegi irribarretsua, ahoa zabalik"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Katu-aurpegi irribarretsua bihotz-formako begiekin"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Katu-aurpegia irribarre ironikoarekin"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Musu emateko katu-aurpegia begi itxiekin"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Katu-aurpegia oso haserretuta"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Katu-aurpegia negarrez"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Katu-aurpegia aspertuta"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Keinu txarreko aurpegia"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Onarpen-keinuko aurpegia"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Pertsona makurtuta, agur egiten"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Tximinoa, gauza okerrak esaten ez dituena"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Tximinoa, gauza okerrak entzuten ez dituena"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Tximinoa, gaizki hitz egiten ez duena"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Pertsona alaia, eskua altxatuta"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Bostekoa bi eskuekin"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Pertsona bekoki ilunarekin"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Pertsona bat oso haserre"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Pertsona bat, eskuak batera jarrita"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Suziria"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopteroa"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Lurrunezko trena"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Bagoia"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Abiadura handiko trena"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Abiadura handiko trena mutur borobilduarekin"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Trena"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metroa"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Burdinbide arina"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Geltokia"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tranbia"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tranbia-bagoia"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobusa"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobusa heltzen"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolebusa"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobus-geltokia"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibusa"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Anbulantzia"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Suhiltzaileen kamioia"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Polizia-autoa"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Polizia-autoa heltzen"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxia"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxia heltzen"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Ibilgailua"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Ibilgailua heltzen"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Aisialdirako ibilgailua"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Banaketa-kamioia"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Kamioi artikulatua"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktorea"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Errailbakarra"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Mendiko trena"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Tren esekia"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Mendiko teleferikoa"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Teleferikoa"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Itsasontzia"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Txalupa"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motorrezko ontzia"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semaforo horizontala"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semaforo bertikala"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Obren ikurra"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Polizia-autoen argiak"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Hiruki formako bandera zutoin batean"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Atea"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Ez sartu ikurra"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Erretzearen ikurra"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Erretzea debekatuta ikurra"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Bota zaborra zaborrontzira ikurra"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Ez bota zaborrik ikurra"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Ur edangarria ikurra"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ur ez edangarria ikurra"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bizikleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Bizikletarik ez"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Txirrindularia"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mendiko txirrindularia"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Oinezkoa"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Oinezkorik ez"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Umeak gurutzatzen"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Gizonezkoen ikurra"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Emakumezkoen ikurra"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Denentzako komuna"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Haurtxoaren ikurra"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Komuna"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC komuna"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dutxa"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bainua hartzea"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bainuontzia"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasaporte-kontrola"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Aduana"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Ekipaje-erreklamazioa"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Ahaztutako maletak"</string>
+</resources>
diff --git a/java/res/values-eu-rES/strings-talkback-descriptions.xml b/java/res/values-eu-rES/strings-talkback-descriptions.xml
index 949195d..285cc7b 100644
--- a/java/res/values-eu-rES/strings-talkback-descriptions.xml
+++ b/java/res/values-eu-rES/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Ez da testurik idatzi"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> teklak \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" hitza \"<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>\" bihurtzen du"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> teklak zuzenketa automatikoa egiten du"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ez dago iradokizunik"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Karaktere ezezaguna"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Maius"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Ikur gehiago"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiuskula goi-puntuduna"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ikur ezezaguna"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emotikono ezezaguna"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Aurpegi aspertua"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Aurpegi lotsatua"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Eguzkitako betaurrekodun aurpegia"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Harritutako aurpegia"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Musu ematen ari den aurpegia"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Kopeta zimurtutako aurpegia"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Ordezko karaktereak erabilgarri daude"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Ordezko karaktereak baztertu dira"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Ordezko iradokizunak erabilgarri daude"</string>
diff --git a/java/res/values-eu-rES/strings.xml b/java/res/values-eu-rES/strings.xml
index 5db18a9..179ebf4 100644
--- a/java/res/values-eu-rES/strings.xml
+++ b/java/res/values-eu-rES/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Egin dar-dar sakatzean"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Egin soinua tekla sakatzean"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Handitu teklak, sakatzean"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Hobespenak"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Kontuak eta pribatutasuna"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Itxura eta diseinuak"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Keinu bidezko idazketa"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Testu-zuzenketa"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Ezarpen aurreratuak"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Gaia"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Gaitu teklatu banatua"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google teklatuaren sinkronizazioa"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinkronizazioa aktibatuta dago"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Izan hiztegi pertsonala sinkronizatuta gailu guztietan"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinkronizatu"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Ezabatu hodeiko datuak"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Sinkronizatutako datuak ezabatzen ditu Google-tik"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Datuak hodeitik ezabatuko dira. Ziur hori egin nahi duzula?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Ezabatu"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Utzi"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Hiztegi pertsonalizatua sinkronizatu egingo da eta Google zerbitzarietan gordeko da babeskopia gisa. Hitzak erabiltzeko maiztasunari buruzko estatistikak bil daitezke produktuak hobetzen laguntzeko. Informazioaren bilketak eta erabilerak "<a href="https://www.google.com/policies/privacy">"Google Pribatutasun-gidalerroak"</a>" gordeko ditu uneoro."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Eginbidea gaitzeko, gehitu Google kontua gailuan"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Aldatu idazketa-metodoa"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Hizkuntza aldatzeko teklak beste idazketa-metodoetarako ere balio du"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Hizkuntza aldatzeko tekla"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Erakutsi hainbat sarrera-hizkuntza gaituta daudenean"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Erakutsi lerratze-adierazlea"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Bistaratu ikusizko seinalea Maius edo Ikur tekletatik lerratzean"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Desagertzeko atzerapena"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Atzerapenik gabe"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lehenetsia"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hiztegi nagusia"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Erakutsi zuzenketa-iradokizunak"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Bistaratu iradokitako hitzak idatzi bitartean"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Erakutsi beti"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Erakutsi bertikalean"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ezkutatu beti"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokeatu hitz iraingarriak"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ez iradoki iraingarria izan daitekeen hitzik"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Zuzenketa automatikoa"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Ahots bidezko idazketaren tekla"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ez da ahots bidezko idazketa-metodorik gaitu. Egiaztatu Hizkuntza eta idazketa ataleko ezarpenak."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguratu idazketa-metodoak"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idazketa-hizkuntzak"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Bidali oharrak"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idazketa-hizkuntzak"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Hizkuntzak"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Laguntza eta iritziak"</string>
+    <string name="select_language" msgid="5709487854987078367">"Hizkuntzak"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gordetzeko, ukitu berriro"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Gordetzeko, ukitu hau"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Hiztegia erabilgarri"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Teklatuaren gaia"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Aldatu kontuz"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Ez da konturik hautatu"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> helbidea ari zara erabiltzen"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Ados"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Utzi"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Amaitu saioa"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Hautatu erabili nahi duzun kontua"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingelesa (Erresuma Batua)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingelesa (AEB)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Gaztelania (AEB)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglisha"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbiarra (latindarra)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingelesa (Erresuma Batua) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingelesa (AEB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Gaztelania (AEB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglisha (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbiarra (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionala)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (zirilikoa)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latindarra)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (trinkoa)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ez dago hizkuntzarik (alfabetoa)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabetoa (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabetoa (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabetoa (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabetoa (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emotikonoak"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Teklatuaren gaia"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Idazketa-estilo pertsonalizatuak"</string>
     <string name="add_style" msgid="6163126614514489951">"Gehitu estiloa"</string>
     <string name="add" msgid="8299699805688017798">"Gehitu"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Gaitu"</string>
     <string name="not_now" msgid="6172462888202790482">"Orain ez"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Idazketa-estilo hori badago lehendik ere: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tekla luze sakatzearen atzerapena"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Tekla sakatzearen dardararen iraupena"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Tekla sakatzearen bolumena"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Irakurri kanpoko hiztegi-fitxategia"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Ez dago hiztegi-fitxategirik Deskargak karpetan"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Hautatu hiztegi-fitxategi bat instalatzeko"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Fitxategi hau <xliff:g id="LANGUAGE_NAME">%s</xliff:g> hizkuntzarako instalatu nahi duzu?"</string>
-    <string name="error" msgid="8940763624668513648">"Errore bat gertatu da"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tekla luze sakatzearen atzerapena"</string>
     <string name="button_default" msgid="3988017840431881491">"Lehenetsia"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Ongi etorri <xliff:g id="APPLICATION_NAME">%s</xliff:g> aplikaziora"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Keinu bidezko idazketarekin"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Gogokoen dituzun aplikazioetan idatz dezakezu dagoeneko <xliff:g id="APPLICATION_NAME">%s</xliff:g> erabilita."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfiguratu hizkuntza gehigarriak"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Amaituta"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Erakutsi aplikazioaren ikonoa"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Bistaratu aplikazioaren ikonoa abiarazlean"</string>
     <string name="app_name" msgid="6320102637491234792">"Hiztegi-hornitzailea"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Hiztegi-hornitzailea"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Hiztegi-zerbitzua"</string>
diff --git a/java/res/values-fa/strings-emoji-descriptions.xml b/java/res/values-fa/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..e10689d
--- /dev/null
+++ b/java/res/values-fa/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"علامت حق نسخه‌برداری"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"علامت ثبت شده"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"دو علامت تعجب"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"علامت تعجب و سؤال"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"علامت تجاری"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"منبع اطلاعات"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"پیکان چپ راست"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"پیکان بالا پایین"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"پیکان شمال غرب"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"پیکان شمال شرق"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"پیکان جنوب شرق"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"پیکان جنوب غرب"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"پیکان سمت چپ با قلاب"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"پیکان سمت راست با قلاب"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"ساعت مچی"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"ساعت شنی"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"دو مثلث سیاه به سمت راست"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"دو مثلث سیاه به سمت چپ"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"دو مثلث سیاه به سمت بالا"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"دو مثلث سیاه به سمت پایین"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"ساعت زنگ‌دار"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"ساعت شنی با شن‌های در جریان"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"‏حرف بزرگ M داخل دایره"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"مربع کوچک سیاه"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"مربع کوچک سفید"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"مثلث سیاه به سمت راست"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"مثلث سیاه به سمت چپ"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"مربع متوسط سفید"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"مربع متوسط سیاه"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"مربع کوچک متوسط سفید"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"مربع کوچک متوسط سیاه"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"خورشید سیاه با اشعه"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"ابر"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"تلفن سیاه"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"جعبه نظردهی علامت‌دار"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"چتر با قطرات باران"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"نوشیدنی گرم"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"انگشت اشاره سفید به سمت بالا"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"صورتک سفید خندان"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"قوچ"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"گاو"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"دوقلو"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"خرچنگ"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"شیر"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"سنبله"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"ترازو"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"عقرب"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"کمان‌دار"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"بزغاله"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"دلو"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"ماهی"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"ورق پیک سیاه"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"ورق گیشنیز سیاه"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"ورق دل سیاه"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"ورق خشت سیاه"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"چشمه‌های آب داغ"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"نماد سیاه جهانی بازیافت"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"نماد صندلی چرخ‌دار"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"لنگر"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"علامت خطر"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"علامت ولتاژ بالا"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"دایره متوسط سفید"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"دایره متوسط سیاه"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"توپ فوتبال"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"توپ بیسبال"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"آدم‌برفی بدون برف"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"خورشید پشت ابر"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"نشان مار اَفسای"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"ورود ممنوع"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"کلیسا"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"فواره"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"پرچم گلف"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"قایق بادبانی"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"چادر"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"پمپ بنزین"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"قیچی سیاه"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"تیک بزرگ سفید"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"هواپیما"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"پاکت نامه"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"مشت بالا آمده"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"دست بالا آمده"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"علامت پیروزی"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"مداد"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"نوک قلم مشکی"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"تیک بزرگ"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"علامت ضرب بزرگ"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"ستاره درخشان"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"ستاره هشت شاخه"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"ستاره هشت شاخه سیاه"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"دانه برف"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"ستاره درخشان"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"علامت ضربدر"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"علامت ضربدر در مربع منفی"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"علامت سؤال سیاه تزئینی"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"علامت سؤال سفید تزئینی"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"علامت تعجب سفید تزئینی"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"نماد علامت تعجب بزرگ"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"قلب سیاه سنگین"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"علامت مثبت بزرگ"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"علامت منفی بزرگ"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"علامت تقسیم بزرگ"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"پیکان سیاه به سمت راست"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"حلقه پیچ‌دار"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"حلقه با دو پیچ"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"پیکان منحنی به سمت راست و سپس با پیچ به سمت بالا"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"پیکان منحنی به سمت راست و سپس با پیچ به سمت پایین"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"پیکان سیاه به سمت چپ"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"پیکان سیاه به سمت بالا"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"پیکان سیاه به سمت پایین"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"مربع بزرگ سیاه"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"مربع بزرگ سفید"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"ستاره متوسط سفید"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"دایره بزرگ سفید"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"خط موج‌دار"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"علامت تغییر جزئی"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"علامت تصویری تبریک داخل دایره"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"علامت تصویری اسرار داخل دایره"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"اژدهای قرمز کاشی مهجونگ"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"ورق جوکر سیاه"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"‏گروه خونی A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"‏گروه خونی B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"‏گروه خونی O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"محوطه پارکینگ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"‏گروه خونی AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"‏CL داخل مربع"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"‏Cool داخل مربع"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"‏Free داخل مربع"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"‏ID داخل مربع"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"‏new داخل مربع"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"‏N G داخل مربع"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"‏OK داخل مربع"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"‏SOS داخل مربع"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"‏up با علامت تعجب داخل مربع"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"‏vs داخل مربع"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"حروف کاتاکانای کلمه اینجا داخل مربع"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"حروف کاتاکانای کلمه سرویس داخل مربع"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"علامت تصویری بدون هزینه داخل مربع"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"علامت صندلی رزرو شده داخل مربع"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"علامت تصویری ممنوع داخل مربع"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"علامت تصویری جای خالی داخل مربع"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"علامت تصویری پذیرش داخل مربع"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"علامت تصویری اشغال کامل داخل مربع"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"علامت تصویری پرداخت شده داخل مربع"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"علامت تصویری ماهانه داخل مربع"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"علامت تصویری درخواست داخل مربع"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"علامت تصویری تخفیف داخل مربع"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"علامت تصویری مشغول کسب و کار داخل مربع"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"علامت تصویری مزیت داخل دایره"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"علامت تصویری پذیرش داخل دایره"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"گردباد"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"مه‌آلود"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"چتر بسته شده"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"شب پرستاره"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"طلوع خورشید بالای کوه‌ها"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"طلوع خورشید"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"منظره شهر هنگام غروب"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"غروب خورشید بالای ساختمان‌ها"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"رنگین‌کمان"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"منظره پل در شب"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"امواج آب"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"آتش‌فشان"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"راه شیری"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"کره زمین اروپا-آفریقا"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"کره زمین قاره آمریکا"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"کره زمین آسیا-استرالیا"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"کره با نصف النهارها"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"نماد هلال ماه"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"نماد هلال ماه فزاینده"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"نماد ربع اول ماه"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"نماد هلال ماه برآمده فزاینده"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"نماد ماه کامل"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"نماد هلال ماه برآمده کاهنده"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"نماد ربع ماه آخر"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"نماد هلال ماه کاهنده"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"هلال ماه"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"ماه نو با چهره"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"ربع اول ماه با چهره"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"ربع آخر ماه با چهره"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"ماه کامل با چهره"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"خورشید با چهره"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"ستاره درخشان"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"شهاب سنگ"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"شاه بلوط"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"جوانه"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"درخت همیشه سبز"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"درخت پاییزی"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"درخت نخل"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"کاکتوس"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"گل لاله"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"شکوفه‌های گیلاس"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"گل رز"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"گل ختمی ژاپنی"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"گل آفتابگردان"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"شکوفه"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"خوشه ذرت"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"خوشه برنج"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"علف"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"شبدر چهاربرگ"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"برگ افرا"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"برگ افتاده"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"برگ‌های لرزان در باد"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"قارچ"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"گوجه‌فرنگی"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"بادمجان"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"انگور"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"خربزه"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"هندوانه"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"نارنگی"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"لیمو"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"موز"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"آناناس"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"سیب قرمز"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"سیب سبز"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"گلابی"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"هلو"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"گیلاس"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"توت‌فرنگی"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"همبرگر"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"قاچ پیتزا"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"گوشت با استخوان"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"ران مرغ"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"کراکر برنج"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"کوفته برنجی"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"برنج پخته شده"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"کاری و برنج"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"کاسه بخارپز"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"اسپاگتی"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"نان"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"سیب‌زمینی سرخ کرده"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"سیب‌زمینی شیرین برشته"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"دانگو"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"اودن"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"سوشی"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"میگو سوخاری"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"کیک ماهی با طرح چرخشی"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"بستنی نرم"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"بستنی یخی"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"بستنی"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"دونات"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"کلوچه"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"تخته شکلات"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"آبنبات"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"آب‌نبات چوبی"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"کاستارد"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ظرف عسل"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"کیک روغنی"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"جعبه سوشی بنتو"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"قابلمه غذا"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"آشپزی"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"چاقو و چنگال"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"فنجان چای بدون دسته"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"بطری و پیاله شراب برنج"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"گیلاس شراب"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"گیلاس کوکتل"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"نوشیدنی استوایی"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"لیوان آبجو"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"به هم خوردن لیوان‌های آبجو"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"پستانک بچه"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"روبان"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"هدیه کادو شده"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"کیک تولد"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"کدوی فانوسی"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"درخت کریسمس"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"بابانوئل"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"آتش‌بازی"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"آتش‌بازی جرقه‌دار"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"بالون"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"پارتی پوپر"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"توپ آبنباتی"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"درخت تاناباتا"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"پرچم‌های ضربدری"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"تزئین درخت کاج"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"عروسک‌های ژاپنی"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"پرچم ماهی‌های کپور"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"سوت سوتک بادی"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"جشن تماشای ماه"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"کیف مدرسه"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"کلاه فارغ‌التحصیلی"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"اسب چرخ و فلک"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"چرخ و فلک"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"رولرکوستر"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"چوب ماهیگیری و ماهی"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"میکروفون"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"دوربین فیلم"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"سینما"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"هدفون"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"پالت نقاشی"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"کلاه مردانه استوانه‌ای"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"چادر سیرک"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"بلیت"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"کلاکت"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"هنرهای نمایشی"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"بازی ویدیویی"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"ضربه مستقیم"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"ماشین پولی"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"بیلیارد"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"تاس بازی"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"بولینگ"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"گل ورق بازی"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"نت موسیقی"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"نت‌های چندگانه موسیقی"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"ساکسوفون"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"گیتار"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"کی‌بورد موسیقی"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ترومپت"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"ویولون"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"نت موسیقی"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"تی‌شرت دو با حمایل"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"راکت و توپ تنیس"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"اسکی و کفش اسکی"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"بسکتبال و حلقه"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"پرچم شطرنجی"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"اسنوبورد سوار"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"دونده"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"موج‌سوار"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"جام"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"مسابقه اسب‌سواری"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"فوتبال آمریکایی"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"فوتبال راگبی"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"شناگر"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"ساختمان خانه"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"خانه با باغ"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"ساختمان اداره"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"اداره پست ژاپنی"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"اداره پست اروپایی"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"بیمارستان"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"بانک"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"دستگاه خودپرداز"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"هتل"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"هتل عشاق"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"خواروبار فروشی"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"مدرسه"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"فروشگاه زنجیره‌ای"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"کارخانه"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"فانوس ژاپنی"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"قلعه ژاپنی"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"قلعه اروپایی"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"موش صحرایی"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"موش"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"گاو"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"بوفالوی آبی"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"گاو"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"پلنگ"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"خرگوش"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"گربه"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"اژدها"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"تمساح"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"نهنگ"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"حلزون"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"مار"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"اسب"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"قوچ"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"بز"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"گوسفند"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"میمون"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"خروس"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"مرغ"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"سگ"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"خوک"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"گراز وحشی"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"فیل"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"اختاپوس"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"صدف مارپیچ"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"حشره"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"مورچه"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"زنبور عسل"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"کفشدوزک"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"ماهی"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ماهی استوایی"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ماهی بادکنکی"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"لاک‌پشت"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"جوجه در حال بیرون آمدن از تخم"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"جوجه"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"جوجه از رو به رو"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"پرنده"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"پنگوئن"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"کوآلا"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"سگ پشمالو"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"شتر یک‌کوهانه"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"شتر دوکوهانه"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"دولفین"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"صورت موش"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"صورت گاو"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"صورت ببر"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"صورت خرگوش"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"صورت گربه"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"صورت اژدها"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"نهنگ در حال آب پاشیدن"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"صورت اسب"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"صورت میمون"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"صورت سگ"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"صورت خوک"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"صورت قورباغه"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"صورت همستر"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"صورت گرگ"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"صورت خرس"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"صورت پاندا"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"بینی خوک"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"اثر پنجه"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"چشم‌ها"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"گوش"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"بینی"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"دهان"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"زبان"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"اشاره به بالا با دست"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"اشاره به پایین با دست"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"اشاره به چپ با دست"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"اشاره به راست با دست"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"علامت دست مشت شده"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"علامت دست درحال خداحافظی"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"علامت دست تأیید"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"علامت شصت به بالا"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"علامت شصت به پایین"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"علامت در حال دست زدن"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"علامت دو دست باز"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"تاج"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"کلاه زنانه"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"عینک"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"کراوات"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"تی‌شرت"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"شلوار جین"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"پیراهن"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"کیمونو"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"بیکینی"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"لباس زنانه"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"کیف زنانه"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"کیف دستی"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"کیف پارچه‌ای"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"کفش مردانه"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"کفش ورزشی"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"کفش پاشنه بلند"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"صندل زنانه"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"چکمه زنانه"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"رد پا"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"سایه سر و شانه"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"سایه‌های سر و شانه"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"پسر"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"دختر"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"مرد"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"زن"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"خانواده"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"مرد و زن دست در دست هم"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"دو مرد دست در دست هم"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"دو زن دست در دست هم"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"مأمور پلیس"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"زن با گوش‌های خرگوشی"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"عروس با تور"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"شخصی با موهای بلوند"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"مرد با کلاه ژاپنی"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"مرد با عمامه"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"مرد پیر"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"زن پیر"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"کودک"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"کارگر ساختمان"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"شاهزاده خانم"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"غول ژاپنی"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"جن ژاپنی"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"روح"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"فرشته کودک"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"بیگانه فرازمینی"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"هیولای بیگانه"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"شیطانک"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"جمجمه"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"کارمند میز اطلاعات"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"نگهبان"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"رقصنده"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"رژ لب"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"لاک ناخن"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"ماساژ صورت"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"کوتاه کردن مو"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"چرخه آرایشگری"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"سرنگ"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"قرص"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"علامت بوسه"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"نامه عاشقانه"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"حلقه"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"سنگ‌های قیمتی"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"بوسه"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"دسته گل"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"زوج با قلب"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"ازدواج"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"قلب تپنده"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"قلب شکسته"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"دو قلب"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"قلب درخشنده"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"قلب بزرگ‌شونده"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"قلب با پیکان"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"قلب آبی"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"قلب سبز"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"قلب زرد"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"قلب بنفش"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"قلب با روبان"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"قلب‌های گردان"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"تزئین قلب"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"شکل الماس با یک نقطه در داخل آن"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"لامپ برق"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"نماد خشم"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"بمب"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"نماد خواب"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"نماد برخورد"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"نماد ترشح عرق"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"قطره"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"نماد خط تیره"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"توده مدفوع"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"بازوی پهلوانی"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"نماد سرگیجه"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"بالون گفتگو"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"بالون تفکر"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"گل سفید"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"نماد صد امتیاز"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"کیف پول"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"تبدیل ارز"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"نماد دلار زیاد"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"کارت اعتباری"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"اسکناس با علامت ین"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"اسکناس با علامت دلار"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"اسکناس با علامت یورو"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"اسکناس با علامت پوند"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"پول بالدار"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"نمودار با روند رو به بالا و علامت ین"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"صندلی"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"رایانه شخصی"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"سامسونت"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"مینی دیسک"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"فلاپی دیسک"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"دیسک نوری"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"دی وی دی"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"پوشه فایل"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"باز کردن پوشه فایل"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"صفحه با تاخوردگی"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"صفحه رو به بالا"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"تقویم"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"تقویم پاره شده"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"کارت اطلاعات"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"نمودار با روند رو به بالا"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"نمودار با روند رو به پایین"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"نمودار میله‌ای"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"تخته رسم گیره‌دار"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"پین"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"سنجاق ته‌گرد"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"گیره کاغذ"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"خط‌کش"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"گونیا"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"برچسب‌های علامت‌گذاری"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"زونکن"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"دفترچه"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"دفترچه با جلد تزئینی"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"کتاب بسته"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"کتاب باز"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"کتاب سبز"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"کتاب آبی"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"کتاب نارنجی"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"کتاب‌ها"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"نشان نام"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"پیمایش"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"یادداشت"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"گوشی تلفن"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"پیجر"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"دستگاه نمابر"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"آنتن ماهواره"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"بلندگوی جارچی"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"بلندگوی تشویق‌کننده"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"سینی صندوق ارسال"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"سینی صندوق ورودی"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"بسته‌بندی"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"نماد ایمیل"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"پاکت نامه ورودی"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"پاکت نامه با پیکان‌های رو به پایین در بالا"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"صندوق پستی بسته شده با پرچم پایین آمده"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"صندوق پستی بسته شده با پرچم بالا آمده"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"صندوق پستی باز با پرچم بالا آمده"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"صندوق پستی باز با پرچم پایین آمده"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"صندوق پستی"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"بوق پستی"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"روزنامه"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"تلفن همراه"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"تلفن همراه با پیکان رو به راست در سمت چپ"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"حالت لرزش"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"تلفن همراه خاموش"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"تلفن همراه خاموش"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"آنتن با میله"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"دوربین"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"دوربین ویدیویی"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"تلویزیون"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"رادیو"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"نوار ویدیویی"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"پیکان‌های خم شده به سمت راست"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"پیکان‌های دایره‌ای شکل باز به سمت راست و چپ در جهت عقربه‌های ساعت"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"پیکان‌های دایره‌ای شکل باز به سمت راست و چپ در جهت عقربه‌های ساعت با یک پیکان دایره‌‌ای شکل روی آنها"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"پیکان‌های دایره‌ای شکل باز به سمت بالا و پایین در جهت عقربه‌های ساعت"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"پیکان‌های دایره‌ای شکل باز به سمت بالا و پایین در خلاف جهت عقربه‌های ساعت"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"علامت درخشندگی کم"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"علامت درخشندگی زیاد"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"بلندگو با علامت قطع صدا"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"بلندگو"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"بلندگو با یک موج صدا"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"بلندگو با سه موج صدا"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"باتری"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"دوشاخه برق"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"ذره‌بین متمایل به چپ"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"ذره‌بین متمایل به راست"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"قفل با خودنویس"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"قفل بسته با کلید"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"کلید"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"قفل"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"قفل باز"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"زنگ"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"زنگ با علامت قطع صدا"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"نشانک"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"نماد پیوند"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"دکمه رادیو"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"‏Back با پیکان سمت چپ در بالا"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"‏End با پیکان سمت چپ در بالا"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"‏ON با علامت تعجب و پیکان چپ و راست در بالا"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"‏Soon با پیکان سمت راست در بالا"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"‏Top با پیکان سمت بالا"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"نماد بالای هجده سال"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"کلید عدد ۱۰"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"نماد ورودی برای حروف بزرگ لاتین"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"نماد ورودی برای حروف کوچک لاتین"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"نماد ورودی برای اعداد"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"نماد ورودی برای نمادها"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"نماد ورودی برای حروف لاتین"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"آتش"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"چراغ قوه"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"آچار فرانسه"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"چکش"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"پیچ و مهره"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"چاقوی آشپزخانه"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"تپانچه"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"میکروسکوپ"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"تلسکوپ"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"گوی کریستال"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"ستاره شش پر با نقطه وسط"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"نماد ژاپنی برای تازه‌کار"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"علامت نیزه سه شاخه"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"دکمه مربع مشکی"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"دکمه مربع سفید"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"دایره بزرگ قرمز"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"دایره بزرگ آبی"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"الماس بزرگ نارنجی"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"الماس بزرگ آبی"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"الماس کوچک نارنجی"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"الماس کوچک آبی"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"مثلث قرمز رو به بالا"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"مثلث قرمز رو به پایین"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"مثلث کوچک قرمز رو به بالا"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"مثلث کوچک قرمز رو به پایین"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"ساعت نشان‌دهنده ساعت یک"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"ساعت نشان‌دهنده ساعت دو"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"ساعت نشان‌دهنده ساعت سه"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"ساعت نشان‌دهنده ساعت چهار"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"ساعت نشان‌دهنده ساعت پنج"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"ساعت نشان‌دهنده ساعت شش"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"ساعت نشان‌دهنده ساعت هفت"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"ساعت نشان‌دهنده ساعت هشت"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"ساعت نشان‌دهنده ساعت نه"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"ساعت نشان‌دهنده ساعت ده"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"ساعت نشان‌دهنده ساعت یازده"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"ساعت نشان‌دهنده ساعت دوازده"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"ساعت نشان‌دهنده ساعت یک و نیم"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"ساعت نشان‌دهنده ساعت دو و نیم"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"ساعت نشان‌دهنده ساعت سه و نیم"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"ساعت نشان‌دهنده ساعت چهار و نیم"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"ساعت نشان‌دهنده ساعت پنج و نیم"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"ساعت نشان‌دهنده ساعت شش و نیم"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"ساعت نشان‌دهنده ساعت هفت و نیم"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"ساعت نشان‌دهنده ساعت هشت و نیم"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"ساعت نشان‌دهنده ساعت نه و نیم"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"ساعت نشان‌دهنده ساعت ده و نیم"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"ساعت نشان‌دهنده ساعت یازده و نیم"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"ساعت نشان‌دهنده ساعت دوازده و نیم"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"کوه فوجی"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"برج توکیو"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"مجسمه آزادی"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"نقشه سایه‌ای ژاپن"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"مجسمه مویای"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"صورتک با پوزخند"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"صورتک با پوزخند و چشمان خندان"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"صورتک با اشک خوشحالی"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"صورتک خندان با دهان باز"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"صورتک خندان با دهان باز و چشمان خندان"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"صورتک خندان با دهان باز و عرق سرد"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"صورتک خندان با دهان باز و چشمان بسته"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"صورتک خندان با هاله نور"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"صورتک خندان با شاخ"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"صورتک چشمک‌زن"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"صورتک خندان با چشمان خندان"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"صورتک در حال لذت بردن از غذای خوشمزه"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"صورتک آسوده‌خاطر"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"صورتک خندان با چشمان قلب شکل"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"صورتک خندان با عینک دودی"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"صورتک پوزخندزن"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"صورتک بی‌تفاوت"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"صورتک بی‌احساس"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"صورتک کسل شده"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"صورتک با عرق سرد"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"صورتک متفکر"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"صورتک گیج"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"صورتک سردرگم"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"صورتک بوسه‌زن"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"صورت درحال پرتاب بوسه"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"صورتک بوسه‌زن با چشمان خندان"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"صورتک خندان با چشمان بسته"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"صورتک با زبان بیرون آمده"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"صورتک با زبان بیرون آمده و چشمک‌زن"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"صورتک با زبان بیرون آمده و چشمان بسته"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"صورتک ناامید"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"صورتک نگران"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"صورتک عصبانی"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"صورتک با لب‌های آویزان"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"صورتک گریان"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"صورتک مصمم"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"صورتک با حالت پیروزمندانه"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"صورتک ناامید اما آسوده خاطر"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"صورتک اخمو با دهان باز"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"صورتک نگران"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"صورتک ترسو"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"صورتک از پا افتاده"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"صورتک خواب‌آلود"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"صورتک خسته"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"صورتک دهان‌کج"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"صورتک زار زنان"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"صورتک با دهان باز"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"صورتک با علامت هیس"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"صورتک با دهان باز و عرق سرد"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"صورتک جیغ‌زنان از ترس"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"صورتک مبهوت"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"صورت قرمزشده"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"صورتک خواب‌آلود"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"صورتک گیج"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"صورتک بدون دهان"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"صورتک با ماسک پزشکی"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"صورتک گربه پوزخندزنان با چشمان خندان"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"صورتک گربه با اشک خوشحالی"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"صورتک گربه خندان با دهان باز"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"صورتک گربه خندان با چشمانی به شکل قلب"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"صورتک گربه با لبخند کنایه‌آمیز"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"صورتک گربه بوسه‌زن با چشمان بسته"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"صورتک گربه با لب‌های آویزان"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"صورتک گربه گریان"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"صورتک گربه از پا افتاده"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"صورتک با ژست «خوب نیست»"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"صورتک با ژست تأیید"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"شخصی در حال تعظیم کردن"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"میمونی با چشمان بسته"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"میمونی با گوش‌های بسته"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"میمونی با دهان بسته"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"شخص خوشحالی که یک دستش بالاست"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"فردی با دو دست بالا در حال شادی"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"شخصی در حال اخم"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"شخصی با صورت و لب‌های آویزان"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"شخصی با دستان قلاب شده"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"موشک"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"بالگرد"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"لوکوموتیو بخار"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"واگن قطار"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"قطار سریع‌السیر"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"قطار سریع‌السیر با دماغه فشنگی"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"قطار"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"مترو"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"لایت ریل"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"ایستگاه"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"تراموا"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"واگن تراموا"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"اتوبوس"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"اتوبوس‌ در حال نزدیک شدن"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"اتوبوس برقی"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"ایستگاه اتوبوس"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"مینی‌بوس"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"آمبولانس"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"ماشین آتش‌نشانی"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"ماشین پلیس"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"ماشین پلیس درحال نزدیک شدن"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"تاکسی"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"تاکسی در حال نزدیک شدن"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"اتومبیل"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"اتومبیل در حال نزدیک شدن"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"ماشین تفریحی"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"کامیون حمل کالا"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"کامیون کمرشکن"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"تراکتور"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"مونوریل"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"خط آهن کوهستانی"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"راه‌آهن معلق"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"تله‌کابین کوهستانی"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"تراموای هوایی"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"کشتی"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"قایق پارویی"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"قایق سریع‌السیر"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"چراغ راهنمایی افقی"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"چراغ‌های راهنمای عمودی"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"علامت ساخت و ساز"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"چراغ گردان ماشین پلیس"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"پرچم مثلثی روی میله"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"در"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"علامت ورود ممنوع"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"نماد سیگار کشیدن"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"نماد سیگار کشیدن ممنوع"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"نماد انداختن زباله در محل آن"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"نماد زباله ریختن ممنوع"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"نماد آب قابل شرب"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"نماد آب غیرقابل شرب"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"دوچرخه"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"دوچرخه ممنوع"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"دوچرخه‌سوار"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"دوچرخه‌سوار کوهستان"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"عابر پیاده"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"عبور عابر پیاده ممنوع"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"محل عبور اطفال"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"نماد مردان"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"نماد زنان"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"دستشویی"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"نماد کودک"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"توالت"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"‏علامت WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"دوش حمام"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"حمام"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"وان حمام"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"کنترل گذرنامه"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"گمرک"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"تحویل بار"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"بار جامانده"</string>
+</resources>
diff --git a/java/res/values-fa/strings-talkback-descriptions.xml b/java/res/values-fa/strings-talkback-descriptions.xml
index 988dd5c..7a11cff 100644
--- a/java/res/values-fa/strings-talkback-descriptions.xml
+++ b/java/res/values-fa/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"نوشتاری وارد نشده است"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>، ‏<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> را به <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> تصحیح می‌کند"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> تصحیح خودکار را انجام می‌دهد"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"هیچ پیشنهادی وجود ندارد"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"نویسه نامشخص"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"نمادهای بیشتر"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"‏I بزرگ با نقطه بالایی"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"نماد نامشخص"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"‏شکلک emoji نامشخص"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"صورتک بی‌حوصله"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"صورتک شرمنده"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"صورتک با عینک آفتابی"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"صورتک شگفت‌زده"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"صورتک بوسه‌زن"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"صورتک اخمو"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"نویسه‌های جایگزین در دسترس هستند"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"از نویسه‌های جایگزین صرفنظر می‌شود"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"پیشنهادهای جایگزین در دسترس هستند"</string>
diff --git a/java/res/values-fa/strings.xml b/java/res/values-fa/strings.xml
index 1ce5ad2..c6d0595 100644
--- a/java/res/values-fa/strings.xml
+++ b/java/res/values-fa/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"لرزش با فشار کلید"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"صدا با فشار کلید"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"بازشدن با فشار کلید"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"تنظیمات ترجیحی"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"حساب‌ها و حریم خصوصی"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"شکل ظاهری و چیدمان"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ورودی اشاره‌ای"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"اصلاح نوشتار"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"پیشرفته"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"طرح‌زمینه"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"فعال کردن دونیم‌کردن صفحه‌کلید"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"‏همگام‌سازی صفحه‌کلید Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"همگام‌سازی روشن است"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"همگام‌سازی فرهنگ لغت شخصی‌تان در همه دستگاه‌ها"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"اکنون همگام‌سازی شود"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"‏حذف داده‌های cloud"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"‏اطلاعات همگام‌سازی شده شما را از Google حذف می‌کند"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"‏داده‌های همگام‌سازی شده شما از cloud حذف می‌شوند. مطمئنید؟"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"حذف"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"لغو"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"‏فرهنگ لغت شخصی شما با سرورهای Google همگام‌سازی و در آنها پشتیبان گرفته می‌شود. ممکن است برای کمک به بهبود محصولات ما، اطلاعات آماری از فراوانی کلمه جمع‌آوری شود. جمع‌آوری و استفاده از همه اطلاعات مطابق با "<a href="https://www.google.com/policies/privacy">"خط‌مشی رازداری Google"</a>" خواهد بود."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"‏برای فعال کردن این ویژگی، یک حساب Google به این دستگاه اضافه کنید"</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">"کلید تغییر زبان، سایر ورودی‌های زبان را نیز پوشش می‌دهد"</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">"نمایش نشانگر لغزاندن"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"‏نمایش نشان بصری، هنگام لغزاندن کلیدهای Shift یا نماد"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -81,25 +83,36 @@
     <string name="gesture_floating_preview_text" msgid="4443240334739381053">"پیش‌نمایش متحرک پویا"</string>
     <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"مشاهده کلمه پیشنهادی در حین انجام حرکات"</string>
     <string name="gesture_space_aware" msgid="2078291600664682496">"‫ورود عبارت با حرکت اشاره‌ای"</string>
-    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"با سراندن انگشت به کلید فاصله در زمان اشاره‌ها، فاصله را وارد کنید"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"با سراندن انگشت روی کلید فاصله در زمان استفاده از حرکات، فاصله وارد کنید"</string>
     <string name="voice_input" msgid="3583258583521397548">"کلید ورودی صدا"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"هیچ روش ورودی صوتی فعال نشده است. تنظیمات زبان و ورودی را بررسی کنید."</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="language_selection_title" msgid="3666971864764478269">"زبان‌ها"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"راهنما و بازخورد"</string>
+    <string name="select_language" msgid="5709487854987078367">"زبان‌ها"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"برای ذخیره دوباره لمس کنید"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"برای ذخیره اینجا را لمس کنید"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"طرح زمینه صفحه‌کلید"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"جابه‌جایی بین حساب‌ها"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"هیچ حسابی انتخاب نشده است"</string>
+    <string name="account_selected" msgid="2846876462199625974">"در حال حاضر در حال استفاده از <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"تأیید"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"لغو"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"خروج از سیستم"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"انتخاب یک حساب برای استفاده"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگلیسی (بریتانیا)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگلیسی (امریکا)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"اسپانیایی (آمریکا)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"هندی انگلیسی"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"صربی (لاتین)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"انگلیسی (بریتانیا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"انگلیسی (آمریکا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"اسپانیایی (آمریکا) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"هندی انگلیسی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"صربی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سنتی)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سیریلیک)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (لاتین)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (فشرده)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"بدون زبان (حروف الفبا)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"‏حروف الفبا (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"‏حروف الفبا (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"‏حروف الفبا (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"‏حروف الفبا (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"طرح زمینه صفحه کلید"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"سبک‌های ورودی سفارشی"</string>
     <string name="add_style" msgid="6163126614514489951">"افزودن سبک"</string>
     <string name="add" msgid="8299699805688017798">"افزودن"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"این فایل واقعاً برای <xliff:g id="LANGUAGE_NAME">%s</xliff:g> نصب شود؟"</string>
-    <string name="error" msgid="8940763624668513648">"خطایی روی داد"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"تأخیر فشار طولانی کلید"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"اکنون می‌توانید در همه برنامه‌های دلخواه خود با <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">"نمایش نماد برنامه در راه‌انداز"</string>
     <string name="app_name" msgid="6320102637491234792">"ارائه‌دهنده فرهنگ لغت"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ارائه‌دهنده فرهنگ لغت"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"سرویس فرهنگ لغت"</string>
diff --git a/java/res/values-fi/strings-emoji-descriptions.xml b/java/res/values-fi/strings-emoji-descriptions.xml
index ad08bbd..7d6a9f9 100644
--- a/java/res/values-fi/strings-emoji-descriptions.xml
+++ b/java/res/values-fi/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Pikkuleipä"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Suklaapatukka"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Karamelli"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Tikkukaramelli"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Tikkari"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vanukas"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Hunajapurkki"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Kakkuviipale"</string>
diff --git a/java/res/values-fi/strings-talkback-descriptions.xml b/java/res/values-fi/strings-talkback-descriptions.xml
index bec46ca..bd68f4a 100644
--- a/java/res/values-fi/strings-talkback-descriptions.xml
+++ b/java/res/values-fi/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Ei kirjoitettua tekstiä"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> korjaa sanan <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> sanaksi <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> suorittaa automaattisen korjauksen"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ei ehdotusta."</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Tuntematon merkki"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Vaihto"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Lisää symboleita"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Suuraakkonen I ja yläpuolinen piste"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Tuntematon symboli"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Tuntematon emoji-merkki"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Kyllästynyt naama"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Nolostunut naama"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Naama aurinkolasit silmillä"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Yllättynyt naama"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Naama ja pusuhuulet"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Kurttuotsainen naama"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Vaihtoehtoisia merkkejä on saatavilla"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Vaihtoehtoiset merkit hylättiin"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Vaihtoehtoisia ehdotuksia on saatavilla"</string>
diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml
index 5f2ef6a..66cc4b2 100644
--- a/java/res/values-fi/strings.xml
+++ b/java/res/values-fi/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Käytä värinää näppäimiä painettaessa"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Toista ääni näppäimiä painettaessa"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Ponnahdusikkuna painalluksella"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Syöttöasetukset"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Ulkonäkö"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Kieliasetukset"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Piirtokirjoitusasetukset"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Asetukset"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Tilit ja tietosuoja"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Ulkoasu ja asettelut"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Piirtokirjoitus"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Tekstin korjaus"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Lisäasetukset"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Teema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Ota jaettu näppäimistö käyttöön"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-näppäimistön synkronointi"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synkronointi on käytössä."</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synkronoi oma sanakirjasi eri laitteiden välillä."</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synkronoi"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Poista tiedot pilvestä"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Poistaa synkronoidut tietosi Googlen palveluista"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Synkronoidut tiedot poistetaan pilvestä. Oletko varma?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Poista"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Peruuta"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Oma sanakirjasi synkronoidaan ja varmuuskopiodaan Googlen palvelimille. Sanojen yleisyyttä koskevia tilastotietoja voidaan kerätä tuotteidemme parantamiseksi. Tietojen keräämisessä ja käytössä noudatetaan "<a href="https://www.google.com/policies/privacy">"Googlen tietosuojakäytäntöä"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Ota tämä ominaisuus käyttöön lisäämällä Google-tili laitteeseen."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Käytä toista syöttötapaa"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kielenvaihtonäppäin kattaa myös muut syöttötavat"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Kielenvaihtonäppäin"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Näytä, kun käytössä on useita syöttökieliä"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Näytä liu\'utuksen tilaosoitin"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Näytä visuaalinen vihje Vaihto- tai Symbol-näppäim. liu\'uttam."</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Näppäimen hylkäysviive"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Ei viivettä"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Oletus"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Pääsanakirja"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Näytä korjausehdotukset"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Näytä sanaehdotukset kirjoitettaessa"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Näytä aina"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Näytä pystysuunnassa"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Piilota aina"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Estä loukkaavat sanat"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Älä ehdota mahd. loukkaavia sanoja"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autom. korjaus"</string>
@@ -76,24 +84,35 @@
     <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Näytä ehdotettu sana piirron aikana"</string>
     <string name="gesture_space_aware" msgid="2078291600664682496">"Ilmausele"</string>
     <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Lisää välilyöntejä eleiden aikana liukumalla välilyöntinäppäim."</string>
-    <string name="voice_input" msgid="3583258583521397548">"Äänisyöteavain"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Äänisyötenäppäin"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Äänen syöttötapoja ei ole otettu käyttöön. Tarkista Kieli ja syöttötapa -asetukset."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Lähetä palautetta"</string>
-    <string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Kielet"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ohje ja palaute"</string>
+    <string name="select_language" msgid="5709487854987078367">"Kielet"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tallenna koskettamalla uudelleen"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tallenna koskettamalla tätä"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Näppäimistöteema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Vaihda tiliä"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Tilejä ei ole valittu"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Tällä hetkellä käytetään tiliä <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Peruuta"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Kirjaudu ulos"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Valitse käytettävä tili"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"englanti (Iso-Britannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"englanti (Yhdysvallat)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"espanja (Yhdysvallat)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindienglanti"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"serbialainen (latinal.)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"englanti (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"englanti (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espanja (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindienglanti (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"serbialainen (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (perinteinen)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillinen)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinalainen)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tiivis)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ei kieltä (aakkoset)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Aakkoset (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Aakkoset (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Aakkoset (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Näppäimistöteema"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Valkoinen"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Sininen"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Tumma"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Vaalea"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Muokatut syöttötyylit"</string>
     <string name="add_style" msgid="6163126614514489951">"Lisää tyyli"</string>
     <string name="add" msgid="8299699805688017798">"Lisää"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Ota käyttöön"</string>
     <string name="not_now" msgid="6172462888202790482">"Ei nyt"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Syöttötyyli on jo olemassa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Pitkän painalluksen viive"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Painalluksen värinän kesto"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Näppäinpainalluksen äänenvoim."</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lue ulkoista sanakirjatiedostoa"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Lataukset-kansiossa ei ole sanakirjatiedostoja"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Valitse asennettava sanakirjatiedosto"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Haluatko asentaa tämän tiedoston kielelle <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Tapahtui virhe"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Pitkän painalluksen viive"</string>
     <string name="button_default" msgid="3988017840431881491">"Oletusarvot"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Tervetuloa käyttämään sovellusta <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"ja piirtokirjoitus"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nyt voit kirjoittaa kaikissa lempisovelluksissasi sovelluksen <xliff:g id="APPLICATION_NAME">%s</xliff:g> avulla."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Määritä lisää kieliä"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Valmis"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Näytä sovelluskuvake"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Näytä sovelluskuvake käynnistysohjelmassa."</string>
     <string name="app_name" msgid="6320102637491234792">"Sanakirjan tarjoaja"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Sanakirjan tarjoaja"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Sanakirjapalvelu"</string>
@@ -170,9 +178,9 @@
     <string name="install_dict" msgid="180852772562189365">"Asenna"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"Peruuta"</string>
     <string name="delete_dict" msgid="756853268088330054">"Poista"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Laitteesi käyttökielelle on saatavilla sanakirja.&lt;br/&gt; Suosittelemme <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>-sanakirjan &lt;b&gt;lataamista&lt;/b&gt;, sillä se helpottaa laitteella kirjoittamista.&lt;br/&gt; &lt;br/&gt; Lataus kestää useimmiten muutaman minuutin 3G-yhteydellä. Latauksesta saatetaan periä maksu, ellei käytössäsi ole &lt;b&gt;rajoittamatonta tiedonsiirtopakettia&lt;/b&gt;.&lt;br/&gt; Jos et ole varma tiedonsiirtosopimuksesi tyypistä, etsi käyttöösi wifi-yhteys, niin lataus alkaa automaattisesti.&lt;br/&gt; &lt;br/&gt; Vinkki: voit ladata ja poistaa sanakirjoja mobiililaitteesi &lt;b&gt;Asetukset&lt;/b&gt;-valikon &lt;b&gt;Kieli ja syöttötapa&lt;/b&gt; -osiossa."</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Laitteesi käyttökielelle on saatavilla sanakirja.&lt;br/&gt; Suosittelemme <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>-sanakirjan &lt;b&gt;lataamista&lt;/b&gt;, sillä se helpottaa laitteella kirjoittamista.&lt;br/&gt; &lt;br/&gt; Lataus kestää useimmiten muutaman minuutin 3G-yhteydellä. Latauksesta saatetaan periä maksu, ellei käytössäsi ole &lt;b&gt;rajoittamatonta tiedonsiirtopakettia&lt;/b&gt;.&lt;br/&gt; Jos et ole varma tiedonsiirtosopimuksesi tyypistä, etsi käyttöösi Wi-Fi-yhteys, niin lataus alkaa automaattisesti.&lt;br/&gt; &lt;br/&gt; Vinkki: voit ladata ja poistaa sanakirjoja mobiililaitteesi &lt;b&gt;Asetukset&lt;/b&gt;-valikon &lt;b&gt;Kieli ja syöttötapa&lt;/b&gt; -osiossa."</string>
     <string name="download_over_metered" msgid="1643065851159409546">"Lataa nyt (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> Mt)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Lataa wifi-yhteydellä"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Lataa Wi-Fi-yhteydellä"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"Sanakirja on saatavilla kielelle <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"Paina tätä, jos haluat tarkastella kohdetta ja ladata sen"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Ladataan: kielen <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> ehdotukset ovat pian käytettävissä."</string>
diff --git a/java/res/values-fr-rCA/strings-emoji-descriptions.xml b/java/res/values-fr-rCA/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..e2337f6
--- /dev/null
+++ b/java/res/values-fr-rCA/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Signe de droit d\'auteur"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Signe de marque déposée"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Double point d\'exclamation"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Point d\'interrogation et d\'exclamation"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Signe de marque de commerce"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Source d\'information"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Double flèche horizontale"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Double flèche verticale"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Flèche nord-ouest"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Flèche nord-est"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Flèche sud-est"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Flèche sud-ouest"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Flèche courbe vers la gauche"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Flèche courbe vers la droite"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Montre"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Sablier"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Deux triangles noirs pointant vers la droite"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Deux triangles noirs pointant vers la gauche"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Deux triangles noirs pointant vers le haut"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Deux triangles noirs pointant vers le bas"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Réveil"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Sablier avec du sable qui coule"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"M majuscule encerclé"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Petit carré noir"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Petit carré blanc"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triangle noir pointant vers la droite"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triangle noir pointant vers la gauche"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Carré moyen blanc"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Carré moyen noir"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Carré blanc moyennement petit"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Carré noir moyennement petit"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Soleil noir avec des rayons"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nuage"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Téléphone noir"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Urne avec case cochée"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Parapluie avec gouttes de pluie"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Boisson chaude"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Index blanc pointant vers le haut"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Visage souriant blanc"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Bélier"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taureau"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gémeaux"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lion"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Vierge"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Balance"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittaire"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorne"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Verseau"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Poisson"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Couleur de carte pique noir"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Couleur de carte trèfle noir"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Couleur de carte cœur noir"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Couleur de carte carreau noir"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Sources thermales"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Symbole noir universel du recyclage"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Symbole de fauteuil roulant"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ancre marine"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Signal d\'avertissement"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Signal de haute tension"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Cercle moyen blanc"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Cercle moyen noir"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Ballon de soccer"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Bonhomme de neige sans neige"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Soleil derrière un nuage"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Serpentaire"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Interdiction d\'entrer"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Église"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontaine"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Drapeau dans un trou"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Bateau à voile"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tente"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Pompe à carburant"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Ciseaux noirs"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Coche blanche en gras"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avion"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Enveloppe"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Poing levé"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Main levée"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Signe de la victoire"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Crayon"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Plume de stylo noire"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Coche noire en gras"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Signe de multiplication en gras"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Plusieurs étincelles"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Astérisque à huit branches"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Étoile noire à huit branches"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Flocon de neige"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Étincelle"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Croix"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Croix en négatif dans un carré"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Point d\'interrogation noir décoratif"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Point d\'interrogation blanc décoratif"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Point d\'exclamation blanc décoratif"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Symbole point d\'exclamation en gras"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Cœur noir en gras"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signe plus en gras"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signe moins en gras"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signe diviser en gras"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Flèche noire vers la droite"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Boucle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Double boucle"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Flèche pointant vers la droite, puis recourbée vers le haut"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Flèche pointant vers la droite, puis recourbée vers le bas"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Flèche noire vers la gauche"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Flèche noire vers le haut"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Flèche noire vers le bas"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Grand carré noir"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Grand carré blanc"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Étoile moyenne blanche"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Grand cercle en gras"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Trait d\'union ondulé"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Symbole de début d\'une chanson en japonais"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Idéogramme « Félicitations » dans un cercle"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Idéogramme « Secret » dans un cercle"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Tuile Mahjong de dragon rouge"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Carte de joker noir"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Groupe sanguin A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Groupe sanguin B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Groupe sanguin O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Stationnement"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Groupe sanguin AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Icône de Craiglist dans un carré"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Icone Cool dans un carré"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Icône Free dans un carré"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Icône ID dans un carré"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Icône New dans un carré"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Icône NG dans un carré"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Icône OK dans un carré"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Icône SOS dans un carré"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Icône UP! dans un carré"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Icône vs dans un carré"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Icône « Ici » en katakana dans un carré"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Icône « Service » en katakana dans un carré"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Idéogramme « Gratuit » dans un carré"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Idéogramme « Siège réservé » dans un carré"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Idéogramme « Interdiction » dans un carré"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Idéogramme « Vide » dans un carré"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Idéogramme « Acceptance » dans un carré"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Idéogramme « Complet » dans un carré"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Idéogramme « Payé » dans un carré"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Idéogramme « Mensuel » dans un carré"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Idéogramme « Application » dans un carré"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Idéogramme « Rabais » dans un carré"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Idéogramme « Affaires » dans un carré"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Idéogramme « Avantage » dans un cercle"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Idéogramme « Accepter » dans un carré"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Brouillard"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Parapluie fermé"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Nuit étoilée"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Lever de soleil sur la montagne"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Lever de soleil"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Paysage urbain au crépuscule"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Coucher de soleil derrière des immeubles"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arc-en-ciel"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Pont de nuit"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vague"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Voie lactée"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globe terrestre Europe-Afrique"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globe terrestre Amériques"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globe terrestre Asie-Australie"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globe avec méridiens"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbole de nouvelle lune"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbole de premier croissant de lune"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbole de premier quartier de lune"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbole de lune gibbeuse ascendante"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbole de pleine lune"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbole de lune gibbeuse descendante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbole de dernier quartier de lune"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbole de dernier croissant de lune"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Croissant de lune"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nouvelle lune avec un visage"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Premier quartier de lune avec un visage"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Dernier quartier de lune avec un visage"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Pleine lune avec un visage"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Soleil avec un visage"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Étoile brillante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Étoile filante"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Marron"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Jeune plant"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Arbre à feuilles persistantes"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Arbre à feuilles décidues"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmier"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipe"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Fleur de cerisier"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Tournesol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Fleur"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Épi de maïs"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Épi de riz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herbe"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trèfle à quatre feuilles"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Feuille d\'érable"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Feuille morte"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Feuille emportée par le vent"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Champignon"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Raisin"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Melon d\'eau"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citron"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Jaune banane"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Pomme rouge"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Pomme verte"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Poire"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pêche"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cerises"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Fraise"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Tranche de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Viande avec os"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Cuisse de volaille"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galette de riz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Boulette de riz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Bol de riz"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Riz et curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Bol chaud"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pain"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Patate douce rôtie"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Crevettes frites"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Gâteau de poisson avec motif de tourbillon"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Crème glacée molle"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Glace pilée"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Crème glacée"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Beigne"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biscuit"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barre de chocolat"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bonbon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Sucette"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Crème anglaise"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Pot de miel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Sablé"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Pot de nourriture"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Cuisine"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Fourchette et couteau"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tasse de thé sans poignée"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Bouteille de saké et gobelet"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Verre de vin"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Verre à cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Boisson tropicale"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Chope de bière"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Chopes de bière qui trinquent"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberon"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Ruban"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Cadeau emballé"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Gâteau d\'anniversaire"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Citrouille illuminée"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Sapin de Noël"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Père Noël"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Feux d\'artifice"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Cierge merveilleux"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Cotillons"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Boule de confettis"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Arbre Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Drapeaux croisés"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Bambou décoratif"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Poupées japonaises"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Bannière avec motif de carpe"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Carillon"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Cérémonie de la pleine lune"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Cartable d\'école"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Chapeau de remise de diplôme"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cheval de manège"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Grande roue"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Montagnes russes"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Canne à pêche et poisson"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microphone"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Caméra de cinéma"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinéma"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Écouteurs"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palette de peintre"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Haut-de-forme"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Chapiteau de cirque"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Billet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Clap de cinéma"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Arts du spectacle"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Jeu vidéo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Flèche dans le mille"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Machine à sous"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dé à jouer"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Quilles"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Cartes à jouer japonaises"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Note de musique"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Plusieurs notes de musique"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitare"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Clavier de piano"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompette"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violon"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partition de musique"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Maillot de course avec bande en diagonale"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raquette et balle de tennis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski et chaussure de ski"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Ballon et panier de basketball"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Drapeau à carreaux"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Surfeur des neiges"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Coureur à pied"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfeur"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trophée"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Course hippique"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Football américain"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ballon de rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nageur"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Maison"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Maison avec jardin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Bâtiment de bureaux"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Bureau de poste japonais"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Bureau de poste européen"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hôpital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banque"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Guichet automatique"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hôtel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hôtel de l\'amour"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Dépanneur"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"École"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Grand magasin"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Usine"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lanterne japonaise"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Château japonais"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Château européen"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rat"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Souris"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Bœuf"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Buffle"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vache"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Léopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Lapin"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Chat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodile"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Baleine"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Escargot"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serpent"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cheval"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Bélier"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Chèvre"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Mouton"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Singe"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Coq"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Poulet"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Chien"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cochon"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Sanglier"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Éléphant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pieuvre"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Coquille spiralée"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insecte"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Fourmi"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abeille"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Coccinelle"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Poisson"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Poisson tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Poisson-globe"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tortue"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Éclosion de poussin"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Poussin"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Poussin de face"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Oiseau"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Manchot"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromadaire"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Chameau"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dauphin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Tête de souris"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Tête de vache"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tête de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Tête de lapin"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Tête de chat"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Tête de dragon"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Baleine soufflant"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Tête de cheval"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Tête de singe"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Tête de chien"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Tête de cochon"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Tête de grenouille"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Visage de hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Tête de loup"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Tête d\'ours"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Tête de panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Groin"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Empreintes de pattes"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Yeux"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Oreille"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nez"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Bouche"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Langue"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Main blanche avec index pointant vers le haut"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Main blanche avec index pointant vers le bas"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Main blanche avec index pointant vers la gauche"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Main blanche avec index pointant vers la droite"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Main en forme de poing"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Main qui fait signe"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Main qui fait le signe OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Pouce vers le haut"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Pouce vers le bas"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Mains qui applaudissent"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Mains ouvertes"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Couronne"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Chapeau de femme"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Lunettes"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Cravate"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Robe"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Vêtements de femme"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Sacoche"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Sac à main"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pochette"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Chaussure d\'homme"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Chaussures de sport"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Chaussure à talons hauts"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandales de femme"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Bottes de femme"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Empreintes de pas"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhouette de buste"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhouettes de deux bustes"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Garçon"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Fille"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Homme"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Femme"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Famille"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Homme et femme qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Deux hommes qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Deux femmes qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policier"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Femme avec oreilles de lapin"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Mariée avec voile"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Personne aux cheveux blonds"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Homme portant un gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Homme portant un turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Homme âgé"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Femme âgée"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bébé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Ouvrier du bâtiment"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesse"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogre japonais"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Gobelin japonais"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantôme"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Chérubin"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstre extraterrestre"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Lutin"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Crâne"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Personne à un comptoir de renseignements"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardien"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danseur"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rouge à lèvres"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Vernis à ongles"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Massage facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Coupe de cheveux"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Enseigne de barbier"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Seringue"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilule"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Trace de baiser"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Lettre d\'amour"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Bague"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Pierre précieuse"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bisou"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Couple avec un cœur"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Mariage"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Cœur qui bat"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Cœur brisé"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Deux cœurs"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Cœur étincelant"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Cœur qui grossit"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Cœur avec une flèche"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Cœur bleu"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Cœur vert"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Cœur jaune"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Cœur violet"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Cœur avec un ruban"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Ronde de cœurs"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Décoration à motif de cœur"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamant avec un point à l\'intérieur"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Ampoule électrique"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbole de la colère"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bombe"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbole du sommeil"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbole d\'une collision"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbole de transpiration profuse"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Goutte d\'eau"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbole de la vitesse"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Tas de caca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Biceps contracté"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbole de l\'étourdissement"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bulle de discours"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bulle de pensée"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Fleur blanche"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbole de cent points"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Sac d\'argent"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Conversion de devises"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Symbole du dollar en gras"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Carte de crédit"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billet avec symbole du yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billets de banque avec signe de dollar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billet avec symbole de l\'euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billet avec symbole de la livre sterling"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Argent avec des ailes"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Graphique avec courbe croissante et symbole du yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Siège"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Ordinateur personnel"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Mallette"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisque"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquette"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disque optique"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Dossier de fichiers"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Dossier ouvert"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Page que l\'on tourne"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Page recto"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendrier"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendrier à effeuiller"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Classeur à fiches"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Graphique avec courbe croissante"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Graphique avec courbe décroissante"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Histogramme"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Presse-papiers"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Punaise"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Punaise ronde"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Trombone"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Règle"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Équerre"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Languettes marque-pages"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Grand livre"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Bloc-notes"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Cahier avec couverture décorative"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Livre fermé"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Livre ouvert"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Livre vert"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Livre bleu"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Livre orange"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Livres"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Badge de nom"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Parchemin"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Mémo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Combiné de téléphone"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Téléavertisseur"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Télécopieur"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antenne satellite"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Haut-parleur pour s\'adresser au public"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Mégaphone d\'encouragement"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Bac de départ du courrier"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Bac d\'arrivée du courrier"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Colis"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Symbole de courriel"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Enveloppe de nouveau message"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Enveloppe surmontée d\'une flèche vers le bas"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Boîte aux lettres fermée avec drapeau baissé"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Boîte aux lettres fermée avec drapeau levé"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Boîte aux lettres ouverte avec drapeau levé"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Boîte aux lettres ouverte avec drapeau baissé"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Boîte aux lettres"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Corne des services postaux"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Journal"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Téléphone cellulaire"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Téléphone mobile avec flèche orientée vers la droite sur la gauche"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Mode vibreur"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Téléphone cellulaire éteint"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Pas de téléphone cellulaire"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenne avec barres"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Appareil photo"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Caméscope"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Télévision"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Cassette vidéo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Deux flèches croisées vers la droite"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Cercle formé par deux flèches horizontales tournant dans le sens des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Cercle formé par deux flèches horizontales tournant dans le sens des aiguilles d\'une montre, avec chiffre un dans une pastille"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Cercle formé par deux flèches verticales tournant dans le sens des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Cercle formé par deux flèches verticales tournant dans le sens inverse des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbole de faible luminosité"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbole de forte luminosité"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Haut-parleur barré"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Haut-parleur"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Haut-parleur avec une onde sonore"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Haut-parleur avec trois ondes sonores"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Pile"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Prise électrique"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Loupe orientée vers la gauche"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Loupe orientée vers la droite"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Cadenas avec stylo-plume"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Cadenas fermé avec clé"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Clé"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Cadenas"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Serrure ouverte"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Cloche"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Cloche barrée"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Favoris"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Symbole de lien"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Bouton radio"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"« Back » surmonté d\'une flèche vers la gauche"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"« End » surmonté d\'une flèche vers la gauche"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"« On » avec un point d\'exclamation surmonté d\'une flèche vers la gauche et la droite"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"« Soon » surmonté d\'une flèche vers la droite"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"« Top » surmonté d\'une flèche vers le haut"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbole d\'interdiction aux moins de 18 ans"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Touche avec le nombre 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Symbole d\'entrée pour les majuscules latines"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Symbole d\'entrée pour les minuscules latines"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Symbole d\'entrée pour les chiffres"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Symbole d\'entrée pour les symboles"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Symbole d\'entrée pour les lettres latines"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Flamme"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Lampe de poche électrique"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Clé anglaise"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Marteau"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Écrou et boulon"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Couteau hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistolet"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscope"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Télescope"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Boule de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Étoile à six branches avec point au centre"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Symbole japonais pour « débutant »"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblème à trident"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Bouton carré noir"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Bouton carré blanc"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Grand cercle rouge"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Grand cercle bleu"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Grand losange orange"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Grand losange bleu"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Petit losange orange"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Petit losange bleu"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triangle rouge pointant vers le haut"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triangle rouge pointant vers le bas"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Petit triangle rouge pointant vers le haut"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Petit triangle rouge pointant vers le bas"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Horloge affichant 1 h 00"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Horloge affichant 2 h 00"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Horloge affichant 3 h 00"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Horloge affichant 4 h 00"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Horloge affichant 5 h 00"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Horloge affichant 6 h 00"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Horloge affichant 7 h 00"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Horloge affichant 8 h 00"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Horloge affichant 9 h 00"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Horloge affichant 10 h 00"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Horloge affichant 11 h 00"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Horloge affichant 12 h 00"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Horloge affichant 1 h 30"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Horloge affichant 2 h 30"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Horloge affichant 3 h 30"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Horloge affichant 4 h 30"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Horloge affichant 5 h 30"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Horloge affichant 6 h 30"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Horloge affichant 7 h 30"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Horloge affichant 8 h 30"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Horloge affichant 9 h 30"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Horloge affichant 10 h 30"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Horloge affichant 11 h 30"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Horloge affichant 12 h 30"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mont Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tour de Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statue de la Liberté"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhouette du Japon"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moaï"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Visage souriant à pleines dents"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Visage grimaçant avec les yeux souriants"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Visage avec des larmes de joie"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Visage souriant avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Visage souriant avec la bouche ouverte et des yeux rieurs"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Visage souriant avec la bouche ouverte et des sueurs froides"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Visage souriant avec la bouche ouverte et les yeux bien fermés"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Visage souriant avec un halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Visage souriant avec des cornes"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Visage faisant un clin d\'œil"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Visage souriant avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Visage savourant un plat délicieux"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Visage soulagé"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Visage souriant avec des yeux en forme de cœur"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Visage souriant avec des lunettes de soleil"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Visage souriant en coin"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Visage neutre"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Visage sans expression"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Visage pas amusé"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Visage avec des sueurs froides"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Visage pensif"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Visage confus"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Visage déconcerté"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Visage faisant un baiser"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Visage envoyant un baiser"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Visage faisant un baiser avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Visage faisant un baiser avec les yeux fermés"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Visage tirant la langue"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Visage tirant la langue et faisant un clin d\'œil"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Visage tirant la langue avec les yeux bien fermés"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Visage déçu"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Visage inquiet"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Visage en colère"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Visage qui boude"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Visage qui pleure"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Visage persévérant"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Visage avec un air de triomphe"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Visage déçu, mais soulagé"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Visage fronçant les sourcils avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Visage angoissé"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Visage apeuré"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Visage fatigué"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Visage endormi"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Visage épuisé"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Visage grimaçant"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Visage pleurant à chaudes larmes"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Visage avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Visage calmé"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Visage avec la bouche ouverte et des sueurs froides"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Visage qui hurle de peur"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Visage étonné"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Visage tout rouge"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Visage endormi"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Visage pris de vertige"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Visage sans bouche"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Visage avec un masque médical"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Tête de chat qui sourit avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Tête de chat avec des larmes de joie"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Tête de chat qui sourit avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Tête de chat qui sourit avec des yeux en forme de cœur"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Visage de chat avec sourire ironique"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Tête de chat faisant un baiser avec les yeux fermés"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Tête de chat qui boude"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Tête de chat qui pleure"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Tête de chat fatigué"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Visage faisant signe que rien ne va"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Visage faisant signe que tout va bien"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Personne faisant la révérence"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Singe qui fait semblant de n\'avoir rien vu"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Singe qui fait semblant de n\'avoir rien entendu"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Singe qui fait semblant de n\'avoir rien dit"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Personne heureuse qui lève une main"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Personne qui lève les deux bras en signe de victoire"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Personne fronçant les sourcils"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Personne avec visage qui boude"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Personne les mains jointes"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Fusée"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Hélicoptère"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotive à vapeur"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Wagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Train à grande vitesse"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Train à grande vitesse avec nez en pointe"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Train"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Métro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Train léger"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Gare"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramway"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Voiture de tramway"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobus venant de face"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolley"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Arrêt d\'autobus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camion d\'incendie"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Voiture de police"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Voiture de police venant en sens inverse"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi venant en sens inverse"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobile"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automobile venant en sens inverse"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Véhicule récréatif"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camion de livraison"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Semi-remorque"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tracteur"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Chemin de fer de montagne"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Train suspendu"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Téléphérique de montagne"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Téléphérique"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Bateau"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Chaloupe"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Hors-bord"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Feu de circulation horizontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Feu de circulation vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Signe de travaux routiers"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Gyrophare de voiture de police"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Drapeau triangulaire sur un poteau"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porte"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Panneau d\'interdiction d\'entrée"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Symbole de permission de fumer"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Symbole d\'interdiction de fumer"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Déposez les déchets dans son symbole de lieu"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Ne salissez pas le symbole"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbole d\'eau potable"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbole d\'eau non potable"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Vélo"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Vélos interdits"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cycliste"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Cycliste de montagne"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Piéton"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Piétons interdits"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Passage d\'enfants"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbole d\'homme"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbole de femme"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Salle de bain"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Symbole de bébé"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilettes"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Salle de bain"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Douche"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bain"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Baignoire"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Contrôle de passeport"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Douane"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Zone de récupération des bagages"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Consigne à bagages"</string>
+</resources>
diff --git a/java/res/values-fr-rCA/strings-talkback-descriptions.xml b/java/res/values-fr-rCA/strings-talkback-descriptions.xml
index df644c0..368de9f 100644
--- a/java/res/values-fr-rCA/strings-talkback-descriptions.xml
+++ b/java/res/values-fr-rCA/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Aucun texte entré"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"La touche <xliff:g id="KEY_NAME">%1$s</xliff:g> permet de remplacer <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> par <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"La touche <xliff:g id="KEY_NAME">%1$s</xliff:g> permet d\'effectuer une correction automatique"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Aucune suggestion"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caractère inconnu"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Majuscule"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Autres symboles"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majuscule, point en chef"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Symbole inconnu"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji inconnu"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ennuyé"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarrassé"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Lunettes de soleil"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surpris"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bisou"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Sourcils froncés"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Des caractères supplémentaires sont proposés"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Les caractères supplémentaires sont ignorés"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Des suggestions supplémentaires sont proposées"</string>
diff --git a/java/res/values-fr-rCA/strings.xml b/java/res/values-fr-rCA/strings.xml
index fd34ba9..f0cd0ed 100644
--- a/java/res/values-fr-rCA/strings.xml
+++ b/java/res/values-fr-rCA/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Son à chaque touche"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Agrandir les caractères"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Préférences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Comptes et confidentialité"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Apparence et dispositions"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Entrée gestuelle"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Correction du texte"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avancés"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Thème"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Activer le clavier en deux parties"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synchronisation du clavier Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"La synchronisation est activée"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synchronisez votre dictionnaire personnel sur plusieurs appareils"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synchroniser maintenant"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Supprimer les données du nuage"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Supprime vos données synchronisées de Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Vos données synchronisées seront suppr. du nuage. Êtes-vous sûr?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Supprimer"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Annuler"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Votre dictionnaire personnel sera synchronisé et sauvegardé sur les serveurs de Google. Des statistiques concernant la fréquence des mots peuvent être recueillies pour nous aider à améliorer nos produits. La collecte et l\'utilisation de toutes les données sont effectuées conformément à la "<a href="https://www.google.com/policies/privacy">"politique de confidentialité de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Ajoutez un compte Google à cet appareil pour activer la fonction."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Autres modes de saisie"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La touche de sélection de langue couvre d\'autres modes de saisie"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Touche de sélection de langue"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Afficher lorsque plusieurs langues de saisie sont activées"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Aff. indicateur saisie gestuelle"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Aff. un repère visuel si l\'utilisateur appuie sur Maj ou Symboles"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Aucun délai"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dictionnaire principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Suggestions de correction"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Afficher les suggestions de terme lors de la saisie"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Toujours afficher"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Afficher en mode Portrait"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Toujours masquer"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquer les termes choquants"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Pas de termes potentiellement choquants"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correction auto"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Aucun mode d\'entrée vocale n\'a été activé. Vérifiez les paramètres de langues et d\'entrée de texte."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
-    <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Langues"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Aide et commentaires"</string>
+    <string name="select_language" msgid="5709487854987078367">"Langues"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Touchez ici pour enregistrer le mot dans le dictionnaire"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Changer de compte"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Aucun compte sélectionné"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Vous utilisez actuellement le compte <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Annuler"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Déconnexion"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Sélectionnez le compte à utiliser"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (britannique)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espagnol (États-Unis)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbe (latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"anglais (Royaume-Uni) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"anglais (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espagnol (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbe (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrillique)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Aucune langue (alphabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet latin (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet latin (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alphabet latin (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet latin (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Thème du clavier"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Styles saisie personnalisés"</string>
     <string name="add_style" msgid="6163126614514489951">"Ajouter style"</string>
     <string name="add" msgid="8299699805688017798">"Ajouter"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activer"</string>
     <string name="not_now" msgid="6172462888202790482">"Pas maintenant"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Le style de saisie suivant existe déjà : <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Délai appui prolongé sur touche"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durée vibration press. touche"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume pression de touche"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lire un fichier de dictionnaire externe"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Aucun fichier de dictionnaire dans le dossier \"Téléchargements\""</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Installer ce fichier pour la langue « <xliff:g id="LANGUAGE_NAME">%s</xliff:g> »?"</string>
-    <string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Délai appui prolongé sur touche"</string>
     <string name="button_default" msgid="3988017840431881491">"Par défaut"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Bienvenue dans <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"avec la saisie gestuelle"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>, vous pouvez saisir du texte dans toutes vos applications préférées."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurer des langues supplémentaires"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"OK"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Afficher icône application"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Afficher l\'icône de l\'application dans le lanceur"</string>
     <string name="app_name" msgid="6320102637491234792">"Fournisseur de dictionnaires"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Fournisseur de dictionnaires"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Service de dictionnaires"</string>
diff --git a/java/res/values-fr/strings-emoji-descriptions.xml b/java/res/values-fr/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..1f99ee3
--- /dev/null
+++ b/java/res/values-fr/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Symbole de copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Symbole de marque déposée"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Double point d\'exclamation"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Point d\'exclamation et point d\'interrogation"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Symbole de marque commerciale"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Source d\'informations"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Flèche vers la gauche et la droite"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Flèche vers le haut et le bas"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Flèche en direction du nord-ouest"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Flèche en direction du nord-est"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Flèche en direction du sud-est"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Flèche en direction du sud-ouest"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Flèche courbe vers la gauche"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Flèche courbe vers la droite"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Montre"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Sablier"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Deux triangles noirs pointant vers la droite"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Deux triangles noirs pointant vers la gauche"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Deux triangles noirs pointant vers le haut"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Deux triangles noirs pointant vers le bas"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Réveil"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Sablier avec du sable qui coule"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Lettre majuscule latine m dans un cercle"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Petit carré noir"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Petit carré blanc"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triangle noir pointant vers la droite"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triangle noir pointant vers la gauche"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Carré moyen blanc"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Carré moyen noir"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Carré blanc moyennement petit"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Carré noir moyennement petit"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Soleil noir avec des rayons"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nuage"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Téléphone noir"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Case cochée"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Parapluie avec des gouttes de pluie"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Boisson chaude"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Index blanc pointant vers le haut"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Visage souriant blanc"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Bélier"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taureau"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gémeaux"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lion"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Vierge"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Balance"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittaire"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorne"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Verseau"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Poisson"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Couleur de carte pique noir"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Couleur de carte trèfle noir"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Couleur de carte cœur noir"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Couleur de carte carreau noir"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Sources thermales"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Symbole noir universel du recyclage"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Symbole de fauteuil roulant"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ancre marine"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Signal d\'avertissement"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Signal haute tension"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Cercle moyen blanc"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Cercle moyen noir"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Ballon de foot"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Balle de base-ball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Bonhomme de neige sans neige"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Soleil derrière un nuage"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Serpentaire"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Interdiction d\'entrer"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Église"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontaine"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Drapeau dans un trou"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Bateau à voile"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tente"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Pompe à carburant"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Ciseaux noirs"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Coche blanche en gras"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avion"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Enveloppe"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Poing levé"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Main levée"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Signe de la victoire"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Crayon"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Plume de stylo noire"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Coche noire en gras"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Signe multiplier en gras"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Plusieurs étincelles"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Astérisque à huit branches"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Étoile noire à huit branches"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Flocon de neige"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Étincelle"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Croix"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Croix en négatif dans un carré"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Point d\'interrogation noir décoratif"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Point d\'interrogation blanc décoratif"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Point d\'exclamation blanc décoratif"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Symbole point d\'exclamation en gras"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Cœur noir en gras"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signe plus en gras"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signe moins en gras"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signe diviser en gras"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Flèche noire vers la droite"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Boucle"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Double boucle"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Flèche pointant vers la droite, puis recourbée vers le haut"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Flèche pointant vers la droite, puis recourbée vers le bas"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Flèche noire vers la gauche"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Flèche noire vers le haut"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Flèche noire vers le bas"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Grand carré noir"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Grand carré blanc"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Étoile moyenne blanche"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Grand cercle en gras"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Trait d\'union ondulé"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Symbole de début d\'une chanson en japonais"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Idéogramme \"félicitations\" dans un cercle"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Idéogramme \"secret\" dans un cercle"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Tuile de mah-jong dragon rouge"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Carte à jouer joker noir"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Groupe sanguin A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Groupe sanguin B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Groupe sanguin O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parking"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Groupe sanguin AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"\"CL\" dans un carré"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"\"Cool\" dans un carré"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"\"Free\" dans un carré"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"\"ID\" dans un carré"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"\"New\" dans un carré"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"\"NG\" dans un carré"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"\"OK\" dans un carré"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"\"SOS\" dans un carré"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"\"Up\" dans un carré avec un point d\'exclamation"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"\"Vs\" dans un carré"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"\"Ici\" en katakana dans un carré"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"\"Service\" en katakana dans un carré"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Idéogramme \"gratuit\" dans un carré"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Idéogramme \"siège réservé\" dans un carré"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Idéogramme \"interdiction\" dans un carré"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Idéogramme \"libre\" dans un carré"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Idéogramme \"acceptation\" dans un carré"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Idéogramme \"complet\" dans un carré"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Idéogramme \"payant\" dans un carré"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Idéogramme \"mensuel\" dans un carré"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Idéogramme \"application\" dans un carré"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Idéogramme \"remise\" dans un carré"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Idéogramme \"affaires\" dans un carré"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Idéogramme \"avantage\" dans un cercle"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Idéogramme \"accepter\" dans un cercle"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Brouillard"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Parapluie fermé"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Nuit étoilée"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Lever de soleil sur la montagne"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Lever de soleil"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Paysage urbain au crépuscule"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Coucher de soleil derrière des buildings"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arc-en-ciel"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Pont de nuit"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vague"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Voie lactée"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globe terrestre Europe-Afrique"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globe terrestre Amériques"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globe terrestre Asie-Australie"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globe avec méridiens"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbole nouvelle lune"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbole premier croissant de lune"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbole premier quartier de lune"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbole lune gibbeuse ascendante"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbole pleine lune"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbole lune gibbeuse descendante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbole dernier quartier de lune"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbole dernier croissant de lune"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Croissant de lune"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nouvelle lune avec un visage"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Premier quartier de lune avec un visage"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Dernier quartier de lune avec un visage"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Pleine lune avec un visage"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Soleil avec un visage"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Étoile brillante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Étoile filante"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Marron"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Jeune plant"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Arbre à feuilles persistantes"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Arbre à feuilles caduques"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmier"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipe"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Fleur de cerisier"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Tournesol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Fleur ouverte"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Épi de maïs"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Épi de riz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herbe"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trèfle à quatre feuilles"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Feuille d\'érable"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Feuille morte"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Feuille emportée par le vent"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Champignon"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Raisin"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Pastèque"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citron"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banane"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Pomme rouge"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Pomme verte"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Poire"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pêche"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cerises"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Fraise"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Part de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Viande avec os"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Cuisse de volaille"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galette de riz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Boulette de riz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Bol de riz"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Riz au curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Bol fumant"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghettis"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pain"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Patate douce grillée"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Crevette frite"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Croquette de poisson motif tourbillon"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Glace à l\'italienne"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Glace pilée"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Glace"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Beignet"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biscuit"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barre de chocolat"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bonbon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Sucette"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Crème anglaise"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Pot de miel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Sablé"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Marmite"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Cuisine"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Fourchette et couteau"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tasse de thé sans anse"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Bouteille de saké et gobelet"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Verre de vin"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Boisson tropicale"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Chope de bière"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Chopes de bière qui trinquent"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberon"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Ruban"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Cadeau emballé"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Gâteau d\'anniversaire"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Citrouille éclairée"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Sapin de Noël"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Père Noël"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Feu d\'artifice"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Feu de Bengale"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Cotillons"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Ballon de confettis"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Arbre Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Drapeaux croisés"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Décoration en pin"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Poupées japonaises"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Bannière avec motif de carpe"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Carillon"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Cérémonie de la pleine lune"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Cartable d\'écolier"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Chapeau de remise de diplôme"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cheval de manège"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Grande roue"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Grand huit"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Canne à pêche et poisson"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microphone"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Caméra de cinéma"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinéma"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Casque audio"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palette de peintre"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Haut-de-forme"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Chapiteau de cirque"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Billet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Clap de cinéma"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Arts du spectacle"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Jeu vidéo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Flèche dans le mille"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Machine à sous"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dé à jouer"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Cartes à jouer japonaises"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Note de musique"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Plusieurs notes de musique"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitare"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Clavier de piano"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompette"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violon"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partition de musique"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Maillot de course avec bande en diagonale"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raquette et balle de tennis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski et chaussure de ski"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Ballon de basket et panier"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Drapeau à carreaux"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboardeur"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Coureur à pied"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfeur"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trophée"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Course hippique"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Football américain"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ballon de rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nageur"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Maison"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Maison avec jardin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Bâtiment de bureaux"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Bureau de poste japonais"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Bureau de poste européen"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hôpital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banque"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Distributeur de billets"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hôtel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Supérette"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"École"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Grand magasin"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Usine"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lanterne japonaise"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Château japonais"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Château européen"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rat"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Souris"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Bœuf"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Buffle"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vache"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Léopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Lapin"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Chat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodile"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Baleine"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Escargot"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serpent"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cheval"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Bélier"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Chèvre"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Mouton"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Singe"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Coq"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Poulet"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Chien"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cochon"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Sanglier"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Éléphant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pieuvre"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Coquille spiralée"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insecte"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Fourmi"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abeille"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Coccinelle"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Poisson"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Poisson tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Poisson-globe"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tortue"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Éclosion de poussin"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Poussin"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Poussin de face"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Oiseau"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingouin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromadaire"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Chameau"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dauphin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Tête de souris"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Tête de vache"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tête de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Tête de lapin"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Tête de chat"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Tête de dragon"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Baleine soufflant"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Tête de cheval"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Tête de singe"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Tête de chien"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Tête de cochon"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Tête de grenouille"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Tête de hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Tête de loup"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Tête d\'ours"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Tête de panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Groin"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Empreintes de pattes"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Yeux"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Oreille"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nez"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Bouche"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Langue"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Main blanche avec index pointant vers le haut"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Main blanche avec index pointant vers le bas"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Main blanche avec index pointant vers la gauche"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Main blanche avec index pointant vers la droite"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Main en forme de poing"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Main qui fait signe"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Main qui fait le signe OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Pouce vers le haut"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Pouce vers le bas"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Mains qui applaudissent"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Mains ouvertes"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Couronne"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Chapeau de femme"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Lunettes"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Cravate"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jean"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Robe"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Vêtements de femme"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Porte-monnaie"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Sac à main"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pochette"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Chaussure d\'homme"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Chaussure de sport"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Talon aiguille"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandale de femme"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Bottes de femme"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Empreintes de pas"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhouette de buste"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhouettes de deux bustes"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Garçon"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Fille"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Homme"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Femme"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Famille"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Homme et femme qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Deux hommes qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Deux femmes qui se tiennent la main"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Officier de police"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Femme avec oreilles de lapin"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Mariée avec voile"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Personne aux cheveux blonds"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Homme portant un gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Homme portant un turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Homme âgé"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Femme âgée"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bébé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Ouvrier du bâtiment"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesse"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogre japonais"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Gobelin japonais"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantôme"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Chérubin"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstre extraterrestre"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Lutin"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Crâne"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Personne à un comptoir de renseignements"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardien"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danseur"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rouge à lèvres"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Vernis à ongles"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Massage facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Coupe de cheveux"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Enseigne de barbier"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Seringue"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilule"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Trace de baiser"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Lettre d\'amour"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Bague"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Pierre précieuse"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Baiser"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Couple avec un cœur"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Mariage"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Cœur qui bat"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Cœur brisé"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Deux cœurs"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Cœur étincelant"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Cœur qui grossit"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Cœur avec une flèche"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Cœur bleu"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Cœur vert"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Cœur jaune"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Cœur violet"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Cœur avec un ruban"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Ronde de cœurs"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Décoration motif cœur"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamant avec un point à l\'intérieur"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Ampoule électrique"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbole de la colère"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bombe"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbole du sommeil"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbole d\'une collision"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbole de projection de gouttes de sueur"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Goutte d\'eau"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbole de la vitesse"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Tas de caca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Biceps contracté"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbole de l\'étourdissement"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bulle de discours"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bulle de pensée"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Fleur blanche"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbole cent points"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Sac d\'argent"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Conversion de devises"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Symbole du dollar en gras"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Carte de paiement"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billet avec symbole du yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billet avec symbole du dollar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billet avec symbole de l\'euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billet avec symbole de la livre sterling"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Liasse de billets avec des ailes"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Graphique avec courbe croissante et symbole du yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Siège"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"PC"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Sacoche"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisque"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquette"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disque optique"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Dossier de fichiers"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Dossier ouvert"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Page que l\'on tourne"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Page recto"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendrier"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendrier à effeuiller"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Classeur à fiches"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Graphique avec courbe croissante"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Graphique avec courbe décroissante"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Histogramme"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Presse-papiers"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Punaise"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Punaise ronde"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Trombone"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Règle"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Équerre"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Languettes marque-pages"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Registre"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Cahier"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Cahier avec couverture décorative"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Livre fermé"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Livre ouvert"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Livre vert"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Livre bleu"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Livre orange"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Livres"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Badge nominatif"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Parchemin"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Mémo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Combiné de téléphone"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antenne satellite"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Haut-parleur pour s\'adresser au public"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Mégaphone d\'encouragement"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Bac de départ du courrier"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Bac d\'arrivée du courrier"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Colis"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Symbole e-mail"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Enveloppe de nouveau message"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Enveloppe surmontée d\'une flèche vers le bas"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Boîte aux lettres fermée avec drapeau baissé"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Boîte aux lettres fermée avec drapeau levé"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Boîte aux lettres ouverte avec drapeau levé"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Boîte aux lettres ouverte avec drapeau baissé"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Boîte aux lettres"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Corne des services postaux"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Journal"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Téléphone mobile"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Téléphone mobile avec flèche orientée vers la droite sur la gauche"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Mode vibreur"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Téléphone mobile éteint"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Pas de téléphone mobile"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenne avec barres"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Appareil photo"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Caméscope"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Télévision"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Cassette vidéo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Deux flèches croisées vers la droite"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Cercle formé par deux flèches horizontales tournant dans le sens des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Cercle formé par deux flèches horizontales tournant dans le sens des aiguilles d\'une montre, avec chiffre un dans une pastille"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Cercle formé par deux flèches verticales tournant dans le sens des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Cercle formé par deux flèches verticales tournant dans le sens inverse des aiguilles d\'une montre"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbole de faible luminosité"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbole de forte luminosité"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Haut-parleur barré"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Haut-parleur"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Haut-parleur avec une onde sonore"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Haut-parleur avec trois ondes sonores"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Pile"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Prise électrique"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Loupe orientée vers la gauche"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Loupe orientée vers la droite"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Cadenas avec stylo-plume"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Cadenas fermé avec clé"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Clé"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Cadenas"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Cadenas ouvert"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Cloche"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Cloche barrée"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Marque-page"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Maillons de chaîne"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Bouton radio"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"Back\" surmonté d\'une flèche vers la gauche"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"End\" surmonté d\'une flèche vers la gauche"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"On\" avec un point d\'exclamation surmonté d\'une flèche vers la gauche et la droite"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"Soon\" surmonté d\'une flèche vers la droite"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"Top\" surmonté d\'une flèche vers le haut"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbole d\'interdiction aux moins de 18 ans"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Touche avec le nombre 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Symbole de saisie pour les majuscules latines"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Symbole de saisie pour les minuscules latines"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Symbole de saisie pour les chiffres"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Symbole de saisie pour les symboles"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Symbole de saisie pour les lettres latines"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Feu"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Torche électrique"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Clé anglaise"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Marteau"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Écrou et boulon"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Couteau hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistolet"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscope"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Télescope"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Boule de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Étoile à six branches avec un point au centre"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Symbole japonais pour \"débutant\""</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblème à trident"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Bouton carré noir"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Bouton carré blanc"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Grand cercle rouge"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Grand cercle bleu"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Grand losange orange"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Grand losange bleu"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Petit losange orange"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Petit losange bleu"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triangle rouge pointant vers le haut"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triangle rouge pointant vers le bas"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Petit triangle rouge pointant vers le haut"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Petit triangle rouge pointant vers le bas"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Horloge affichant 1 h 00"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Horloge affichant 2 h 00"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Horloge affichant 3 h 00"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Horloge affichant 4 h 00"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Horloge affichant 5 h 00"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Horloge affichant 6 h 00"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Horloge affichant 7 h 00"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Horloge affichant 8 h 00"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Horloge affichant 9 h 00"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Horloge affichant 10 h 00"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Horloge affichant 11 h 00"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Horloge affichant 12 h 00"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Horloge affichant 1 h 30"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Horloge affichant 2 h 30"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Horloge affichant 3 h 30"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Horloge affichant 4 h 30"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Horloge affichant 5 h 30"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Horloge affichant 6 h 30"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Horloge affichant 7 h 30"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Horloge affichant 8 h 30"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Horloge affichant 9 h 30"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Horloge affichant 10 h 30"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Horloge affichant 11 h 30"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Horloge affichant 12 h 30"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mont Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tour de Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statut de la Liberté"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhouette du Japon"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moaï"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Visage souriant à pleines dents"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Visage souriant à pleines dents avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Visage avec des larmes de joie"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Visage souriant avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Visage souriant avec la bouche ouverte et des yeux rieurs"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Visage souriant avec la bouche ouverte et des sueurs froides"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Visage souriant avec la bouche ouverte et les yeux bien fermés"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Visage souriant avec un halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Visage souriant avec des cornes"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Visage faisant un clin d\'œil"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Visage souriant avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Visage savourant un plat délicieux"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Visage soulagé"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Visage souriant avec des yeux en forme de cœur"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Visage souriant avec des lunettes de soleil"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Visage souriant en coin"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Visage neutre"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Visage sans expression"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Visage pas amusé"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Visage avec des sueurs froides"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Visage pensif"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Visage confus"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Visage déconcerté"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Visage faisant un baiser"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Visage envoyant un baiser"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Visage faisant un baiser avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Visage faisant un baiser avec les yeux fermés"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Visage tirant la langue"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Visage tirant la langue et faisant un clin d\'œil"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Visage tirant la langue avec les yeux bien fermés"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Visage déçu"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Visage inquiet"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Visage en colère"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Visage qui boude"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Visage qui pleure"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Visage persévérant"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Visage avec un air de triomphe"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Visage déçu, mais soulagé"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Visage fronçant les sourcils avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Visage anxieux"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Visage apeuré"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Visage fatigué"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Visage assoupi"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Visage épuisé"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Visage grimaçant"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Visage pleurant à chaudes larmes"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Visage avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Visage calmé"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Visage avec la bouche ouverte et des sueurs froides"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Visage criant de peur"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Visage étonné"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Visage tout rouge"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Visage endormi"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Visage pris de vertige"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Visage sans bouche"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Visage avec un masque médical"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Tête de chat qui sourit avec des yeux rieurs"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Tête de chat avec des larmes de joie"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Tête de chat qui sourit avec la bouche ouverte"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Tête de chat qui sourit avec des yeux en forme de cœur"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Tête de chat avec un sourire narquois"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Tête de chat faisant un baiser avec les yeux fermés"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Tête de chat qui boude"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Tête de chat qui pleure"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Tête de chat fatigué"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Visage faisant signe que rien ne va"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Visage faisant signe que tout va bien"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Personne faisant la révérence"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Singe qui fait semblant de n\'avoir rien vu"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Singe qui fait semblant de n\'avoir rien entendu"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Singe qui fait semblant de n\'avoir rien dit"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Personne heureuse qui lève une main"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Personne qui lève les deux bras en signe de victoire"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Personne fronçant les sourcils"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Personne qui boude"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Personne avec les mains croisées"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Fusée"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Hélicoptère"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotive à vapeur"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Wagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Train à grande vitesse"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Train à grande vitesse avec nez arrondi"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Train"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Métro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Train léger"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Gare"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramway"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Voiture de tramway"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Bus venant de face"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolley"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Arrêt de bus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camion de pompiers"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Voiture de police"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Voiture de police venant de face"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi venant de face"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobile"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automobile venant de face"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Camping-car"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camion de livraison"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camion remorque"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tracteur"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Train de montagne"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Train suspendu"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Téléphérique"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Tramway aérien"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Bateau"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Barque"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Hors-bord"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Feu de circulation horizontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Feu de circulation vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Panneau de chantier"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Gyrophare de voiture de police"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Drapeau triangulaire sur un poteau"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porte"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Panneau d\'interdiction d\'entrée"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Symbole \"zone fumeurs\""</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Symbole \"Interdiction de fumer\""</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Symbole \"jeter les ordures à la poubelle\""</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Symbole \"ne pas jeter d\'ordures\""</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbole \"eau potable\""</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbole \"eau non potable\""</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Vélo"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Interdit aux vélos"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cycliste"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"VTTiste"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Piéton"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Interdit aux piétons"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Enfants qui traversent"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbole \"homme\""</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbole \"femme\""</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toilettes"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Symbole \"bébé\""</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Siège de toilette"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Douche"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bain"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Baignoire"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Contrôle des passeports"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Douane"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Zone de récupération des bagages"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Consigne à bagages"</string>
+</resources>
diff --git a/java/res/values-fr/strings-talkback-descriptions.xml b/java/res/values-fr/strings-talkback-descriptions.xml
index 7ae2056..bda0595 100644
--- a/java/res/values-fr/strings-talkback-descriptions.xml
+++ b/java/res/values-fr/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Aucun texte saisi"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"La touche <xliff:g id="KEY_NAME">%1$s</xliff:g> permet de remplacer \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" par \"<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>\"."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"La touche <xliff:g id="KEY_NAME">%1$s</xliff:g> permet d\'effectuer une correction automatique."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Aucune suggestion"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caractère inconnu."</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Maj"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Autres symboles"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I majuscule, point en chef"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Symbole inconnu."</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji inconnu."</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ennui"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Embarras"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Lunettes de soleil"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Surpris"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bisou"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Sourcils froncés"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Des caractères supplémentaires sont disponibles."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Les caractères supplémentaires sont ignorés."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Des suggestions supplémentaires sont disponibles."</string>
diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml
index 9cefdad..e1598e2 100644
--- a/java/res/values-fr/strings.xml
+++ b/java/res/values-fr/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer à chaque touche"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Son à chaque touche"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Agrandir les caractères"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Préférences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Comptes et confidentialité"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Apparence et dispositions"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Saisie gestuelle"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Correction du texte"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Paramètres avancés"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Thème"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Activer le clavier en deux parties"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synchronisation du clavier Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"La synchronisation est activée."</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synchronisez votre dictionnaire personnel sur plusieurs appareils."</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synchroniser"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Supprimer les données du cloud"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Supprime vos données synchronisées de Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Les données synchronisées seront supprimées du cloud. Continuer ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Supprimer"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Annuler"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Votre dictionnaire personnel sera synchronisé et sauvegardé sur les serveurs de Google. Des statistiques concernant la fréquence des mots peuvent être recueillies pour nous aider à améliorer nos produits. La collecte et l\'utilisation de toutes les informations sont effectuées conformément aux "<a href="https://www.google.com/policies/privacy">"Règles de confidentialité de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Ajoutez compte Google à cet appareil pour activer fonctionnalité."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Autres modes de saisie"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La touche de sélection de langue couvre d\'autres modes de saisie."</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Touche de sélection de langue"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Afficher lorsque plusieurs langues de saisie sont activées"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Aff. indicateur saisie gest."</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Aff. un repère visuel si l\'utilisateur appuie sur Maj ou Symboles"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Masquer touche agrandie"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sans délai"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Par défaut"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dictionnaire principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Suggestions de correction"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Afficher les suggestions de terme lors de la saisie"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Toujours afficher"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Afficher en mode Portrait"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Toujours masquer"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquer les termes choquants"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Pas de termes potentiellement choquants"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correction auto"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Touche de saisie vocale"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Aucun mode de saisie vocale activé. Vérifiez les paramètres de langue et de saisie."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Envoyer des commentaires"</string>
-    <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Langues"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Aide et commentaires"</string>
+    <string name="select_language" msgid="5709487854987078367">"Langues"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Appuyez ici pour enregistrer."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Thème du clavier"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Changer de compte"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Aucun compte sélectionné"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Vous utilisez actuellement le compte <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Annuler"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Déconnexion"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Sélectionner le compte à utiliser"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglais (Royaume-Uni)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglais (États-Unis)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espagnol (États-Unis)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi/Anglais"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbe (latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"anglais (Royaume-Uni) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"anglais (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"espagnol (États-Unis) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/Anglais (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbe (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionnel)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrillique)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Aucune langue (latin)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alphabet latin (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alphabet latin (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alphabet latin (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alphabet latin (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Thème du clavier"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Styles saisie personnalisés"</string>
     <string name="add_style" msgid="6163126614514489951">"Ajouter style"</string>
     <string name="add" msgid="8299699805688017798">"Ajouter"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activer"</string>
     <string name="not_now" msgid="6172462888202790482">"Pas maintenant"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Le style de saisie suivant existe déjà : <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>."</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Délai appui prolongé sur touche"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durée vibration press. touche"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume son pression de touche"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lire un fichier de dictionnaire externe"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Aucun fichier de dictionnaire dans le dossier \"Téléchargements\""</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Sélectionner un fichier de dictionnaire à installer"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Installer ce fichier pour la langue \"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>\" ?"</string>
-    <string name="error" msgid="8940763624668513648">"Une erreur s\'est produite"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Délai appui prolongé sur touche"</string>
     <string name="button_default" msgid="3988017840431881491">"Par défaut"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Bienvenue dans <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"avec la saisie gestuelle"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>, vous pouvez saisir du texte dans toutes vos applications préférées."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurer des langues supplémentaires"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"OK"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Afficher icône application"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Afficher l\'icône de l\'application dans le lanceur"</string>
     <string name="app_name" msgid="6320102637491234792">"Fournisseur de dictionnaires"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Fournisseur de dictionnaires"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Service de dictionnaires"</string>
diff --git a/java/res/values-gl-rES/strings-emoji-descriptions.xml b/java/res/values-gl-rES/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..cdb67fa
--- /dev/null
+++ b/java/res/values-gl-rES/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Signo de copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Signo de rexistro"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Signo de dobre exclamación"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Signo de interrogación exclamativa"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Símbolo de marca rexistrada"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Fonte de información"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Frecha cara á esquerda e cara á dereita"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Frecha cara arriba e cara abaixo"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Frecha cara o noroeste"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Frecha cara o nordeste"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Frecha cara o sudeste"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Frecha cara o sueste"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Frecha á esquerda con gancho"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Frecha á dereita con gancho"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Ver"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Reloxo de area"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Duplo triángulo negro cara á dereita"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Duplo triángulo negro cara á esquerda"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Duplo triángulo negro cara arriba"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Duplo triángulo negro cara abaixo"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Espertador"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Reloxo de area en movemento"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Letra latina m en maiúscula en círculo"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Cadrado negro pequeno"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Cadrado branco pequeno"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triángulo negro cara á dereita"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triángulo que apunta á esquerda"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Cadrado branco mediano"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Cadrado negro mediano"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Cadrado branco pequeno e mediano"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Cadrado negro mediano e pequeno"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sol negro con raios"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nube"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Teléfono negro"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Caixa de selección con marca de verificación"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraugas con gotas de choiva"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Bebida quente"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Dedo índice branco apuntando cara arriba"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Cara branca sorrinte"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tauro"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Xémini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cáncer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Escorpio"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Saxitario"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricornio"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Acuario"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Piscis"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Picas negras"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Trevos negros"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Corazóns negros"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Diamantes negros"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Fontes termais"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Símbolo universal da reciclaxe negro"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Símbolo de carreira de rodas"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Áncora"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Símbolo de advertencia"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Sinal de alta voltaxe"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Círculo branco mediano"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Círculo negro mediano"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Balón de fútbol"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Béisbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Boneco de neve sen neve"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol tapado por unha nube"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ofiuco"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Prohibido pasar"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Igrexa"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fonte"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandeira nun burato"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Bote de vela"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tenda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Gasolineira"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Tesoiras negras"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Marca de verificación branca de trazo groso"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avión"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Sobre"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Puño erguido"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Man erguida"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Man co sinal de vitoria"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Lapis"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Estilográfica negra"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Marca de verificación de trazo groso"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Símbolo de multiplicación x de trazo groso"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Faíscas"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisco de oito puntas"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Estrela negra de oito puntas"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Folerpa"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Faísca"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Cruz"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Cruz branca sobre cadrado de fondo negro"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Signo de interrogación negro"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Signo de interrogación branco"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Signo de exclamación branco"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Signo de exclamación de trazo groso"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Corazón negro de trazo groso"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Signo máis de trazo groso"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Signo menos de trazo groso"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Signo de división de trazo groso"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Frecha negra cara a dereita"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Lazo"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Lazo dobre"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Frecha cara a dereita e curvada cara arriba"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Frecha cara a dereita e curvada cara abaixo"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Frecha negra cara a esquerda"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Frecha negra cara arriba"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Frecha negra cara abaixo"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Cadrado negro grande"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Cadrado branco grande"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Estrela mediana branca"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Círculo grande de trazo ancho"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Guión ondulado"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Marca de alternancia de parte"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograma de felicitación en círculo"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograma de segredo en círculo"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mosaico Mahjong do dragón vermello"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Comodín negro (carta)"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Tipo sanguíneo A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Tipo sanguíneo B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Tipo sanguíneo O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Aparcadoiro"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Tipo sanguíneo AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL sobre cadrado"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cool sobre cadrado"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Free sobre cadrado"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID sobre cadrado"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"New sobre cadrado"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"N G sobre cadrado"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK sobre cadrado"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS sobre cadrado"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"UP con signo de exclamación sobre cadrado"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"vs sobre cadrado"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana aquí sobre cadrado"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Servizo katakana sobre cadrado"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideograma de uso gratuíto sobre cadrado"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideograma de asento reservado sobre cadrado"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideograma de prohibición sobre cadrado"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideograma de posto vacante sobre cadrado"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideograma de aceptación sobre cadrado"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideograma de ocupación completa sobre cadrado"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Pago do ideograma sobre cadrado"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideograma mensual sobre cadrado"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideograma de aplicación sobre cadrado"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideograma de desconto sobre cadrado"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideograma de negocios sobre cadrado"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideograma de beneficios sobre círculo"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideograma de aceptar sobre círculo"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciclón"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Neboento"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Paraugas pechado"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Noite con estrelas"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Amencer sobre as montañas"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Amencer"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Paisaxe urbana ao anoitecer"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Solpor sobre edificios"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arco da vella"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Ponte pola noite"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Onda de auga"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volcán"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Vía láctea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Europa e África no globo terráqueo"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"As Américas no globo terráqueo"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Asia e Australia no globo terráqueo"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo cos meridianos"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Símbolo de lúa nova"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Lúa nova visible"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Símbolo de lúa en cuarto crecente"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Símbolo de lúa xibosa"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Símbolo de lúa chea"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Símbolo de lúa xibosa minguante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Símbolo de lúa en cuarto minguante"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Símbolo de lúa minguante"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Lúa crecente"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Lúa nova con cara"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Lúa en cuarto crecente con cara"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Lúa en cuarto minguante con cara"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Lúa chea con cara"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol con cara"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Estrela brillante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Estrela fugaz"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Castaña"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Plántula"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Árbore de folla perenne"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Árbore de folla caduca"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmeira"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cacto"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Flor da cerdeira"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscos"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Xirasol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Flor"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Mazaroca de millo"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Planta de arroz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Planta"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trevo de catro follas"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Folla de pradairo"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Folla caída"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Folla a voar co vento"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Cogomelo"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Berenxena"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uvas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melón"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Sandía"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tanxerina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limón"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Piña"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Mazá vermella"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Mazá verde"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Melocotón"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cereixas"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Fresa"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburguesa"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Porción de pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Carne con óso"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Pata de ave"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Torta de arroz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Bóla de arroz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arroz cocido"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry e arroz"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Cunca fumeante"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pan"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patacas fritidas"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pataca doce asada"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Camarón frito"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Croqueta de peixe con forma de remuíño"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Xeado"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Granizado"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Xeado de bóla"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Rosquilla"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Galleta"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barra de chocolate"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Caramelo"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Chupa-chupa"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Crema"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Tarro de mel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Pastel"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Comida para levar"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Pota con comida"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Cociña"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Garfo e coitelo"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Cunca do té sen agarradoira"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Botella de sake e cunca"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Copa de viño"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Copa de cóctel"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Bebida tropical"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Xerra de cervexa"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Xerras de cervexa en brinde"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberón"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Cinta"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Agasallo con envoltorio"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Torta de aniversario"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Cabaza de Halloween"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Árbore de Nadal"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Papá Noel"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fogos de artificio"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Luces dos fogos de artificio"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Globo"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Decoración para festas"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Bóla de confeti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Árbore de Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bandeiras cruzadas"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Piñeiro para decorar"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Bonecas xaponesas"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Bandeira con forma de carpa"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Campá de vento"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Cerimonia de contemplación da lúa"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Maletín escolar"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Barrete de graduación"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cabaliños"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Nora"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Patín"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Cana de pescar e peixe"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Micrófono"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Cámara de cine"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cine"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Auricular"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta de cores"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Chapeu de copa"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Carpa de circo"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Tícket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Claqueta"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Artes escénicas"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videoxogo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Dardo no centro da diana"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Máquina recreativa"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dado"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bolos"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Baralla de flores"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota musical"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Varias notas musicais"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofón"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Teclado musical"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violín"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitura"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Camisola para correr cunha banda"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raqueta de tenis e pelota"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Esquí e bota de esquí"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Baloncesto e canastra"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandeira con cadros de xadrez"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Persoa que practica snowboard"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Corredor"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfista"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofeo"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Carreira de cabalos"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Fútbol americano"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nadador"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Casa"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa con xardín"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Edificio de oficinas"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Oficina de correos xaponesa"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Oficina de correos europea"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banco"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Caixeiro automático"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel do amor"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Tenda 24 horas"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Escola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Grandes almacéns"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fábrica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lámpada Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Castelo xaponés"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castelo europeo"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rata"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Rato"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Boi"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Búfalo de auga"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vaca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Coello"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gato"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragón"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodilo"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balea"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Caracol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Cobra"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cabalo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Carneiro"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Cabra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovella"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Mono"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Galo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Polo"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Can"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Porco"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Xabaril"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Polbo"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Cuncha con espiral"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Bicho"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Formiga"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abella"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Xoaniña"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Peixes"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Peixe tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Peixe globo"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tartaruga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Galiña a chocar"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pitiño"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pitiño de fronte"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Paxaro"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingüín"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Coala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Cachorro"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedario"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Camelo"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Golfiño"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Cara de rato"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Cara de vaca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Cara de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Cara de coello"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Cara de gato"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Cara de dragón"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Balea que bota auga"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Cara de cabalo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Cara de mono"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Cara de can"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cara de porco"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Cara de ra"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Cara de hámster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Cara de lobo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Cara de oso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Cara de panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nariz de porco"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pegadas de patas de animais"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ollos"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Orella"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nariz"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Boca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lingua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Man branca co índice a sinalar cara a arriba"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Man branca co índice a sinalar cara a abaixo"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Man branca co índice a sinalar cara á esquerda"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Man branca co índice a sinalar cara á dereita"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Puño"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Man con aceno de saudar"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Man con aceno de aprobación"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Polgar cara arriba"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Polgar cara abaixo"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Mans a dar palmas"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Mans abertas"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Coroa"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Sombreiro de muller"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Lentes"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Gravata de lazo"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Camiseta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Vaqueiros"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Vestido"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Quimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Roupa de muller"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Portamoedas"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Bolso"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Neceser"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Zapato de home"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Zapato de deporte"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Zapato de tacón"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandalia de muller"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Botas de muller"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Pegadas"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta de persoa"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Siluetas de persoas"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Chico"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Chica"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Home"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Muller"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Home e muller collidos da man"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dous homes collidos da man"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dúas mulleres collidas da man"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policía"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Muller con orellas de coello"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Noiva con veo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persoa co cabelo louro"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Home con bigote xaponés"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Home con turbante"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Ancián"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Anciá"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bebé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Obreiro"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogro xaponés"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Trasno xaponés"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Pantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Anxo bebé"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstro alien"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Demo"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Caveira"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Persoa de atención ao cliente"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Soldado"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Bailarín"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Pintalabios"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Pintauñas"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masaxe facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Corte de cabelo"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Sinal de barbaría"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Xiringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pílula"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Bico"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Carta de amor"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anel"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Pedra preciosa"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bico"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Papel bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Parella con corazón"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Vodas"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Corazón que bate"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Corazón roto"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dous corazóns"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Corazón brillante"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Corazón que crece"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Corazón con frecha"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Corazón azul"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Corazón verde"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Corazón amarelo"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Corazón violeta"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Corazón con cinta"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Corazóns que dan voltas"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Corazón decorativo"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamante cun punto dentro"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Lámpada"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Símbolo da ira"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Símbolo de durmir"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Símbolo de colisión"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Símbolo de suor a caer"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Pinga"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Raia"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Montón de caca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bíceps flexionados"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Símbolo de mareado"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Globo de discurso"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Globo de pensamento"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Flor branca"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Símbolo de cen puntos"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Carteira"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Cambio de moeda"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Símbolo groso do dólar"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Tarxeta de crédito"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Billete co símbolo do ien"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Billete co símbolo do dólar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Billete co símbolo do euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Billete co símbolo da libra"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Diñeiro con ás"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Gráfica ascendente e o símbolo do ien"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Asento"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Computador"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Portadocumentos"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquete"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disco óptico"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Cartafol de ficheiros"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Cartafol aberto"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Folla cunha parte curva"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Páxina cara arriba"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendario"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendario de follas soltas"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Clasificador de tarxetas"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Gráfica ascendente"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Gráfica descendente"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Gráfica de barras"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Portapapeis"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Alfinete"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Chincheta redonda"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Clip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Regra"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Cartabón"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Marcapáxinas"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Papel de contabilidade"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Caderno de notas"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Caderno con portada decorativa"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Libro pechado"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Libro aberto"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Libro verde"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Libro azul"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Libro laranxa"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Libros"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Identificación"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Desprazar"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Nota"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Auricular do teléfono"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Busca"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena de satélite"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Altofalante"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megáfono"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Caixa de saída"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Caixa de entrada"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paquete"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Símbolo de correo electrónico"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Sobre recibido"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Sobre con frecha cara abaixo enriba"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Caixa de correo pechada coa bandeiriña baixada"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Caixa de correo pechada coa bandeiriña erguida"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Caixa de correo aberta coa bandeiriña subida"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Caixa de correo aberta coa bandeiriña baixada"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Caixa de correo"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Corneta de posta"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Prensa"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Teléfono móbil"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Teléfono móbil con frecha cara a dereita na esquerda"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Modo de vibración"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Teléfono móbil apagado"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Prohibido teléfonos móbiles"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena con barras"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Cámara"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videocámara"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisión"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocasete"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Frechas cara á dereita enroscadas"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Frechas en círculo cara a dereita e cara a esquerda que xiran no sentido das agullas do reloxo"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Frechas en círculo cara a dereita e cara a esquerda que xiran no sentido das agullas do reloxo co número 1 en círculo superposto"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Frechas en círculos abertos que xira cara a dereita e cara arriba e abaixo"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Frechas en círculo cara arriba e cara abaixo que xiran no sentido contrario das agullas do reloxo"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Símbolo de luminosidade baixa"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Símbolo de luminosidade alta"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altofalante con trazo de cancelación"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altofalante"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altofalante cunha onda de son"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altofalante con tres ondas de son"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batería"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Enchufe"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa inclinada cara a esquerda"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa inclinada cara a dereita"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Cadeado con estilográfica"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Cadeado pechado coa chave"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Chave"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Cadeado"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Cadeado aberto"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Campá"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Campá con trazo de cancelación"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Marcador"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Símbolo de ligazón"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Botón de opción"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"Back\" cunha frecha cara a esquerda enriba"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"End\" cunha frecha cara a esquerda enriba"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"On\" cun signo de exclamación e cunha frecha dobre cara a esquerda e cara a dereita enriba"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"Soon\" cunha frecha cara a dereita enriba"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"Top\" cunha frecha cara arriba enriba"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Símbolo de prohibido a menores de dezaoito"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tecla co número dez"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Símbolo de entrada para letras maiúsculas latinas"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Símbolo de entrada para letras minúsculas latinas"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Símbolo de entrada para números"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Símbolo de entrada para símbolos"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Símbolo de entrada para letras latinas"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Lume"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Lanterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Chave inglesa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martelo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Parafuso e porca"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscopio"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescopio"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bóla de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Estrela de seis puntas cun punto no medio"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Símbolo xaponés para principiante"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Tridente"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botón cadrado negro"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botón cadrado branco"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Círculo vermello grande"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Círculo azul grande"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Diamante laranxa grande"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Diamante azul grande"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Diamante laranxa pequeno"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Diamante azul pequeno"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triángulo vermello apuntando cara arriba"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triángulo vermello cara abaixo"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triángulo vermello pequeno apuntando cara arriba"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triángulo vermello pequeno apuntando cara abaixo"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Reloxo que marca a unha en punto"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Reloxo que marca as dúas en punto"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Reloxo que marca as tres en punto"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Reloxo que marca as catro en punto"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Reloxo que marca as cinco en punto"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Reloxo que marca as seis en punto"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Reloxo que marca as sete en punto"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Reloxo que marca as oito en punto"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Reloxo que marca as nove en punto"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Reloxo que marca as dez en punto"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Reloxo que marca as once en punto"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Reloxo que marca as doce en punto"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Reloxo que marca a unha e media"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Reloxo que marca as dúas e media"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Reloxo que marca as tres e media"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Reloxo que marca as catro e media"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Reloxo que marca as cinco e media"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Reloxo que marca as seis e media"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Reloxo que marca as sete e media"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Reloxo que marca as oito e media"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Reloxo que marca as nove e media"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Reloxo que marca as dez e media"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Reloxo que marca as once e media"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Reloxo que marca as doce e media"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Monte Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Torre de Toquio"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Estatua da Liberdade"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silueta do Xapón"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Cara con sorriso burlón"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Cara con sorriso burlón e ollos sorrintes"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Cara con bágoas de alegría"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Cara sorrinte coa boca aberta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Cara sorrinte coa boca aberta e ollos sorrintes"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Cara sorrinte coa boca aberta e suor frío"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Cara sorrinte coa boca aberta e os ollos pechados con forza"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Cara sorrinte con halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Cara sorrinte con cornos"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Cara que chisca un ollo"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Cara sorrinte con ollos sorrintes"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Cara saboreando unha comida deliciosa"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Cara con sensación de alivio"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Cara sorrinte con ollos en forma de corazón"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Cara sorrinte con gafas de sol"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Cara con sorriso burlón"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Cara neutral"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Cara sen expresión"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Cara de pouca graza"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Cara con suor frío"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Cara pensativa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Cara confusa"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Cara de confusión"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Cara con labios para bicar"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Cara a mandar un bico"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Cara con labios para bicar con ollos sorrintes"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Cara con labios para bicar cos ollos pechados"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Cara coa lingua fóra"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Cara coa lingua fóra e un ollos chiscado"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Cara coa lingua fóra e os ollos pechados con forza"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Cara de desgusto"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Cara de preocupación"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Cara de enfado"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Cara de moito enfado"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Cara a chorar"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Cara de tenacidade"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Cara con aspecto de gañar"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Cara de desgusto pero con sensación de alivio"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Cara triste coa boca aberta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Cara de angustia"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Cara de medo"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Cara de desánimo"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Cara de sono"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Cara de cansazo"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Cara con xesto"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Cara que chora desconsoladamente"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Cara coa boca aberta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Cara de silencio"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Cara coa boca aberta e suor frío"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Cara que grita de medo"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Cara de asombro"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Cara de vergoña"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Cara a durmir"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Cara de mareo"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Cara sen boca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Cara con máscara médica"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Cara con sorriso burlón e ollos sorrintes"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Cara con bágoas de alegría"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Cara de gato sorrinte coa boca aberta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Cara de gato sorrinte cos ollos en forma de corazón"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Cara de gato con sorriso pícaro"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Cara de gato que dá un bico e cos ollos pechados"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Cara de gato moi enfadado"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Cara de gato a chorar"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Cara de gato cansado"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Cara con xesto de desaprobación"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Cara con xesto de aprobación"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persoa facendo unha reverencia"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Mono que non quere ver nada malo"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Mono que non quere oír nada malo"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Mono que non quere falar de nada malo"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Persoa feliz a erguer unha man"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persoa a erguer as dúas mans como celebración"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persoa co cello engurrado"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persoa con cara moi enfadada"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persoa coas mans xuntas"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Foguete"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicóptero"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotora a vapor"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagón"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tren de alta velocidade"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Tren de alta velocidade con morro en forma de bala"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tren lixeiro"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Estación"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tranvía"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tranvía"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobús"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobús próximo"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolebús"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Parada de autobús"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibús"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulancia"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camión dos bombeiros"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Coche de policía"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Coche de policía próximo"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi próximo"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automóbil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automóbil próximo"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Caravana"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camión de entrega"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camión articulado"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorraíl"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Vía de tren na montaña"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Vía férrea en suspensión"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Teleférico na montaña"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Teleférico"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Nave"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Bote de remos"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Lancha motora"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semáforo"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semáforo"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Símbolo de construción"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Coches de policía coas luces acesas"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bandeira con forma de triángulo pendurada nun poste"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Símbolo de prohibido pasar"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Símbolo de fumar"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Símbolo de prohibido fumar"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Símbolo de poñer o lixo neste lugar"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Símbolo de prohibido contaminar"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Símbolo de auga potable"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Símbolo de auga non potable"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Prohibido bicicletas"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista de montaña"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Peón"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Prohibido peóns"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Nenos a cruzar"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Símbolo de homes"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Símbolo de mulleres"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Aseo"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Símbolo de bebé"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Baño"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Retrete"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Ducha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Baño"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bañeira"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Control de pasaportes"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Aduanas"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Zona de recollida de equipaxes"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Equipaxe en depósito"</string>
+</resources>
diff --git a/java/res/values-gl-rES/strings-talkback-descriptions.xml b/java/res/values-gl-rES/strings-talkback-descriptions.xml
index d253d34..70732a0 100644
--- a/java/res/values-gl-rES/strings-talkback-descriptions.xml
+++ b/java/res/values-gl-rES/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"Conecta uns auriculares para escoitar as teclas do contrasinal pronunciadas."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"O texto actual é %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"Non se introduciu ningún texto"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrixe <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> por <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> leva a cabo a corrección automática"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Non hai suxestións"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Carácter descoñecido"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Maiús"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Máis símbolos"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Maiús"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Símbolos"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Maiús"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"Suprimir"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Símbolos"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Letras"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Números"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Configuración"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Pestana"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Espazo"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Entrada de voz"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Emoji"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Volver"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Buscar"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Punto"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Cambiar idioma"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Seguinte"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Anterior"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Maiús activadas"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"Bloqueo de maiúsculas activado"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Modo de símbolos"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"Modo máis símbolos"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Modo de cartas"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Modo teléfono"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Modo de símbolos do teléfono"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Teclado oculto"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"Mostrar teclado <xliff:g id="KEYBOARD_MODE">%s</xliff:g>"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"data"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"data e hora"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"correo electrónico"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"mensaxería"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"número"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"teléfono"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"texto"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"hora"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Recentes"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Persoas"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Obxectos"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Natureza"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Lugares"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Símbolos"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Emoticonas"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"<xliff:g id="LOWER_LETTER">%s</xliff:g> maiúscula"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"I maiúscula"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiúscula, punto superior"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo descoñecido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji descoñecido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara aburrida"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara con vergoña"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara con gafas de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara de sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara con labios para bicar"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara engurrando o cello"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Os caracteres alternativos están dispoñibles"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Descártanse os caracteres alternativos"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"As suxestións alternativas están dispoñibles"</string>
diff --git a/java/res/values-gl-rES/strings.xml b/java/res/values-gl-rES/strings.xml
index a02e383..8370aed 100644
--- a/java/res/values-gl-rES/strings.xml
+++ b/java/res/values-gl-rES/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar as teclas"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Son ao premer as teclas"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Ventás emerxentes ao premer as teclas"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferencias"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Contas e privacidade"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aparencia e deseños"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escritura xestual"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Corrección de texto"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Opcións avanzadas"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Activar teclado dividido"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronización do teclado Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"A sincronización está activada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincroniza o teu dicionario persoal nos dispositivos"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizar agora"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Eliminar datos da nube"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Elimina os teus datos sincronizados de Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Os teus datos sincronizados eliminaranse da nube. Estás seguro?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Eliminar"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancelar"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Sincronizarase o teu dicionario persoal e realizarase unha copia de seguranza nos servidores de Google. Quizais se recompile información estatística da frecuencia das palabras para axudar a mellorar os nosos produtos. A recompilación e o uso de toda a información cumprirán coa "<a href="https://www.google.com/policies/privacy">"Política de privacidade de Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Engade unha conta de Google ao dispositivo para activar a función"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Outros métodos de entrada"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla de cambio de idioma inclúe outros métodos de entrada"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla de cambio de idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostra cando hai varios idiomas de entrada activados"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador movemento"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Indicación visual ao pasar o dedo nas teclas Maiús ou de símbolos"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Retraso ao ampliar tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sen retraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predeterminado"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dicionario principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar suxestións de corrección"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Mostra palabras suxeridas mentres escribes"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar en modo vertical"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar sempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palabras ofensivas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Non suxerir palabras potencialmente ofensivas"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autocorrección"</string>
@@ -85,24 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tecla de entrada de voz"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Non hai ningún método de entrada de voz activado. Comproba a configuración de Idioma e entrada de texto."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentarios"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Axuda e suxerencias"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca de novo para gardar"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toca aquí para gardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionario dispoñible"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Cambiar contas"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Non se seleccionou ningunha conta"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Actualmente utilizando <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Aceptar"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancelar"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Pechar sesión"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecciona unha conta para usar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglés (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglés (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Español (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbio (latino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglés (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglés (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Español (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <skip />
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ningún idioma (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -111,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema do teclado"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos de entrada personalizados"</string>
     <string name="add_style" msgid="6163126614514489951">"Engadir estilo"</string>
     <string name="add" msgid="8299699805688017798">"Engadir"</string>
@@ -132,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activar"</string>
     <string name="not_now" msgid="6172462888202790482">"Agora non"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Xa existe o mesmo estilo de entrada: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso de pulsación prolongada"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duración vibración ao premer teclas"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume do son ao premer teclas"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ler ficheiro de dicionario externo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Non hai ningún ficheiro de dicionario no cartafol de descargas"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecciona un ficheiro de dicionario para instalar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Realmente queres instalar este ficheiro para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Produciuse un erro"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Retraso de pulsación prolongada"</string>
     <string name="button_default" msgid="3988017840431881491">"Predeterminado"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Benvido a <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"con escritura xestual"</string>
@@ -157,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Agora podes escribir en todas as túas aplicacións favoritas con <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurar idiomas adicionais"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Finalizado"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostrar icona da aplicación"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostra a icona da aplicación no menú de aplicacións"</string>
     <string name="app_name" msgid="6320102637491234792">"Fornecedor do dicionario"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Fornecedor do dicionario"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Servizo de dicionario"</string>
@@ -176,7 +170,7 @@
     <string name="no_dictionaries_available" msgid="8039920716566132611">"Non hai dicionarios"</string>
     <string name="check_for_updates_now" msgid="8087688440916388581">"Actualizar"</string>
     <string name="last_update" msgid="730467549913588780">"Última actualización"</string>
-    <string name="message_updating" msgid="4457761393932375219">"Comprobando se hai actualizacións"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Buscando actualizacións"</string>
     <string name="message_loading" msgid="5638680861387748936">"Cargando..."</string>
     <string name="main_dict_description" msgid="3072821352793492143">"Dicionario principal"</string>
     <string name="cancel" msgid="6830980399865683324">"Cancelar"</string>
diff --git a/java/res/values-hi/donottranslate-config-spacing-and-punctuations.xml b/java/res/values-hi/donottranslate-config-spacing-and-punctuations.xml
new file mode 100644
index 0000000..4ef36c0
--- /dev/null
+++ b/java/res/values-hi/donottranslate-config-spacing-and-punctuations.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- The sentence separator code point, for double-space-to-period -->
+    <!-- U+007C: "|" VERTICAL LINE ; 7Ch = 124d -->
+    <integer name="sentence_separator">124</integer>
+</resources>
diff --git a/java/res/values-hi/strings-action-keys.xml b/java/res/values-hi/strings-action-keys.xml
index 7237c24..8768ee7 100644
--- a/java/res/values-hi/strings-action-keys.xml
+++ b/java/res/values-hi/strings-action-keys.xml
@@ -21,7 +21,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="label_go_key" msgid="4033615332628671065">"जाएं"</string>
-    <string name="label_next_key" msgid="5586407279258592635">"अगला"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"आगे"</string>
     <string name="label_previous_key" msgid="1421141755779895275">"पिछला"</string>
     <string name="label_done_key" msgid="7564866296502630852">"पूर्ण"</string>
     <string name="label_send_key" msgid="482252074224462163">"भेजें"</string>
diff --git a/java/res/values-hi/strings-config-important-notice.xml b/java/res/values-hi/strings-config-important-notice.xml
index 3f22541..c3332bb 100644
--- a/java/res/values-hi/strings-config-important-notice.xml
+++ b/java/res/values-hi/strings-config-important-notice.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="use_personalized_dicts_summary" msgid="590432261305469627">"सुझावों में सुधार हेतु अपने संचार और लिखे गए डेटा से जानकारी पाएं"</string>
+    <string name="use_personalized_dicts_summary" msgid="590432261305469627">"सुझावों में सुधार के लिए अपने संचार और लिखे गए डेटा से जानकारी पाएं"</string>
 </resources>
diff --git a/java/res/values-hi/strings-emoji-descriptions.xml b/java/res/values-hi/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..1f18e6a
--- /dev/null
+++ b/java/res/values-hi/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"कॉपीराइट चिह्न"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"पंजीकृत चिह्न"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"दोहरा विस्मयादिबोधक चिह्न"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"विस्मयादिबोधक प्रश्नवाचक चिह्न"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"ट्रेडमार्क चिह्न"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"जानकारी स्रोत"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"बायां दायां तीर"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"ऊपर नीचे तीर"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"उत्तर पश्चिम तीर"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"उत्तर पूर्व तीर"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"दक्षिण पूर्व तीर"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"दक्षिण पश्चिम तीर"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"हुक वाला बाईं ओर मुड़ा तीर"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"हुक वाला दाईं ओर मुड़ा तीर"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"देखें"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"रेतघड़ी"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"काला दाईं ओर इंगित करता दोहरा त्रिभुज"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"काला बाईं ओर इंगित करता दोहरा त्रिभुज"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"काला ऊपर की ओर इंगित करता दोहरा त्रिभुज"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"काला नीचे इंगित करता हुआ दोहरा त्रिभुज"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"अलार्म घड़ी"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"बहती रेत वाली रेत घड़ी"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"घेराबद्ध बड़ा अक्षर m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"काला छोटा वर्ग"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"सफेद छोटा वर्ग"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"काला दाईं ओर इंगित करता हुआ त्रिभुज"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"काला बाईं ओर इंगित करता हुआ त्रिभुज"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"सफेद मध्यम वर्ग"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"काला मध्यम वर्ग"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"सफेद मध्यम छोटा वर्ग"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"काला मध्यम छोटा वर्ग"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"किरणों वाला काला सूर्य"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"बादल"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"काला टेलीफ़ोन"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"चेक वाला बैलट बॉक्स"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"बारिश की बूंदों वाला छाता"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"गर्म पेय"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"सफेद ऊपर इंगित करता हुआ सूचक"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"सफेद हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"मेष"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"वृषभ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"मिथुन"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"कर्क"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"सिंह"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"कन्या"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"तुला"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"वृश्चिक"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"धनु"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"मकर"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"कुंभ"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"मीन"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"कालापान"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"चिड़ी"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"कालापान"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"ईंट"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"उष्ण बसंत"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"काला वैश्विक रिसायक्लिंग प्रतीक"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"व्हीलचेयर प्रतीक"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"एंकर"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"चेतावनी चिह्न"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"उच्च वोल्टेज चिह्न"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"मध्यम सफेद घेरा"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"मध्यम काला घेरा"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"फुटबॉल"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"बेसबॉल"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"बिना बर्फ वाला स्नोमेन"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"बादलों के पीछे सूर्य"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ऑफ़ीयूकस"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"प्रवेश नहीं"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"गिरजाघर"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"फव्वारा"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"छिद्र में झंडा"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"पाल-नौका"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"तम्बू"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"फ्यूल पंप"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"काली कैंचियां"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"सफेद मोटा चेक मार्क"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"हवाईजहाज़"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"लिफ़ाफ़ा"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"उठी हुई मुठ्ठी"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"उठा हुआ हाथ"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"विजयी हाथ"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"पेंसिल"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"काली निब"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"मोटा चेक मार्क"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"मोटा गुणन x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"चिंगारियां"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"आठ सलाखों वाला तारा"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"आठ भुजाओं वाला काला तारा"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"स्नोफ्लेक"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"चिंगारी"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"क्रॉस चिह्न"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"नेगेटिव वर्ग वाला क्रॉस चिह्न"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"काला प्रश्नवाचक चिह्न आभूषण"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"सफेद प्रश्नवाचक चिह्न आभूषण"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"सफेद विसमयादिबोधक चिह्न आभूषण"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"मोटा विस्मयादिबोधक चिह्न प्रतीक"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"मोटा काला दिल"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"मोटा धन चिह्न"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"मोटा ऋण चिह्न"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"मोटा विभाजन चिह्न"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"काला दायां तीर"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"घुमावदार लूप"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"दोहरा घुमावदार लूप"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"दाईं ओर होकर ऊपर तीर"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"दाईं ओर होकर नीचे तीर"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"बाएं काला तीर"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"ऊपर काला तीर"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"नीचे काला तीर"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"काला बड़ा वर्ग"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"सफेद बड़ा वर्ग"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"सफेद मध्यम तारा"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"मोटा बड़ा चक्र"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"लहरिल डैश"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"भाग विकल्प चिह्न"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"चक्रित आइडियोग्राफ़़ बधाई"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"चक्रित आइडियोग्राफ़ रहस्य"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"माहजोंग टाइल लाल ड्रेगन"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"प्लेइंग कार्ड काला जोकर"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"रक्त प्रकार A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"रक्त प्रकार B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"रक्त प्रकार O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"पार्किंग स्थल"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"रक्त प्रकार AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"चौकोर CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"शानदार चौकोर"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"मुक्त चौकोर"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"चौकोर आईडी"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"नया चौकोर"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"चौकोर N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"चौकोर ठीक"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"चौकोर SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"चौकोर आकार के साथ विस्मयादिबोधक चिह्न"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"चौकोर बनाम"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"चौकोर काताकाना"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"चौकोर काताकाना सेवा"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"चौकोर आइडियोग्राफ़़ निशुल्क"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"चौकोर आइडियोग्राफ़ आरक्षित सीट"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"चौकोर आइडियोग्राफ़ प्रतिबंध"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"चौकोर आइडियोग्राफ़ वेकेंसी"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"चौकोर ऑडियोग्राफ़ स्वीकार्यता"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"चौकोर आइडियोग्राफ़़ पूर्ण अधिकार"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"चौकोर आइडियोग्राफ़ सशुल्क"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"चौकोर आइडियोग्राफ़़ मासिक"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"चौकोर आइडियोग्राफ़़ ऐप्लिकेशन"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"चौकोर आइडियोग्राफ़़ छूट"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"व्यवसाय में चौकोर आइडियोग्राफ़़"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"गोल आइडियोग्राफ़़ लाभ"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"गोल आइडियोग्राफ़़ स्वीकार"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"चक्रवात"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"कोहरे वाला"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"बंद छाता"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"तारों भरी रात"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"पहाड़ों पर सूर्योदय"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"सूर्योदय"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"संध्याकाल में शहर का दृश्य"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"बिल्डिंग पर सूर्यास्त"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"इंद्रधनुष"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"रात में पुल"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"पानी की लहर"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"ज्वालामुखी"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"आकाशगंगा"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"विश्व ग्लोब यूरोप-अफ़्रीका"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"विश्व ग्लोब अमेरिका"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"विश्व ग्लोब एशिया-ऑस्ट्रेलिया"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"मध्याह्न रेखाओं वाला ग्लोब"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"नए चंद्रमा का प्रतीक"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"शुक्लपक्षीय चाप के आकार का चंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"शुल्कपक्षीय अर्द्धचंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"शुक्लपक्षीय तीन-चौथाई आकार का चंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"पूर्ण चंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"कृष्णपक्षीय तीन-चौथाई आकार का चंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"कृष्णपक्षीय अर्द्धचंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"कृष्णपक्षीय अर्धचंद्र का प्रतीक"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"कृष्णपक्षीय चाप के आकार का चंद्र प्रतीक"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"चेहरे वाला नव चंद्र"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"चेहरे वाला शुल्कपक्षीय अर्द्धचंद्र"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"चेहरे वाला कृष्णपक्षीय अर्द्धचंद्र"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"चेहरे वाला पूर्ण चंद्र"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"चेहरे वाला सूरज"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"चमकता सितारा"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"टूटा तारा"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"शाहबलूत"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"अंकुर"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"सदाबहार वृक्ष"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"पर्णपाती वृक्ष"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"ताड़ का वृक्ष"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"कैक्टस"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"ट्यूलिप"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"चेरी के फूल"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"गुलाब"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"गुड़हल"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"सूर्यमुखी"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"फूल"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"मक्के का भुट्टा"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"चावल की बाली"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"जड़ी-बूटी"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"चार पत्तियों वाला क्लोवर"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"चिनार की पत्ती"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"गिरी हुई पत्ती"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"हवा में फड़फड़ाती पत्ती"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"कुकुरमुत्ता"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"टमाटर"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"बैंगन"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"अंगूर"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"खरबूजा"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"तरबूज"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"कीनू"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"नींबू"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"केला"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"अनानास"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"लाल सेब"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"हरा सेब"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"नाशपाती"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"आड़ू"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"चेरी"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"स्ट्रॉबेरी"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"हैमबर्गर"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"पिज्जा स्लाइस"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"हड्डी पर मांस"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"मुर्गे की टांग"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"चावल का बिस्कुट"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"राइस बॉल"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"पका हुआ चावल"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"करी और चावल"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"स्टीमिंग बाउल"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"स्पैगेटी"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ब्रेड"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"फ्रेंच फ्राइज़"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"भुना हुआ शकरकंद"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"डेंगो"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ऑडेन"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"सुशी"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"तला हुआ केकड़ा"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"घुमावदार आकृति वाला फिश केक"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"सॉफ़्ट आइस्क्रीम"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"छीली हुई बर्फ"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"आइस्क्रीम"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"डोनट"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"कुकी"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"चॉकलेट बार"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"कैंडी"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"लॉलीपॉप"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"दही"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"शहद का बर्तन"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"शॉर्टकेक"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"बेंटो बॉक्स"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"भोजन का बरतन"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"पाक कला"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"कांटा और चाकू"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"बिना हैंडल वाला चाय का कप"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"मदिरा की बोतल और कप"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"शराब का ग्‍लास"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"कॉकटेल ग्लास"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"ट्रॉपिकल ड्रिंक"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"बीयर मग"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"क्लिंकिंग बीयर मग"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"छोटी बॉटल"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"रिबन"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"लिपटा हुआ उपहार"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"जन्मदिन का केक"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"कद्दू का हैलोवीन लालटेन"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"क्रिसमस ट्री"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"फ़ादर क्रिसमस"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"आतिशबाज़ी"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"आतिशबाज़ी स्पार्कलर"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"गुब्बारा"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"पार्टी पॉपर"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"कंफेटी बॉल"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"तानाबाटा वृक्ष"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"क्रॉस किए गए फ़्लैग"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"पाइन की सजावट"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"जापानी गुड़िया"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"कार्प स्ट्रीमर"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"विंड चाइम"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"चांद देखने का उत्सव"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"स्कूल का बस्ता"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"ग्रेजुएशन कैप"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"घोड़े वाला झूला"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"फ़ेरिस झूला"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"घुमावदार रेल-पथ"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"मछली पकड़ने का डंडा और मछली"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"माइक्रोफ़ोन"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"मूवी कैमरा"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"सिनेमा"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"हेडफ़ोन"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"कलाकार की पैलेट"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"टोप हैट"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"सर्कस का तंबू"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"टिकट"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"क्लेपर बोर्ड"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"अभिनय कला"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"वीडियो गेम"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"सीधा हिट"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"स्लॉट मशीन"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"बिलियर्ड्स"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"गेम डाइ"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"बॉलिंग"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"फूल वाले खेलने के कार्ड"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"संगीत नोट"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"एकाधिक संगीत नोट"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"सैक्सोफ़ोन"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"गिटार"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"संगीत कीबोर्ड"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"तुरही"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"वायलिन"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"संगीत स्कोर"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"बेल्ट वाली रनिंग शर्ट"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"टेनिस रैकेट और गेंद"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"स्की और स्की बूट"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"बास्केटबॉल और हूप"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"चौकड़ी वाला ध्वज"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"बर्फ़ की बॉर्डर"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"धावक"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"सर्फ़र"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ट्रॉफ़ी"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"घुड़दौड़"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"अमेरिकी फ़ुटबाल"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"रग्बी फ़ुटबाल"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"तैराक"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"गृह निर्माण"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"बगीचे वाला घर"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"कार्यालय का भवन"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"जापानी पोस्ट ऑफ़िस"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"यूरोपियन पोस्ट ऑफिस"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"अस्पताल"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"बैंक"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"स्वचालित टेलर मशीन"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"होटल"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"लव होटल"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"सुविधा स्‍टोर"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"विद्यालय"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"डिपार्टमेंट स्टोर"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"कारखाना"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"इज़ाक्या लैंटर्न"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"जापानी किला"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"यूरोपीय किला"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"चूहा"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"माउस"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"बैल"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"भैंस"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"गाय"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"बाघ"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"खरगोश"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"बिल्ली"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ड्रैगन"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"मगरमच्छ"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"व्हेल"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"घोंघा"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"सांप"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"घोड़ा"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"राम"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"बकरी"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"भेड़"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"बंदर"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"मुर्गा"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"चूज़ा"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"कुत्ता"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"सुअर"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"जंगली सुअर"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"हाथी"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ऑक्टोपस"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"सर्पिल आवरण"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"बग"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"चींटी"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"मधुमक्खी"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"मादा भौंरा"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"मछली"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ट्रॉपिकल मछली"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ब्लॉफिश"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"कछुआ"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"हैचिंग चिक"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"छोटा चूज़ा"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"सामने की ओर चेहरा किया हुआ छोटा चूज़ा"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"पक्षी"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"पेंगुइन"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"कोआला"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"पूडल"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"ड्रॉमेडेरी ऊंट"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"बैक्ट्रीयन ऊंट"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"डॉल्फ़िन"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"चूहे का चेहरा"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"गाय का चेहरा"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"चीते का चेहरा"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"खरगोश का चेहरा"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ड्रेगन का चेहरा"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"स्पाउटिंग व्हेल"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"घोड़े का चेहरा"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"बंदर का चेहरा"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"कुत्ते का चेहरा"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"सुअर का चेहरा"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"मेंढक का चेहरा"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"हैम्स्टर का चेहरा"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"भेड़िये का चेहरा"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"भालू का चेहरा"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"पांडा का चेहरा"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"सुअर की नाक"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"पंजों के निशान"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"आंखें"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"कान"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"नाक"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"मुंह"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"जीभ"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"तर्जनी से ऊपर इंगित करता हाथ"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"तर्जनी से नीचे इंगित करता हाथ"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"तर्जनी से बाएं इंगित करता हाथ"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"तर्जनी से दाएं इंगित करता हाथ"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"मुठ्ठीबंद हाथ का चिह्न"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"हिलते हुए हाथ का चिह्न"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"ओके दर्शाने वाले हाथ का चिह्न"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"थंब्स अप का चिह्न"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"थंब्स डाउन का चिह्न"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"ताली बजाते हुए हाथ का चिह्न"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"खुले हाथ का चिह्न"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"मुकुट"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"महिलाओं की टोपी"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"आंखों का चश्मा"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"गले की टाइ"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"टी-शर्ट"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"जीन्स"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"पोशाक"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"किमोनो"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"बिकनी"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"महिलाओं के कपड़े"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"बटुआ"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"हैंडबेग"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"पाउच"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"पुरुषों के जुते"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"एथलेटिक जूते"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ऊंची एड़ी वाला जूता"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"महिलाओं की सैंडल"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"महिलाओं के बूट"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"पैर के निशान"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"वक्ष की रूपरेखा"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"वक्षों की रूपरेखा"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"लड़का"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"लड़की"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"मनुष्य"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"महिला"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"परिवार"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"हाथ पकड़े हुए महिला और पुरुष"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"हाथ पकड़े हुए दो पुरुष"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"हाथ पकड़े हुए दो महिलाएं"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"पुलिस अधिकारी"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"खरगोश के कानों वाली महिला"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"पर्दे वाली दुल्हन"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"सुनहरे बालों वाला व्यक्ति"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"गुआ पि माओ वाला व्यक्ति"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"पगड़ी वाला व्यक्ति"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"बूढ़ा आदमी"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"बूढ़ी महिला"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"बच्‍चा"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"ठेकेदारी मजदूर"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"राजकुमारी"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"जापानी राक्षस"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"जापानी गोब्लिन"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"भूत"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"नन्हा फरिश्ता"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"परग्रही एलियन"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"एलियन राक्षस"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"बौना"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"खोपड़ी"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"जानकारी डेस्क पर मौजूद व्यक्ति"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"संतरी"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"नर्तक"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"लिपस्टिक"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"नैल पॉलिश"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"चेहरे की मसाज"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"बाल काटना"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"नाई की दुकान"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"सिरिंज"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"पिल"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"चुबंन चिह्न"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"प्रेम पत्र"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"अंगूठी"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"जेम स्टोन"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"चुंबन"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"गुलदस्‍ता"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"दिल वाला जोड़ा"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"विवाह"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"धड़कता दिल"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"टूटा हुआ दिल"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"दो दिल"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"चमकता दिल"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"बढ़ता हुआ दिल"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"तीर वाला दिल"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"नीला दिल"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"हरा दिल"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"पीला दिल"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"बैंगनी दिल"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"रिबन वाला दिल"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"घूमने वाला दिल"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"सजावट वाला दिल"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"अंदर एक डॉट के साथ हीरे का आकार"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"बिजली का बल्ब"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"गुस्से का प्रतीक"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"बम"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"सोने का प्रतीक"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"टकराव का प्रतीक"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"पसीने के छींटे का प्रतीक"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"बूंद का प्रतीक"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"डैश प्रतीक"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"मल का ढेर"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"हाथ की उभरी हुई मांसपेशियां"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"भ्रमित प्रतीक"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"स्पीच बलून"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"विचारों का बलून"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"सफेद फूल"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"सौ बिंदुओं का प्रतीक"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"पैसों का झोला"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"मुद्रा विनिमय"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"डॉलर का मोटा चिह्न"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"क्रेडिट कार्ड"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"येन चिह्न वाला बैंकनोट"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"डॉलर चिह्न वाला बैंकनोट"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"यूरो चिह्न वाला बैंकनोट"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"पाउंड चिह्न वाला बैंकनोट"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"पंखों वाला पैसा"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"ऊपरी रुझान और येन चिह्न वाला चार्ट"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"सीट"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"व्यक्तिगत कंप्यूटर"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"ब्रीफकेस"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"मिनीडिस्क"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"फ्लॉपी डिस्क"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ऑप्टिकल डिस्क"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"फ़ाइल फ़ोल्डर"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"खुला फ़ाइल फ़ोल्डर"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"मुड़ा हुआ पृष्ठ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"पृष्ठ का सामने वाला भाग"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"कैलेंडर"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"टीयर-ऑफ़ कैलेंडर"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"कार्ड अनुक्रमणिका"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"ऊपरी रूझान वाला चार्ट"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"नीचे रूझान वाला चार्ट"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"बार चार्ट"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"क्लिपबोर्ड"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"पुशपिन"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"गोलाकार पुशपिन"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"पेपरक्लिप"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"सीधी पट्टी"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"त्रिभूजाकार पट्टी"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"बुकमार्क टैब"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"लेजर"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"नोटबुक"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"सजावटी कवर वाली नोटबुक"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"बंद पुस्तिका"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"खुली किताब"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"हरी किताब"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"नीली किताब"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"नारंगी किताब"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"किताबें"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"नाम बैज"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"स्क्रॉल"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"मेमो"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"टेलीफोन रिसीवर"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"पेजर"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"फैक्स मशीन"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"सैटेलाइट एंटीना"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"सार्वजनिक संबोधन लाउडस्पीकर"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"चीयरिंग मेगाफोन"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"आउटबॉक्स ट्रे"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"इनबॉक्स ट्रे"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"पैकेज"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ईमेल चिह्न"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"इनकमिंग लिफाफा"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ऊपर से नीचे तीर वाला लिफाफा"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"झुके हुए झंडे वाला बंद मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"उठे हुए झंडे वाला बंद मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"उठे हुए झंडे वाला खुला मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"झुके हुए झंडे वाला खुला मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"पोस्टबॉक्स"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"पोस्टल होर्न"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"समाचारपत्र"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"मोबाइल फ़ोन"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"बाईं ओर तीर वाला मोबाइल फ़ोन"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"कंपन मोड"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"बंद मोबाइल फोन"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"कोई मोबाइल फ़ोन नहीं"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"बार वाला एंटीना"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"कैमरा"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"वीडियो कैमरा"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"टेलीविज़न"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"रेडियो"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"वीडियो कैसेट"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"दाई ओर मुड़े तीर"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"दाईं एवं बाईं ओर मुड़े खुले चक्र तीर"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"एक अधिव्यापन से घेरेनुमा घड़ी की दिशा में बाईं ओर एवं दाईं ओर खुले गोल चिह्न"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"घड़ी की सुई की दिशा में नीचे एवं ऊपर की ओर खुले चक्रिय तीर"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"घड़ी की विपरीत दिशा में नीचे एवं ऊपर की ओर खुले चक्र तीर"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"कम चमकीले वाले प्रतीक"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"अधिक चमकीले प्रतीक"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"रद्दीकारण स्ट्रोक वाले स्पीकर"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"स्‍पीकर"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"एकल ध्वनि तरंग वाले स्पीकर"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"तीन ध्वनि तरंगों वाले स्पीकर"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"बैटरी"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"इलैक्ट्रिक प्लग"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"बाईं ओर इंगित करता हुआ आवर्धक कांच"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"दाईं ओर इंगित करता हुआ आवर्धक कांच"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"इंक पेन वाला लॉक"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"कुंजी वाला बंद किया लॉक"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"कुंजी"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"लॉक करें"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"खुला लॉक"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"घंटी"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"रद्दीकरण स्ट्रोक वाली घंटी"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"बुकमार्क"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"लिंक प्रतीक"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"रेडियो बटन"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"ऊपर बाईंओर तीर के साथ वापस"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"ऊपर बाई ओर तीर के साथ वापस"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ऊपर बाएं दाएं तीर वाले विस्मयादिबोधक चिह्न पर"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"जल्द ही ऊपर बाईं ओर के तीर के साथ"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"ऊपर की ओर तीर वाला टोप"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"अठारह प्रतीक के अंतर्गत कोई नहीं"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"कीकैप टेन"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"लैटिन बड़े अक्षराें के लिए इनपुट प्रतीक"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"लैटिन छोटे अक्षरों के लिए इनपुट प्रतीक"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"संख्याओं के लिए इनपुट प्रतीक"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"प्रतीकों के लिए इनपुट प्रतीक"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"लैटिन अक्षरों के लिए इनपुट प्रतीक"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"आग"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"इलैक्ट्रिक टॉर्च"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"पाना"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"हथौड़ा"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"नट और बोल्ट"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"होचो"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"पिस्टल"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"सूक्ष्मदर्शी यंत्र"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"टेलीस्कोप"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"क्रिस्टल बॉल"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"मध्य बिंदु के साथ छ: सलाखों वाला तारा"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"आरंभक के लिए जापानी प्रतीक"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"त्रिशूल चिह्न"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"काला चौकोर बटन"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"सफेद चौकोर बटन"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"बड़ा लाल घेरा"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"बड़ा नीला घेरा"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"बड़ा नारंगी हीरा"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"बड़ा नीला हीरा"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"छोटा नारंगी हीरा"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"छोटा नीला हीरा"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"ऊपर इंगित करने वाला लाल त्रिभुज"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"नीचे इंगित करने वाला लाल त्रिभुज"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"ऊपर इंगित करने वाला छोटा लाल त्रिभुज"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"नीचे इंगित करने वाला छोटा लाल त्रिभुज"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"घड़ी का डायल एक बजे"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"घड़ी का डायल दो बजे"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"घड़ी का डायल तीन बजे"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"घड़ी का डायल चार बजे"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"घड़ी का डायल पांच बजे"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"घड़ी का डायल छ: बजे"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"घड़ी का डायल सात बजे"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"घड़ी का डायल आठ बजे"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"घड़ी का डायल नौ बजे"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"घड़ी का डायल दस बजे"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"घड़ी का डायल ग्यारह बजे"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"घड़ी का डायल बारह बजे"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"घड़ी का डायल डेढ़ बजे"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"घड़ी का डायल ढाई बजे"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"घड़ी का डायल साढ़े तीन बजे"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"घड़ी का डायल साढ़े चार बजे"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"घड़ी का डायल साढ़े पांच बजे"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"घड़ी का डायल साढ़े छ:"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"घड़ी का डायल साढ़े सात"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"घड़ी का डायल साढ़े आठ"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"घड़ी का डायल साढ़े नौ"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"घड़ी का डायल साढ़े दस"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"घड़ी का डायल साढ़े ग्यारह"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"घड़ी का डायल साढ़े बारह"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"माउंट फुजी"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"टोकियो टावर"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"स्टैच्यू ऑफ़ लिबर्टी"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"जापान का छायाचित्र"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"मोयाई"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"बनावटी चेहरा"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"मुस्कुराती आंखों वाला दांत दिखाता चेहरा"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"खुशी के आंसु वाला चेहरा"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"खुले चेहरा वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"खुले चेहरा और हंसती आंखों वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"खुले चेहरा और पसीने वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"खुले चेहरा और कसके बंद हुई आंखों वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"हालो वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"सींगो वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"पलक झपकाता चेहरा"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"हंंसती आंखाें वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"स्वादिष्ट भोजन का आनंद लेता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"चिंता मुक्त चेहरा"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"हृदयाकार आंखों वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"सनग्लास वाला हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"बनावटी हंसी वाला चेहरा"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"उदासीन चेहरा"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"भावहीन चेहरा"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"नाराज़ चेहरा"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"पसीने वाला चेहरा"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"विचारमग्न चेहरा"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"उलझन भरा चेहरा"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"हैरान चेहरा"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"चुमता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"चुंबन करता चेहरा"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"हंसती आंखों वाला चुमता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"बंद आंखों वाला चुमता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"बाहर निकली जीभ वाला चेहरा"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"बाहर निकली जीभ और आंख मारता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"बाहर निकली जीभ और कसकर बंद की हुई आंखों वाला चेहरा"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"उदास चेहरा"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"चिंतित चेहरा"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"गुस्से वाला चेहरा"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"चेहरा फुलाया हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"रोता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"दृढ़ चेहरा"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"विजयी मुद्रा वाला चेहरा"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"उदास लेकिन चिंतामुक्त चेहरा"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"खुले चेहरा वाला क्रोधित चेहरा"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"दुखी चेहरा"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"क्रोधित चेहरा"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"घबराया हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"सोता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"थका हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"चेहरा बनाता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"जोर से रोता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"खुले चेहरा वाला चेहरा"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"निस्तब्ध चेहरा"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"खुला चेहरा और पसीने से भीगा चेहरा"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"क्रोध से रोता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"हैरान चेहरा"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"उत्तेजित चेहरा"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"सोता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"भौचक चेहरा"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"बिना चेहरा वाला चेहरा"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"मेडिकल मास्क वाला चेहरा"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"हंसती आंखों वाला मुस्कराता बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"खुशी के आंसु वाला बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"खुले चेहरा वाला बिल्ली का हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"हृदयाकार आंखों वाला बिल्ली का हंसता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"राइ मुस्कान वाला बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"बंद आंखों वाला बिल्ली का चुमता हुआ चेहरा"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"खीझता हुआ बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"रोता हुआ बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"ऊबा हुआ बिल्ली का चेहरा"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"बिना अच्छी मुद्रा वाला चेहरा"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"ठीक है कि मुद्रा वाला चेहरा"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"बहुत अधिक झुकता हुआ व्यक्ति"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"बूरा न देखो वाला बंदर"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"बूरा न सुनो वाला बंदर"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"बूरा न बोलो वाला बंदर"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"एक हाथ उठाता हुआ खुश व्यक्ति"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"खुशी में दोनों हाथ उठाए हुए व्यक्ति"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"क्रोधित व्यक्ति"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"खीझते चेहरे वाला व्यक्ति"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"बंद हाथाें वाला व्यक्ति"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"रॉकेट"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"हैलीकॉप्टर"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"भाप लोकोमोटीव"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"रेलवे कार"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"अधिक गति वाली ट्रेन"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"गोली जैसी नाक वाली उच्च गति की ट्रेन"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"रेलगाड़ी"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"मेट्रो"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"हल्की रेल"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"स्टेशन"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ट्राम"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ट्राम कार"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"बस"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"आती हुई बस"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ट्रॉलीबस"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"बस स्टॉप"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"मिनीबस"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"एम्बुलेंस"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"दमकल"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"पुलिस कार"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"आती हुई पुलिस कार"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"टैक्सी"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"आती हुई टैक्सी"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"ऑटोमोबाइल"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"आता हुआ ऑटोमोबाइल"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"मनोरंजात्मक वाहन"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"डिलीवरी ट्रक"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ट्रेलर ट्रक"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ट्रैक्टर"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"मोनोरेल"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"पर्वतीय रेलवे"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"सस्पेंशन रेलवे"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"माउंटेन केबलवे"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"एरीयल ट्रामवे"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"शिप करें"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"रोबोट"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"स्पीडबोट"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"क्षैतिज ट्रैफ़िक लाइट"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"उर्ध्वाधर ट्रैफ़िक लाइट"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"निर्माण चिह्न"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"घुमती हुई लाइट वाली पुलिस कार"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"पोस्ट पर तिरंगा झंडा"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"दरवाजा"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"प्रवेश नहीं चिह्न"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"धुम्रपान करता हुआ व्यक्ति"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"धूम्रपान निषेध प्रतीक"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"इस स्थान पर कचरा रखें वाला प्रतीक"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"कचरा न करें वाला प्रतीक"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"पेयजल प्रतीक"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"अपेयजल प्रतीक"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"साइकिल"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"कोई साइकिल नहीं"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"साइक्लिस्ट"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"माउंटेन साइक्लिस्ट"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"पैदल यात्री"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"कोई पैदल यात्री नहीं"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"पार करते हुए बच्चे"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"पुरुष प्रतीक"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"महिला प्रतीक"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"शौचालय"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"बच्चों का प्रतीक"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"शौचालय"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"शौचालय"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"शोवर"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"स्नान"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"बाथटब"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"पासपोर्ट नियंत्रण"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"प्रथाएं"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"सामान पर दावा"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"शेष सामान"</string>
+</resources>
diff --git a/java/res/values-hi/strings-letter-descriptions.xml b/java/res/values-hi/strings-letter-descriptions.xml
index ecf589a..1e817fd 100644
--- a/java/res/values-hi/strings-letter-descriptions.xml
+++ b/java/res/values-hi/strings-letter-descriptions.xml
@@ -200,7 +200,7 @@
     <string name="spoken_symbol_2105" msgid="7289404939366976829">"द्वारा"</string>
     <string name="spoken_symbol_2192" msgid="827804523596125414">"दायां तीर"</string>
     <string name="spoken_symbol_2193" msgid="2659541693445985717">"नीचे तीर"</string>
-    <string name="spoken_symbol_2205" msgid="4457188084269117343">"रिक्त सेट"</string>
+    <string name="spoken_symbol_2205" msgid="4457188084269117343">"खाली सेट"</string>
     <string name="spoken_symbol_2206" msgid="4856786565708380687">"वृद्धि"</string>
     <string name="spoken_symbol_2264" msgid="5092061257745123554">"इससे कम या इसके बराबर"</string>
     <string name="spoken_symbol_2265" msgid="1907966479878036357">"इससे अधिक या इसके बराबर"</string>
diff --git a/java/res/values-hi/strings-talkback-descriptions.xml b/java/res/values-hi/strings-talkback-descriptions.xml
index aba2592..1ae49c8 100644
--- a/java/res/values-hi/strings-talkback-descriptions.xml
+++ b/java/res/values-hi/strings-talkback-descriptions.xml
@@ -21,10 +21,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="spoken_use_headphones" msgid="4313642710742229868">"जोर से बोली जाने वाली पासवर्ड कुंजियां सुनने के लिए हैडसेट प्‍लग करें."</string>
-    <string name="spoken_current_text_is" msgid="4240549866156675799">"वर्तमान पाठ %s है"</string>
-    <string name="spoken_no_text_entered" msgid="1711276837961785646">"कोई पाठ नहीं डाला गया"</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"वर्तमान लेख %s है"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"कोई लेख नहीं डाला गया"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> को सुधार कर <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> करता है"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> स्वत: सुधार करता है"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"कोई सुझाव नहीं"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"अज्ञात वर्ण"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"शिफ़्ट"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"और प्रतीक"</string>
@@ -44,7 +45,7 @@
     <string name="spoken_description_search" msgid="5099937658231911288">"खोजें"</string>
     <string name="spoken_description_dot" msgid="5644176501632325560">"डॉट"</string>
     <string name="spoken_description_language_switch" msgid="6818666779313544553">"भाषा स्विच करें"</string>
-    <string name="spoken_description_action_next" msgid="431761808119616962">"अगला"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"आगे"</string>
     <string name="spoken_description_action_previous" msgid="2919072174697865110">"पिछला"</string>
     <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"शिफ़्ट सक्षम किया गया"</string>
     <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"कैप्स लॉक सक्षम किया गया"</string>
@@ -61,7 +62,7 @@
     <string name="keyboard_mode_im" msgid="3812086215529493501">"संदेश सेवा"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"संख्या"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"फ़ोन"</string>
-    <string name="keyboard_mode_text" msgid="9138789594969187494">"पाठ"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"लेख"</string>
     <string name="keyboard_mode_time" msgid="8558297845514402675">"समय"</string>
     <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
     <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"हाल ही के"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"बड़ा आई, बिंदु ऊपर"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"अज्ञात प्रतीक"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"अज्ञात इमोजी"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"उदास चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"शर्मिंदा चेहरा"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"चश्मा पहना हुआ चेहरा"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"अचंभित चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"चूमता हुआ चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"क्रोधित चेहरा"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"वैकल्पिक वर्ण उपलब्ध हैं"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"वैकल्पिक वर्ण ख़ारिज कर दिए जाते हैं"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"वैकल्पिक सुझाव उपलब्ध हैं"</string>
diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml
index 5abbecd..6c2b84a 100644
--- a/java/res/values-hi/strings.xml
+++ b/java/res/values-hi/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"कुंजी दबाने पर कंपन करता है"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"कुंजी दबाने पर आवाज"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"कुंजी दबाने पर पॉपअप दिखाएं"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"प्राथमिकताएं"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"खाते और गोपनीयता"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"दिखावट और सज्जा"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"हावभाव लेखन"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"लेख सुधार"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"अतिरिक्त सेटिंग"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"थीम"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"स्प्लिट कीबोर्ड सक्षम करें"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google कीबोर्ड समन्‍वयन"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"समन्‍वयन चालू किया गया है"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"अपना व्‍यक्‍तिगत शब्‍दकोश सभी डिवाइसों में समन्‍वयित करें"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"अभी समन्वयन करें"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"क्‍लाउड डेटा हटाएं"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google से आपका समन्वयित डेटा हटाता है"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"आपका समन्‍वयित डेटा क्‍लाउड से हटा दिया जाएगा. आप सुनिश्‍चित हैं?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"हटाएं"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"अभी नहीं"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"आपका व्यक्तिगत शब्दकोश Google सर्वरों पर समन्वयित किया जाएगा और उसका बैक अप लिया जाएगा. हमारे उत्पादों को बेहतर बनाने में सहायता करने के लिए शब्द को दोहराने की सांख्यिकीय जानकारी एकत्र की जा सकती है. सभी जानकारी को एकत्र करना और उपयोग करना "<a href="https://www.google.com/policies/privacy">"Google की गोपनीयता नीति"</a>" के अनुपालन में होगा."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"यह सुविधा सक्षम करने के लिए इस डिवाइस पर एक Google खाता जोड़ें"</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">"भाषा स्‍विच कुंजी में अन्‍य इनपुट पद्धतियां भी शामिल हैं"</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">"स्लाइड संकेतक दिखाएं"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"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>
@@ -57,14 +62,11 @@
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"स्पेसबार पर डबल टैप करने से पीरियड शामिल हो जाता है जिसके बाद एक रिक्ति होती है"</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="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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"ध्‍वनि‍ इनपुट कुंजी"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"कोई ध्वनि इनपुट पद्धति सक्षम नहीं है. भाषा और इनपुट सेटिंग जांचें."</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="language_selection_title" msgid="3666971864764478269">"भाषाएं"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"सहायता और फ़ीडबैक"</string>
+    <string name="select_language" msgid="5709487854987078367">"भाषाएं"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"सहेजने के लिए पुन: स्‍पर्श करें"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"सहेजने के लिए यहां स्पर्श करें"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्‍दकोश उपलब्‍ध है"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"खाते स्‍विच करें"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"कोई खाता नहीं चुना गया"</string>
+    <string name="account_selected" msgid="2846876462199625974">"वर्तमान में <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> का उपयोग कर रहा है"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ठीक"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"अभी नहीं"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"प्रस्थान करें"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"उपयोग करने के लिए कोई खाता चुनें"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेज़ी (यूके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेज़ी (यूएस)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पेनिश (यूएस)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिंग्लिश"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"सर्बियाई (लैटिन)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"अंग्रेज़ी (यूके) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"अंग्रेज़ी (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्‍पेनिश (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियाई (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपरिक)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (लैटिन)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (संक्षिप्त)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"भाषा उपलब्ध नहीं है (लैटिन वर्णाक्षर)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णाक्षर (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णाक्षर (QWERTZ)"</string>
@@ -108,35 +121,21 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"वर्णाक्षर (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"वर्णाक्षर (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"कीबोर्ड थीम"</string>
     <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="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_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="4782116251651288054">"क्या वाकई <xliff:g id="LANGUAGE_NAME">%s</xliff:g> के लिए यह फ़ाइल इंस्‍टॉल करें?"</string>
-    <string name="error" msgid="8940763624668513648">"कोई त्रुटि हुई थी"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"कुंजी को देर तक दबाने का विलंब"</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>
@@ -144,18 +143,16 @@
     <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_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_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">"अब आप <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">"लॉन्चर में ऐप्स  आइकन प्रदर्शित करें"</string>
     <string name="app_name" msgid="6320102637491234792">"डिक्‍शनरी प्रदाता"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"डिक्‍शनरी प्रदाता"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"डिक्‍शनरी सेवा"</string>
@@ -176,18 +173,18 @@
     <string name="message_updating" msgid="4457761393932375219">"नई जानकारी देखा जा रहा हैं"</string>
     <string name="message_loading" msgid="5638680861387748936">"लोड हो रहा है…"</string>
     <string name="main_dict_description" msgid="3072821352793492143">"मुख्‍य डिक्‍शनरी"</string>
-    <string name="cancel" msgid="6830980399865683324">"रद्द करें"</string>
+    <string name="cancel" msgid="6830980399865683324">"अभी नहीं"</string>
     <string name="go_to_settings" msgid="3876892339342569259">"सेटिंग"</string>
     <string name="install_dict" msgid="180852772562189365">"इंस्टॉल करें"</string>
-    <string name="cancel_download_dict" msgid="7843340278507019303">"रद्द करें"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"अभी नहीं"</string>
     <string name="delete_dict" msgid="756853268088330054">"हटाएं"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"आपके मोबाइल पर चयनित भाषा के लिए शब्‍दकोश उपलब्‍ध है.&lt;br/&gt; हम आपके लेखन अनुभव को बेहतर बनाने के लिए <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्‍दकोश &lt;b&gt;डाउनलोड करने&lt;/b&gt; की अनुशंसा करते हैं.&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="should_download_over_metered_prompt" msgid="1583881200688185508">"आपके मोबाइल पर चयनित भाषा के लिए शब्‍दकोश उपलब्‍ध है.&lt;br/&gt; हम आपके लेखन अनुभव को बेहतर बनाने के लिए <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्‍दकोश &lt;b&gt;डाउनलोड करने&lt;/b&gt; की सुझाव देते हैं.&lt;br/&gt; &lt;br/&gt; 3G में डाउनलोड करने पर एक या दो मिनट लगेंगे. यदि आपके पास &lt;b&gt;असीमित डेटा योजना&lt;/b&gt; नहीं है, तो शुल्क लागू हो सकते हैं.&lt;br/&gt; यदि आप अपनी डेटा योजना के बारे में सुनिश्चित नहीं हैं, तो हम अपने आप डाउनलोड प्रारंभ करने के लिए वाई-फ़ाई  कनेक्‍शन ढूंढने की सुझाव देते हैं.&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>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi से डाउनलोड करें"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"वाई-फ़ाई  से डाउनलोड करें"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> के लिए एक शब्‍दकोश उपलब्‍ध है"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"समीक्षा करने और डाउनलोड करने के लिए दबाएं"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"डाउनलोड प्रारंभ हो रहा है: <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> के लिए सुझाव जल्दी ही उपलब्ध होंगे."</string>
-    <string name="version_text" msgid="2715354215568469385">"संस्करण <xliff:g id="VERSION_NUMBER">%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>
diff --git a/java/res/values-hr/strings-emoji-descriptions.xml b/java/res/values-hr/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..aee3901
--- /dev/null
+++ b/java/res/values-hr/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Znak autorskih prava"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Znak \"registrirano\""</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dvostruki uskličnik"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Uskličnik i upitnik"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Zaštitni znak (™)"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Izvor informacija"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Strelica lijevo-desno"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Strelica gore-dolje"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Strelica koja pokazuje \"sjeverozapad\""</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Strelica koja pokazuje \"sjeveroistok\""</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Strelica koja pokazuje \"jugoistok\""</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Strelica koja pokazuje \"jugozapad\""</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Strelica ulijevo s kukom"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Strelica udesno s kukom"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Sat"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Pješčani sat"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Dvostruki trokut koji pokazuje ulijevo i udesno"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Crni dvostruki trokut koji pokazuje ulijevo"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Crni dvostruki trokut koji pokazuje prema gore"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Crni dvostruki trokut koji pokazuje prema dolje"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Budilica"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Pješčani sat s pijeskom koji curi"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Zaokruženo latinično veliko slovo m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Maleni crni kvadrat"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Maleni bijeli kvadrat"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Crni trokut koji pokazuje udesno"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Crni trokut koji pokazuje ulijevo"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Bijeli srednji kvadrat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Crni srednji kvadrat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Bijeli srednje mali kvadrat"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Crni srednje mali kvadrat"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Crno sunce sa zrakama"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Oblak"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Crni telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Glasački okvir s kvačicom"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Kišobran s kišnim kapima"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Topli napitak"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Bijeli kažiprst koji pokazuje prema gore"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Bijelo nasmiješeno lice"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Ovan"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Bik"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Blizanci"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rak"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lav"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Djevica"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Vaga"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Škorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Strijelac"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Jarac"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vodenjak"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ribe"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Karte crni pik"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Karte crni tref"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Karte crni herc"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Karte crni karo"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Topli izvori"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Crni univerzalni simbol recikliranja"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Simbol za osobe u invalidskim kolicima"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Sidro"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Znak upozorenja"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Znak visokog napona"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Srednji bijeli krug"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Srednji crni krug"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Nogometna lopta"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bejzbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snjegović bez snijega"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sunce iza oblaka"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Sazvježđe Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Zabranjen ulaz"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Crkva"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontana"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Zastava u rupi"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Jedrilica"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Šator"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Benzinska crpka"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Crne škare"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Masno otisnuta bijela kvačica"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Zrakoplov"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Omotnica"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Podignuta šaka"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Podignuti dlan"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Pobjednička ruka"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Olovka"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Crno pero"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Masno otisnuta kvačica"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Masno otisnuto slovo x koje označava množenje"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Iskre"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Osmerokraka zvjezdica"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Osmerokraka crna zvijezda"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snježna pahuljica"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Iskra"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Znak križa"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Križić u kvadratu koji označava negaciju"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Ukras u obliku crnog upitnika"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ukras u obliku bijelog upitnika"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ukras u obliku bijelog uskličnika"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Masno otisnuti znak uskličnika"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Teško crno srce"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Masno otisnuti znak plus"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Masno otisnuti znak minus"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Masno otisnuti znak dijeljenja"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Crna strelica udesno"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Vitičasta petlja"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dvostruka vitičasta petlja"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Strelica koja pokazuje udesno, a zatim se zakrivljuje prema gore"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Strelica koja pokazuje udesno, a zatim se zakrivljuje prema dolje"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Crna strelica ulijevo"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Crna strelica gore"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Crna strelica dolje"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Veliki crni kvadrat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Veliki bijeli kvadrat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Bijela srednja zvijezda"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Veliki masno otisnuti krug"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Valovita crtica"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Oznaka djelomične alternacije"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Zaokruženi ideogram \"čestitke\""</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Zaokruženi ideogram \"tajna\""</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong pločica crveni zmaj"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Igraća karta crni joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Krvna grupa A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Krvna grupa B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Krvna grupa 0"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkiralište"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Krvna grupa AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"\"CL\" u kvadratu"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"\"Cool\" u kvadratu"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"\"Free\" u kvadratu"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"\"ID\" u kvadratu"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"\"New\" u kvadratu"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"\"N G\" u kvadratu"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"\"OK\" u kvadratu"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"\"SOS\" u kvadratu"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"\"Up\" s uskličnikom u kvadratu"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"\"Vs\" u kvadratu"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Ovdje dolazi \"katakana\" u kvadratu"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"\"Katakana service\" u kvadratu"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogram \"besplatno\" u kvadratu"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogram \"rezervirano sjedalo\" u kvadratu"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogram zabrane u kvadratu"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogram slobodnog mjesta u kvadratu"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogram prihvaćanja u kvadratu"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogram potpune popunjenosti u kvadratu"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogram \"plaćeno\" u kvadratu"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogram \"mjesečno\" u kvadratu"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogram aplikacije u kvadratu"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogram popusta u kvadratu"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogram poslovanja u kvadratu"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Zaokruženi ideogram prednosti"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Zaokruženi ideogram prihvaćanja"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Maglovito"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Zatvoreni kišobran"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Zvjezdana noć"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Izlazak sunca iznad planina"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Izlazak sunca"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Slika grada u sumrak"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Zalazak sunca iznad zgrada"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Duga"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Most noću"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vodeni val"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Mliječna staza"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Prikaz Europe i Afrike na globusu"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Prikaz Sjeverne i Južne Amerike na globusu"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Prikaz Azije i Australije na globusu"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globus s meridijanima"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbol mlađaka"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbol mladog mjeseca"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbol prve četvrti mjeseca"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbol posljednje četvrti mjeseca"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbol punog mjeseca"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbol prve četvrti mjeseca"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbol posljednje četvrti mjeseca"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbol balzamičkog mjeseca"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Polumjesec"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Mladi mjesec s licem"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Prva četvrt mjeseca s licem"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Posljednja četvrt mjeseca s licem"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Puni mjesec s licem"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sunce s licem"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Sjajna zvijezda"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Zvijezda padalica"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kesten"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Sadnica"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Zimzeleno drvo"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Bjelogorično drvo"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmino drvo"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Trešnjin cvijet"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Ruža"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Suncokret"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Cvjetanje"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Klas kukuruza"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Klas riže"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Biljka"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Četverolisna djetelina"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"List javora"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Otpali list"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"List koji treperi na vjetru"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Gljiva"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Rajčica"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Patlidžan"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Grožđe"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Dinja"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Lubenica"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limun"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Crvena jabuka"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zelena jabuka"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Kruška"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Breskva"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Višnje"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jagoda"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Kriška pizze"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Meso s kostima"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Pileći batak"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Keks od riže"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Kuglica od riže"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kuhana riža"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry i riža"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Kipuća zdjelica"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Špageti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Kruh"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Pomfrit"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pečeni batat"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Suši"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Prženi škamp"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Riblji kolač s motivom spirale"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Meki sladoled"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Sladoled s komadićima leda"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Sladoled"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Krafna"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Kolačić"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Čokoladna pločica"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bombon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lizaljka"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Krema od jaja"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Vrč s medom"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Biskvit"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento kutija"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Lonac s hranom"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Kuhanje"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Vilica i nož"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Šalica bez ručke"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Boca i čaša sa sakeom"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Čaša za vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Čaša za koktel"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropsko piće"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Krigla za pivo"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Zdravica kriglama piva"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Bočica za bebe"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Traka"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Umotani poklon"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Rođendanski kolač"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Izrezbarena bundeva"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Božićno drvce"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Djed Božićnjak"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Vatromet"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Prskalica"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Praskalo za tulume"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Kugla sa snijegom u boji"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Drvo tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Ukrštene zastave"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Ukras od šišarki"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanske lutke"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Cjevasti zmaj u obliku ribe"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vjetrena zvona"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Svečanost promatranja mjeseca"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Školska torba"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Maturalna kapa"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Konjić na vrtuljku"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Panoramski kotač"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Vlak smrti"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Štap za pecanje i riba"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmska kamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Slušalice"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Slikarska paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cilindar"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkuski šator"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ulaznica"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klapa"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Izvedbene umjetnosti"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videoigra"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Izravan pogodak"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Jednoruki Jack"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Igraća kocka"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Kuglanje"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Cvjetne igraće karte"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Glazbena nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Više glazbenih nota"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klavijatura"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Truba"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violina"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Notno crtovlje"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Majica za trčanje s oznakom trkača"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Teniski reket i loptica"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Skija i pancerica"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Košarkaška lopta i obruč"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Zastava sa šahovnicom"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Daskaš na snijegu"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Trkač"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofej"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Konjičke utrke"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Američki nogomet"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragbi nogomet"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Plivač"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Kuća"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Kuća s vrtom"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Uredska zgrada"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japanski poštanski ured"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europski poštanski ured"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Bolnica"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Ljubavni hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Trgovina mješovitom robom"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Škola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Robna kuća"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Tvornica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lampion izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japanski dvorac"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europski dvorac"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Štakor"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Miš"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Vol"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vodeni bizon"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Krava"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Zec"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Mačka"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Zmaj"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Kit"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Puž"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Zmija"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Konj"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ovan"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Koza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovca"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Majmun"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Pijetao"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kokoš"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Pas"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Svinja"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Vepar"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Slon"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Hobotnica"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiralna školjka"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Buba"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mrav"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Pčela"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Bubamara"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Riba"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropska ribica"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Riba balon"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Kornjača"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pile izleglo iz jajeta"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pile"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pile okrenuto prema naprijed"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ptica"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudlica"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Jednogrba deva"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Dvogrba deva"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dupin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Lice miša"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Lice krave"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Lice tigra"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Lice zeca"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Lice mačke"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Lice zmaja"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Kit koji izbacuje mlaz vode"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Lice konja"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Lice majmuna"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Lice psa"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Lice svinje"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Lice žabe"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Lice hrčka"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Lice vuka"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Lice medvjeda"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Lice pande"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Svinjski nos"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Otisci šape"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oči"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Uho"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nos"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Usta"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Jezik"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Bijeli kažiprst koji pokazuje prema gore"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Bijeli kažiprst koji pokazuje prema dolje"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Bijeli kažiprst koji pokazuje ulijevo"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Bijeli kažiprst koji pokazuje udesno"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Znak stisnute šake"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Znak ruke koja maše"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Znak šake koja pokazuje \"u redu\""</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Znak \"palac gore\""</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Znak \"palac dolje\""</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Znak ruku koje plješću"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Znak otvorenih ruku"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Kruna"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Ženski šešir"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Naočale"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kravata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Majica s kratkim rukavima"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Traperice"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Haljina"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Ženska odjeća"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Torbica"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Ručna torba"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Vrećica"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Muška cipela"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportska cipela"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Cipela s visokom potpeticom"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Ženska sandala"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Ženske čizme"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Otisci stopala"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Poprsje u silueti"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Poprsja u silueti"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Dječak"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Djevojčica"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Muškarac"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Žena"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Obitelj"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Muškarac i žena koji se drže za ruke"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dva muškarca koji se drže za ruke"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dvije žene koje se drže za ruke"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policajac"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Žena sa zečjim ušima"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Mladenka s velom"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Osoba plave kose"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Muškarac s kapom gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Muškarac s turbanom"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Stariji muškarac"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Starija žena"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Beba"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Građevinski radnik"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princeza"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanski div"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanski goblin"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Duh"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Beba anđeo"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Izvanzemaljac"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Izvanzemaljsko čudovište"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Vražićak"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Lubanja"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Službenik na infopultu"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Stražar"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Plesač"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Ruž za usne"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Lak za nokte"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masaža lica"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Frizura"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Stup koji označava brijačnicu"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Šprica"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilula"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Trag poljupca"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Ljubavno pismo"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Prsten"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Dragulj"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Poljubac"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Buket"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Par sa srcem"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Vjenčanje"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Srce koje kuca"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Slomljeno srce"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dva srca"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Svjetlucavo srce"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Srce koje raste"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Srce sa strelicom"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Plavo srce"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zeleno srce"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Žuto srce"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Ljubičasto srce"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Srce s trakom"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Srca koja kruže"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Ukras srca"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Oblik dijamanta s točkom"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Električna žarulja"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Simbol ljutnje"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Simbol spavanja"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Simbol sudara"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Sličica prskanja znoja"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Kapljica"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Znak crtice"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Hrpica izmeta"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Napeti biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Simbol vrtoglavice"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Balončić za tekst govora"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Balončić za tekst misli"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Bijeli cvijet"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbol za sto bodova"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Vreća s novcem"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Mjenjačnica"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Masno otisnuti znak dolara"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditna kartica"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Novčanica sa znakom jena"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Novčanica sa znakom dolara"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Novčanica sa znakom eura"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Novčanica sa znakom funte"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Novac s krilima"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Grafikon s uzlaznim trendom i znakom jena"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sjedalo"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Osobno računalo"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktovka"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketa"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optički disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Mapa"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Otvori mapu datoteka"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Savinuta stranica"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Stranica okrenuta prema gore"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendar"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Kalendar na trganje"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Indeks kartica"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Grafikon s uzlaznim trendom"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Grafikon sa silaznim trendom"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Stupčasti grafikon"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Međuspremnik"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pribadača"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Zaobljena pribadača"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Spajalica"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Ravnalo"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trokutno ravnalo"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Jezičci knjiških oznaka"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Glavna knjiga"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Bilježnica"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Bilježnica s ukrasnim omotom"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Zatvorena knjiga"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Otvorena knjiga"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zelena knjiga"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Plava knjiga"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Narančasta knjiga"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Knjige"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Bedž s imenom"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Pomicanje"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Dopis"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonski prijemnik"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Dojavljivač"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faks"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelitska antena"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Megafon"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Navijački megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Ladica izlazne pošte"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Ladica dolazne pošte"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Simbol e-pošte"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Omotnica dolazne pošte"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Omotnica sa strelicom odozgo prema dolje"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Zatvoreni poštanski sandučić sa spuštenom zastavicom"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Zatvoreni poštanski sandučić s podignutom zastavicom"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Otvoreni poštanski sandučić s podignutom zastavicom"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Otvoreni poštanski sandučić sa spuštenom zastavicom"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Poštanski sandučić"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Poštanska truba"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Novine"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobitel"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobitel sa strelicom udesno u lijevom dijelu"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Način vibracije"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobitel je isključen"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Bez mobitela"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena s crticama"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoaparat"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokaseta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Zakrivljene strelice udesno"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Otvoreni krug strelica ulijevo i udesno u smjeru kazaljke na satu"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Otvoreni krug strelica ulijevo i udesno u smjeru kazaljke na satu s jedinicom u krugu"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Otvoreni krug strelica prema gore i prema dolje u smjeru kazaljke na satu"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Otvoreni krug strelica prema gore i prema dolje suprotno od kazaljke na satu"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbol niske svjetline"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbol visoke svjetline"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Zvučnik s linijom isključenja"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Zvučnik"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Zvučnik s jednim zvučnim valom"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Zvučnik s tri zvučna vala"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Baterija"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Strujni utikač"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Povećalo usmjereno ulijevo"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Povećalo usmjereno udesno"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lokot s naliv-perom"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Zatvoreni lokot s ključem"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ključ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lokot"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Otvoreni lokot"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zvono"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Zvono s linijom isključenja"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Oznaka"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Simbol veze"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Izborni gumb"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Natpis \"Back\" sa strelicom lijevo iznad njega"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Natpis \"End\" sa strelicom lijevo iznad njega"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Natpis \"On\" s uskličnikom i strelicom lijevo-desno iznad njega"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Natpis \"Soon\" sa strelicom desno iznad njega"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Natpis \"Top\" sa strelicom gore iznad njega"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbol \"zabranjeno mlađima od osamnaest\""</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Kapica tipke s oznakom \"deset\""</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Simbol unosa za velika latinična slova"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Simbol unosa za mala latinična slova"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Simbol unosa za brojeve"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Ulazni simbol za simbole"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Simbol unosa za latinična slova"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Vatra"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Električna svjetiljka"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Ključ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Čekić"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Matica i vijak"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Nož hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pištolj"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikrofon"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristalna kugla"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Šesterokraka zvijezda s točkom u sredini"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japanski simbol za početnika"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Znak trozupca"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Gumb s crnim kvadratom"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Gumb s bijelim kvadratom"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Veliki crveni krug"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Veliki plavi krug"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Veliki narančasti dijamant"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Veliki plavi dijamant"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Maleni narančasti dijamant"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Maleni plavi dijamant"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Crveni trokut koji pokazuje prema gore"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Crveni trokut koji pokazuje prema dolje"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Maleni crveni trokut koji pokazuje prema gore"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Maleni crveni trokut koji pokazuje prema dolje"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Brojčanik sata koji pokazuje \"jedan sat\""</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Brojčanik sata koji pokazuje \"dva sata\""</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Brojčanik sata koji pokazuje \"tri sata\""</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Brojčanik sata koji pokazuje \"četiri sata\""</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Brojčanik sata koji pokazuje \"pet sati\""</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Brojčanik sata koji prikazuje \"šest sati\""</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Brojčanik sata koji prikazuje \"sedam sati\""</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Brojčanik sata koji prikazuje \"osam sati\""</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Brojčanik sata koji prikazuje \"devet sati\""</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Brojčanik sata koji prikazuje \"deset sati\""</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Brojčanik sata koji prikazuje \"jedanaest sati\""</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Brojčanik sata koji prikazuje \"dvanaest sati\""</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Brojčanik sata koji prikazuje \"jedan i trideset\""</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Brojčanik sata koji prikazuje \"dva i trideset\""</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Brojčanik sata koji prikazuje \"tri i trideset\""</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Brojčanik sata koji prikazuje \"četiri i trideset\""</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Brojčanik sata koji prikazuje \"pet i trideset\""</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Brojčanik sata koji prikazuje \"šest i trideset\""</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Brojčanik sata koji prikazuje \"sedam i trideset\""</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Brojčanik sata koji prikazuje \"osam i trideset\""</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Brojčanik sata koji prikazuje \"devet i trideset\""</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Brojčanik sata koji prikazuje \"deset i trideset\""</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Brojčanik sata koji prikazuje \"jedanaest i trideset\""</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Brojčanik sata koji prikazuje \"dvanaest i trideset\""</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Planina Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokijski toranj"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Kip slobode"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Obris Japana"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Nasmiješeno lice"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Nasmiješeno lice"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Lice sa suzama radosnicama"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Nasmiješeno lice s otvorenim ustima"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Nasmiješeno lice s otvorenim ustima i nasmiješenim očima"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Nasmiješeno lice s otvorenim ustima i hladnim znojem"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Nasmiješeno lice s otvorenim ustima i čvrsto zatvorenim očima"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Nasmiješeno lice s aureolom"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Nasmiješeno lice s rogovima"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Lice koje namiguje"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Nasmiješeno lice s nasmiješenim očima"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Lice s izrazom uživanja u ukusnoj hrani"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lice s izrazom olakšanja"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Nasmiješeno lice s očima u obliku srca"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Nasmiješeno lice sa sunčanim naočalama"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Usiljeno lice"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutralno lice"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Bezizražajno lice"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Lice s izrazom dosade"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Lice s hladnim znojem"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Zamišljeno lice"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zbunjeno lice"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Lice sa zbunjenim izrazom"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Lice koje ljubi"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Lice koje šalje poljubac"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Lice koje ljubi nasmiješenih očiju"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Lice koje ljubi zatvorenih očiju"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Lice s isplaženim jezikom"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Lice koje namiguje s isplaženim jezikom"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Lice s isplaženim jezikom i čvrsto zatvorenim očima"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Razočarano lice"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Zabrinuto lice"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Ljutito lice"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Lice koje se duri"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Uplakano lice"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Odlučno lice"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Lice pobjedonosnog izraza"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Lice koje je razočarano, ali s izrazom olakšanja"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Namršteno lice otvorenih usta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Izmučeno lice"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Preplašeno lice"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Umorno lice"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Pospano lice"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Umorno lice"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Lice s grimasom"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Lice koje glasno plače"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Lice otvorenih usta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Lice koje ušutkava"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Lice otvorenih usta u hladnom znoju"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Lice koje vrišti od straha"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Zapanjeno lice"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Rumeno lice"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Lice koje spava"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Lice s vrtoglavicom"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Lice bez usta"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Lice s medicinskom maskom"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Nasmiješeno lice mačke s nasmiješenim očima"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Lice mačke sa suzama radosnicama"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Nasmiješeno lice mačke s otvorenim ustima"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Nasmiješeno lice mačke s očima u obliku srca"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Lice mačke s kiselim osmjehom"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Lice mačke koja ljubi zatvorenih očiju"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Lice mačke koja se duri"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Uplakano lice mačke"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Tegobno lice mačke"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Lice s gestom \"nije dobro\""</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Lice s gestom \"u redu\""</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Osoba koja se duboko klanja"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Majmun koji \"ne vidi ništa loše\""</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Majmun koji \"ne čuje ništa loše\""</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Majmun koji \"ne govori ništa loše\""</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Sretna osoba koja podiže jednu ruku"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Osoba koja slavodobitno podiže obje ruke"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Osoba koja se mršti"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Osoba s licem koje se duri"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Osoba prekriženih ruku"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parna lokomotiva"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Brzi vlak"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Brzi vlak s lokomotivom u obliku metka"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vlak"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Laka željeznica"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Postaja"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvaj"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagon tramvaja"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobus u dolasku"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobusna postaja"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Hitna pomoć"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Vatrogasno vozilo"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policijski automobil"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Policijski automobil u dolasku"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taksi u dolasku"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automobil u dolasku"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Rekreacijsko vozilo"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Dostavni kamion"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Šleper"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Jednotračna željeznica"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Planinska željeznica"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Viseća željeznica"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Žičara"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Zračni tramvaj"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Brod"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Čamac s veslima"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Gliser"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vodoravni semafor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Okomiti semafor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Znak radova"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Rotirajuće svjetlo policijskog automobila"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trokutasta zastava na stupu"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Vrata"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Znak zabranjenog ulaza"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Znak pušenja"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Znak zabranjenog pušenja"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Znak \"stavite otpatke tamo gdje pripadaju\""</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbol \"ne bacajte otpatke\""</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbol pitke vode"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbol vode koja nije za piće"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicikl"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Zabranjeno za bicikle"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Biciklist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Brdski biciklist"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pješak"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Zabranjeno za pješake"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Djeca prelaze cestu"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Simbol muškog toaleta"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Simbol ženskog toaleta"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toalet"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Simbol bebe"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toalet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Nužnik"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Tuš"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Kupaonica"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Kada"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kontrola putovnica"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Carina"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Preuzimanje prtljage"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Zaboravljena prtljaga"</string>
+</resources>
diff --git a/java/res/values-hr/strings-talkback-descriptions.xml b/java/res/values-hr/strings-talkback-descriptions.xml
index e86db07..65a52f8 100644
--- a/java/res/values-hr/strings-talkback-descriptions.xml
+++ b/java/res/values-hr/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nije unesen tekst"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ispravlja <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> u <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> vrši samoispravljanje"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nema prijedloga"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Nepoznati znak"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Više simbola"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Veliko slovo I, s točkicom iznad"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nepoznati simbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nepoznati emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Lice s izrazom dosade"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Lice s izrazom neugode"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Lice sa sunčanim naočalama"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Iznenađeno lice"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Lice koje ljubi"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Namršteno lice"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Dostupni su zamjenski znakovi"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Zamjenski su znakovi isključeni"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Dostupni su zamjenski prijedlozi"</string>
diff --git a/java/res/values-hr/strings.xml b/java/res/values-hr/strings.xml
index 0cdc74a..8cf4e52 100644
--- a/java/res/values-hr/strings.xml
+++ b/java/res/values-hr/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibracija pri pritisku na tipku"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri pritisku tipke"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Povećanja na pritisak tipke"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Postavke"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Računi i privatnost"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Izgled i rasporedi"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Pisanje kretnjama"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Ispravljanje teksta"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Napredno"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Omogući razdvojenu tipkovnicu"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sink. Googleove tipkovnice"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinkronizacija je uključena"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sinkronizirajte svoj osobni rječnik na više uređaja"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinkroniziraj sada"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Brisanje podataka iz oblaka"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Brisanje vaših sinkroniziranih podataka s Googlea"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Vaši sinkronizirani podaci izbrisat će se iz oblaka. Sigurni ste?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Izbriši"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Odustani"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Vaš osobni rječnik sinkronizirat će se i sigurnosno kopirati na Googleovim poslužiteljima. Moguće je prikupljanje statističkih podataka o učestalosti riječi radi poboljšanja naših proizvoda. Prikupljanje i upotreba svih podataka odvijat će se u skladu s "<a href="https://www.google.com/policies/privacy">"Googleovim pravilima o privatnosti"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Dodajte Google račun na uređaj da biste omogućili tu značajku"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prebaci na druge unose"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za prebacivanje jezika pokriva i druge načine unosa"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tipka za izmjenjivanje jezika"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Prikaži kada je omogućen unos na više jezika"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Prikaži pokazivač klizanja"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Prikaži vizualni znak tijekom klizanja od tipke Shift ili tipki sa znakovima"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Odgoda prikaza tipki"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez odgode"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Zadano"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Glavni rječnik"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokaži prijedloge ispravka"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Prikazivanje predloženih riječi prilikom upisivanja"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Uvijek prikaži"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Prikaži u portretnom načinu"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Uvijek sakrij"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokiraj uvredljive riječi"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ne predlaži potencijalno uvredljive riječi"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatski ispravak"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni unos"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nije omogućen nijedan način glasovnog unosa. Provjerite postavke jezika i unosa."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Slanje povratnih informacija"</string>
-    <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Jezici"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pomoć i povratne informacije"</string>
+    <string name="select_language" msgid="5709487854987078367">"Jezici"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dodirnite ponovo za spremanje"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Dodirnite ovdje za spremanje"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Prijelaz na drugi račun"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nije odabran nijedan račun"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Trenutačno upotrebljavate <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"U redu"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Odustani"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Odjava"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Odaberite račun za upotrebu"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engleski (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engleski (SAD)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španjolski (SAD)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Srpski (latinica)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"engleska (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"engleska (SAD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španjolska (SAD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Srpski (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalni)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ćirilica)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinica)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktna)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nema jezika (abeceda)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abeceda (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abeceda (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Abeceda (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Abeceda (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema tipkovnice"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Prilagođeni stilovi unosa"</string>
     <string name="add_style" msgid="6163126614514489951">"Dodaj stil"</string>
     <string name="add" msgid="8299699805688017798">"Dodaj"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Omogući"</string>
     <string name="not_now" msgid="6172462888202790482">"Ne sada"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Već postoji isti stil unosa: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Odgoda dugog pritiska tipke"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Trajanje vibracije pritiska"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Glasnoća pritiska tipke"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Čitanje datoteke vanjskog rječnika"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"U mapi Preuzimanja nema datoteka rječnika"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Odabir datoteke rječnika za instaliranje"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Želite li zaista instalirati tu datoteku za <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Došlo je do pogreške"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Odgoda dugog pritiska tipke"</string>
     <string name="button_default" msgid="3988017840431881491">"Zadano"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Dobro došli u aplikaciju <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"s Pisanjem kretnjama"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Sada možete pisati u svim svojim omiljenim aplikacijama pomoću aplikacije <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfiguriraj dodatne jezike"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Završeno"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Prikaži ikonu aplikacije"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Prikazivanje ikone aplikacije u pokretaču"</string>
     <string name="app_name" msgid="6320102637491234792">"Davatelj rječnika"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Davatelj rječnika"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Usluga rječnika"</string>
diff --git a/java/res/values-hu/strings-emoji-descriptions.xml b/java/res/values-hu/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..b72f298
--- /dev/null
+++ b/java/res/values-hu/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Szerzői jog embléma"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Regisztrált embléma"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Kettős felkiáltójel"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Felkiáltó- és kérdőjel"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Védjegy jel"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Információs pont"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Kétágú vízszintes nyíl"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Kétágú függőleges nyíl"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Északnyugatra mutató nyíl"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Északkeletre mutató nyíl"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Délkeletre mutató nyíl"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Délnyugatra mutató nyíl"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Balra mutató kampós nyíl"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Jobbra mutató kampós nyíl"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Karóra"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Homokóra"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Jobbra mutató fekete kettős háromszög"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Balra mutató fekete kettős háromszög"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Felfelé mutató fekete kettős háromszög"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Lefelé mutató fekete kettős háromszög"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Ébresztőóra"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Homokóra folyó homokkal"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Latin nagy m betű egy körben"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Kis fekete négyzet"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Kis fehér négyzet"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Jobbra mutató fekete háromszög"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Balra mutató fekete háromszög"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Közepes fehér négyzet"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Közepes fekete négyzet"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Közepesen kicsi fehér négyzet"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Közepesen kicsi fekete négyzet"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Fekete nap sugarakkal"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Felhő"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Fekete telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Szavazónégyzet pipával"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Esernyő esőcseppekkel"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Forró ital"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Fehér felfelé mutató ujj"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Fehér mosolygó arc"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Kos"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Bika"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Ikrek"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rák"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Oroszlán"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Szűz"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Mérleg"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpió"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Nyilas"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Bak"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vízöntő"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Halak"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Fekete pikk"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Fekete treff"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Fekete szív"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Fekete káró"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Hőforrások"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Fekete általános újrahasznosítás jel"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Kerekes szék szimbólum"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Horgony"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Figyelmeztető jel"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Nagyfeszültség jele"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Közepes fehér kör"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Közepes fekete kör"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Focilabda"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball-labda"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Hóember hó nélkül"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Nap felhő mögött"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Kígyótartó"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Behajtani tilos"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Templom"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Szökőkút"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Golfzászló lyukban"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Vitorláshajó"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Sátor"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Benzinkút"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Fekete olló"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Nagy fehér pipa jel"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Repülőgép"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Boríték"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Felemelt ököl"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Felemelt kéz"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Győzelmet mutató kéz"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Ceruza"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Fekete tollhegy"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Nagy pipa jel"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Nagy szorzásjel"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Szikrák"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Nyolcágú csillag"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Nyolcágú fekete csillag"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Hópehely"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Szikra"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kereszt"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Kereszt négyzetben negatívban"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Fekete kérdőjel"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Fehér kérdőjel"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Fehér felkiáltójel"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Nagy fekete felkiáltójel"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Fekete szív"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Nagy pluszjel"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Nagy mínuszjel"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Nagy osztásjel"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Fekete jobbra mutató nyíl"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Hurok"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dupla hurok"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Jobbra mutató, majd felfelé kanyarodó nyíl"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Jobbra mutató, majd lefelé kanyarodó nyíl"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Balra mutató fekete nyíl"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Felfelé mutató fekete nyíl"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Lefelé mutató fekete nyíl"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Nagy fekete négyzet"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Nagy fehér négyzet"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Közepes fehér csillag"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Nagy kör"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Hullámos vonal"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Dalrész kezdete jel"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Gratuláció ideogram körben"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Titok ideogram körben"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Madzsong vörös sárkány kő"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Fekete dzsóker kártya"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A vércsoport"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B vércsoport"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"0 vércsoport"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkoló"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB vércsoport"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL négyzetben"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cool négyzetben"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Free négyzetben"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID négyzetben"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"New négyzetben"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG négyzetben"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK négyzetben"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS négyzetben"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Up felkiáltójellel négyzetben"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS négyzetben"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Itt katakana négyzetben"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Szolgáltatás katakana négyzetben"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Díjmentes ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Foglalt hely ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Tiltás ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Üresedés ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Elfogadás ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Teljes foglaltság ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Kifizetve ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Havi ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Alkalmazás ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Kedvezmény ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Munkában ideogram négyzetben"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Előny ideogram körben"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Elfogad ideogram körben"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Ködös"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Összecsukott esernyő"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Éjszakai ég csillagokkal"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Napfelkelte a hegyek fölött"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Napfelkelte"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Városi látkép alkonyatkor"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Napnyugta épületek felett"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Szivárvány"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Híd éjszaka"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Hullám"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkán"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Tejút"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Földgömb Európával és Afrikával"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Földgömb Észak- és Dél-Amerikával"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Földgömb Ázsiával és Ausztráliával"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Földgömb délkörökkel"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Újhold szimbólum"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Növekvő félhold szimbólum"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Első negyed holdfázis szimbólum"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Növekvő hold szimbólum"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Telihold szimbólum"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Fogyó hold szimbólum"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Utolsó negyed holdfázis szimbólum"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Fogyó félhold szimbólum"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Holdsarló"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Újhold arccal"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Első negyed holdfázis arccal"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Utolsó negyed holdfázis arccal"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Telihold arccal"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Nap arccal"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Tündöklő csillag"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Hullócsillag"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Gesztenye"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Palánta"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Örökzöld fa"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Lombhullató fa"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Pálmafa"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktusz"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Cseresznyevirág"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rózsa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiszkusz"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Napraforgó"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Virág"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kukoricacső"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Rizskalász"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Gyógynövény"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Négylevelű lóhere"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Juharlevél"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Lehullott levél"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Hulló falevél"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Gomba"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Paradicsom"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Padlizsán"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Szőlő"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Dinnye"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Görögdinnye"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citrom"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banán"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananász"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Piros alma"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zöldalma"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Körte"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Barack"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cseresznye"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Eper"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzaszelet"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Hús csonttal"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Csirkecomb"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rizskeksz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rizsgombóc"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Főtt rizs"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Currys rizs"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Tészta tálban"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Kenyér"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Sült krumpli"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Sült édesburgonya"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Szusi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Sült garnéla"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Haltorta örvény mintával"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Fagylalt"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Jégkása"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Jégkrém"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Fánk"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Sütemény"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Csokoládé"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Cukorka"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Sodó"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Mézesbödön"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Tortaszelet"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento tál"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Egy fazék étel"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Serpenyő"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Kés és villa"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Fületlen teáscsésze"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Szakés kancsó és csésze"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Borospohár"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Koktélos pohár"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Trópusi ital"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Söröskorsó"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Koccintó söröskorsók"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Cumisüveg"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Masni"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Becsomagolt ajándék"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Születésnapi torta"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Töklámpás"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Karácsonyfa"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Télapó"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Tűzijáték"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Csillagszóró"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Léggömb"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Mini konfettiágyú"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettigömb"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata fa"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Keresztbe tett zászlók"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Fenyődísz"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japán babák"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Ponty alakú szélzsákok"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Szélharang"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Holdszemlélő ünnep"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Iskolatáska"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Diplomaosztón viselt kalap"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Ló körhintán"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Óriáskerék"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Hullámvasút"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Horgászbot hallal"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmfelvevő gép"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Mozi"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Fejhallgató"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Festőpaletta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cilinder"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkuszi sátor"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Jegy"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Csapó"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Előadóművészetek"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videojáték"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Telitalálat"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Játékgép"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliárd"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dobókocka"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Virág kártya"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Hangjegy"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Több hangjegy"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Szaxofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitár"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Zenei billentyűzet"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trombita"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Hegedű"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Kotta"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Futótrikó vállszalaggal"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Teniszütő és -labda"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Síléc és sícipő"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Kosárlabda és kosár"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Kockás zászló"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboardozó"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Futó"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Szörfös"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Kupa"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Lóverseny"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikaifutball-labda"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rögbilabda"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Úszó"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Ház"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Ház kerttel"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Irodaépület"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japán posta"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Európai posta"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Kórház"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ATM"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Szálloda"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Motel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Kisbolt"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Iskola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Áruház"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Gyár"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Japán lámpás"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japán kastély"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Európai kastély"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Patkány"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Egér"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Ökör"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vízibivaly"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Tehén"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopárd"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Nyúl"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Macska"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Sárkány"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Bálna"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Csiga"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Kígyó"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Ló"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Kos"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Kecske"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Juh"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Majom"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Kakas"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Csirke"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Kutya"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Sertés"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Vaddisznó"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefánt"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Polip"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Csavart kagyló"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Rovar"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Hangya"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Méh"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Katicabogár"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Hal"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Trópusi hal"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Gömbhal"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Teknős"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kikelő csibe"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kiscsibe"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Szembe forduló kiscsibe"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Madár"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudli"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Egypúpú teve"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kétpúpú teve"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Egérfej"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Tehénfej"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigrisfej"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Nyúlfej"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Macskafej"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Sárkányfej"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Vízsugarat fújó bálna"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Lófej"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Majomfej"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Kutyafej"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Disznófej"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Békafej"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hörcsögfej"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Farkasfej"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Medvefej"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandafej"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Malacorr"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Mancsnyomok"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Szempár"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Fül"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Orr"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Száj"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Nyelv"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Felfelé mutató fehér kéz"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Lefelé mutató fehér kéz"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Balra mutató fehér kéz"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Jobbra mutató fehér kéz"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Ökölbe szorított kéz"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Integető kéz"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Rendben jelet mutató kéz"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Felfelé mutató hüvelykujj"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Lefelé mutató hüvelykujj"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Tapsoló kéz"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Kinyitott kéz"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Korona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Női kalap"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Szemüveg"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Nyakkendő"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Póló"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Farmer"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Női ruha"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimonó"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Blúz"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Pénztárca"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Női táska"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Kézitáska"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Férficipő"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportcipő"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Magas sarkú cipő"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Női szandál"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Női csizma"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Lábnyomok"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Felsőtest sziluettje"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Felsőtestek sziluettje"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Fiú"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Lány"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Férfi"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Nő"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Család"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Férfi és nő kézen fogva"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Két férfi kézen fogva"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Két nő kézen fogva"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Rendőr"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Nő nyuszifülekkel"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Menyasszony fátyollal"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Szőke lány"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Kínai férfi"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Turbános férfi"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Idős férfi"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Idős nő"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Kisbaba"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Építőmunkás"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Hercegnő"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japán ogre"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japán manó"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Kísértet"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Szárnyas puttó"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Földönkívüli"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Idegen szörny"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Manó"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Koponya"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Információs pultban ülő személy"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gárdista"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Táncos"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rúzs"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Körömlakk"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Arcmasszázs"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Hajvágás"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Borbélycégér"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Fecskendő"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pirula"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Rúzsos csóknyom"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Szerelmes levél"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Gyűrű"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Drágakő"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Csók"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Csokor"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Szerelmespár szívvel"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Esküvő"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Dobogó szív"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Összetört szív"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Két szív"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Csillogó szív"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Növekvő szív"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Szív nyíllal"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Kék szív"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zöld szív"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Sárga szív"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lila szív"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Szív szalaggal"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Kört alkotó szívek"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Szív díszítés"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Gyémánt alakzat ponttal a közepén"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Villanykörte"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Harag szimbóluma"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Alvás szimbóluma"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Robbanás szimbóluma"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Fröcskölő izzadtság szimbólum"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Vízcsepp"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Száguldás szimbóluma"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Ürülékkupac"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Megfeszített bicepsz"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Szédülés szimbóluma"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Szövegbuborék"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Gondolatbuborék"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Fehér virág"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Század jele"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Pénzeszsák"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Pénzváltás"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Nagy dollárjel"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Hitelkártya"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bankjegy a jen jelével"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Bankjegy dollárjellel"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bankjegy az euró jelével"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bankjegy a font jelével"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Szárnyas pénz"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Növekvő tendenciát jelző diagram a jen jelével"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Ülés"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Számítógép"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktatáska"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppy lemez"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"CD"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Irattartó"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Nyitott mappa"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Felkunkorodó aljú papír"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Felfelé néző papír"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Naptár"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Letéphető oldalú naptár"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kartoték"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Növekvő tendenciát jelző diagram"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Csökkenő tendenciát jelző diagram"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Oszlopdiagram"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Jegyzettömb"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Rajzszög"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Gömb fejű rajzszög"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Gemkapocs"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Egyenes vonalzó"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Háromszögvonalzó"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Könyvjelzők"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Főkönyv"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Jegyzetfüzet"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Jegyzetfüzet díszes borítóval"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Csukott könyv"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Nyitott könyv"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zöld könyv"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Kék könyv"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Narancssárga könyv"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Könyvek"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Névkitűző"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Papírtekercs"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Emlékeztető"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonkagyló"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Személyhívó"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Parabolaantenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Köztéri hangosbeszélő"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Kézi megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Tálcáról le"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Tálcára rá"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Csomag"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mail jele"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Beérkező levél borítékja"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Boríték és felette lefelé mutató nyíl"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Csukott postaláda leeresztett zászlóval"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Csukott postaláda felemelt zászlóval"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Nyitott postaláda felemelt zászlóval"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Nyitott postaláda leeresztett zászlóval"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Levélszekrény"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Postakürt"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Újság"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiltelefon jobbra mutató nyíllal a bal oldalán"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Rezgő üzemmód"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiltelefon ki"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobiltelefon nem használható"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna sávokkal"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fényképezőgép"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televízió"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Rádió"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokazetta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Összecsavarodott jobbra mutató nyilak"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Az óramutató járásának megfelelően jobbra és balra mutató, kört formázó nyilak"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Az óramutató járásának megfelelően jobbra és balra mutató, kört formázó nyilak, felettük egy körben lévő egyessel"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Az óramutató járásának megfelelően fel és le mutató, kört formázó nyilak"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Az óramutató járásával ellentétesen le és fel mutató, kört formázó nyilak"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Kis fényerő szimbólum"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Nagy fényerő szimbólum"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Hangszóró áthúzva"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Hangszóró"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Hangszóró egy hanghullámmal"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Hangszóró három hanghullámmal"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Elem"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Dugós csatlakozó"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Balra dőlő nagyító"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Jobbra dőlő nagyító"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lakat töltőtollal"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Bezárt lakat kulccsal"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Kulcs"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lakat"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Nyitott lakat"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Csengő"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Csengő áthúzva"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Könyvjelző"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Link szimbóluma"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Választógomb"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back szó felette balra mutató nyíllal"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End szó felette balra mutató nyíllal"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On szó felkiáltójellel és felette kétágú vízszintes nyíllal"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon szó jobbra mutató nyíllal"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top szó felette felfelé mutató nyíllal"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Tizennyolc éven aluliaknak tilos jel"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tízes billentyű"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Beviteli szimbólum latin nagybetűkhöz"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Beviteli szimbólum latin kisbetűkhöz"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Bevitel szimbólum számokhoz"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Bevitel szimbólum szimbólumokhoz"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Beviteli szimbólum latin betűkhöz"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Tűz"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elemlámpa"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Csavarkulcs"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Kalapács"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Csavar és anya"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Japán kés"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pisztoly"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroszkóp"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Távcső"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristálygömb"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Hatágú csillag a közepén ponttal"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"A kezdő japán szimbóluma"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Háromágú szigony embléma"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Fekete négyzetes gomb"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Fehér négyzetes gomb"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Nagy piros kör"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Nagy kék kör"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Nagy narancssárga gyémánt"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Nagy kék gyémánt"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Kis narancssárga gyémánt"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Kis kék gyémánt"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Felfelé mutató piros háromszög"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Lefelé mutató piros háromszög"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Felfelé mutató kicsi piros háromszög"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Lefelé mutató kicsi piros háromszög"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Óra számlapja egy órát mutat"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Óra számlapja két órát mutat"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Óra számlapja három órát mutat"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Óra számlapja négy órát mutat"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Óra számlapja öt órát mutat"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Óra számlapja hat órát mutat"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Óra számlapja hét órát mutat"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Óra számlapja nyolc órát mutat"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Óra számlapja kilenc órát mutat"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Óra számlapja tíz órát mutat"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Óra számlapja tizenegy órát mutat"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Óra számlapja tizenkét órát mutat"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Óra számlapja fél kettőt mutat"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Óra számlapja fél hármat mutat"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Óra számlapja fél négyet mutat"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Óra számlapja fél ötöt mutat"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Óra számlapja fél hatot mutat"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Óra számlapja fél hetet mutat"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Óra számlapja fél nyolcat mutat"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Óra számlapja fél kilencet mutat"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Óra számlapja fél tízet mutat"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Óra számlapja fél tizenegyet mutat"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Óra számlapja fél tizenkettőt mutat"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Óra számlapja fél egyet mutat"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fudzsi hegy"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokiói torony"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Szabadság-szobor"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Japán körvonala"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Vigyorgó arc"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Vigyorgó arc mosolygó szemmel"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Örömében síró arc"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Tátott szájjal nevető arc"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Tátott szájjal nevető, mosolygó szemű arc"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Tátott szájjal nevető, izzadó arc"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Tátott szájjal nevető, szorosan becsukott szemű arc"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Mosolygó arc glóriával"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Mosolygó arc ördögszarvakkal"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Kacsintó arc"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Mosolygó arc mosolygó szemmel"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Szája szélét nyalogató arc"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Megkönnyebbült arc"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Mosolygó arc szív alakú szemmel"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Mosolygó arc napszemüvegben"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Csücsörítve mosolygó arc"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Semleges arc"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Kifejezéstelen arc"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Unott arc"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Hidegen verejtékező arc"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Tűnődő arc"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zavarodott arc"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Megdöbbent arc"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Csókot adó arc"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Csókot küldő arc"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Csókot adó arc mosolygó szemmel"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Csókot adó arc csukott szemmel"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Arc kinyújtott nyelvvel"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Arc kinyújtott nyelvvel és kacsintó szemmel"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Arc kinyújtott nyelvvel és szorosan becsukott szemmel"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Csalódott arc"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Aggódó arc"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Mérges arc"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Duzzogó arc"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Síró arc"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Állhatatos arc"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Diadalmas arc"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Csalódott, de megkönnyebbült arc"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Tátott szájjal meglepődő arc"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Szenvedő arc"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Félelemmel teli arc"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Elcsigázott arc"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Álmos arc"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Fáradt arc"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimaszoló arc"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Zokogó arc"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Arc tátott szájjal"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Csendes arc"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Tátott szájú, izzadó arc"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Félelmében sikoltó arc"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Elképedt arc"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Kipirult arc"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Alvó arc"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Szédülő arc"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Száj nélküli arc"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Arc orvosi maszkkal"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Vigyorgó macskafej mosolygó szemmel"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Örömében síró macskafej"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Tátott szájjal nevető macskafej"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Mosolygó macskafej szív alakú szemmel"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Macskafej fanyar mosollyal"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Csókot adó macskafej csukott szemmel"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Duzzogó macskafej"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Síró macskafej"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Elcsigázott macskafej"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Nem jó jelet mutató arc"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OK jelet mutató arc"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Mélyen meghajló ember"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Nem látok majom"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Nem hallok majom"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Nem beszélek majom"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Boldog ember, egyik kezét felemelve"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Égnek emelt kézzel örülő személy"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Meggörnyedt ember"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Duzzogó arcú ember"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Összekulcsolt kezű ember"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Űrrakéta"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Gőzmozdony"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vasúti kocsi"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Gyorsvasút"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Gyorsvasút lekerekített orral"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vonat"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metró"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Hév"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Állomás"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Villamos"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Villamoskocsi"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Busz"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Érkező busz"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolibusz"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Buszmegálló"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibusz"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Mentőautó"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Tűzoltóautó"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Rendőrautó"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Érkező rendőrautó"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Érkező taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Autó"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Érkező autó"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Utcai terepjáró"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Teherautó"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Kamion"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Egysínű vasút"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Hegyi vasút"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Függővasút"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Hegyi kábelvasút"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Drótkötélpályás felvonó"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Hajó"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Evezős csónak"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motorcsónak"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vízszintes jelzőlámpa"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Függőleges jelzőlámpa"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Útépítés jelző"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Rendőrautó forgó fényjelzése"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Háromszög alakú zászló rúdon"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Ajtó"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Belépni tilos jelzés"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Dohányzás jel"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Dohányozni tilos jel"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Dobja ki a szemetet jel"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Ne szemeteljen jel"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Ivóvíz szimbólum"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Nem ivóvíz szimbólum"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Kerékpár"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Kerékpárral behajtani tilos"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Kerékpáros"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Hegyikerékpáros"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Gyalogos"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Gyalog bemenni tilos"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Átkelő gyermekekkel"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Férfiak jelzés"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Nők jelzés"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Mosdó"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Pelenkázó jelzés"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"WC"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Toalett"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Zuhanyzó"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Fürdő"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Fürdőkád"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Útlevélvizsgálat"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Vám"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Poggyászkiadó terminál"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Elveszett poggyász"</string>
+</resources>
diff --git a/java/res/values-hu/strings-talkback-descriptions.xml b/java/res/values-hu/strings-talkback-descriptions.xml
index ae0c047..84e758b 100644
--- a/java/res/values-hu/strings-talkback-descriptions.xml
+++ b/java/res/values-hu/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nincs szöveg megadva"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> billentyű – <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> szóra javítja a következőt: <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> billentyű automatikus javítást végez"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nincs javaslat"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Ismeretlen karakter"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"További szimbólumok"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Nagy I, felette ponttal"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ismeretlen szimbólum"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ismeretlen hangulatjel"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Unott arc"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Zavarban lévő arc"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Napszemüveges arc"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Meglepődött arc"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Csókot adó arc"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Homlokráncoló arc"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Az alternatív karakterek elérhetők"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Az alternatív karakterek billentyűzete bezárva"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Az alternatív javaslatok elérhetők"</string>
diff --git a/java/res/values-hu/strings.xml b/java/res/values-hu/strings.xml
index 8e65921..4c9a4b3 100644
--- a/java/res/values-hu/strings.xml
+++ b/java/res/values-hu/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rezgés gombnyomásra"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Hangjelzés gombnyomásra"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Nagyobb billentyű gombnyomásra"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Beállítások"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Fiókok és adatvédelem"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Megjelenés és elrendezés"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Kézmozdulatokkal történő gépelés"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Szövegjavítás"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Speciális"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Téma"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Megosztott billentyűzet bekapcsolása"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-billentyűzet szinkronizálása"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"A szinkronizálás be van kapcsolva"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Szinkronizálja személyes szótárát eszközei között"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Szinkronizálás most"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Adatok törlése a felhőből"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Törli a Google rendszeréből a szinkronizált adatokat"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"A szinkronizált adatok törlődnek a felhőből. Biztosan folytatja?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Törlés"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Mégse"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"A rendszer szinkronizálni fogja az Ön személyes szótárát, és biztonsági mentést készít róla a Google szerverein. Termékeink továbbfejlesztése érdekében a rendszer a szavak előfordulási gyakoriságára vonatkozó statisztikai adatokat gyűjthet. Ezen információkat a "<a href="https://www.google.com/policies/privacy">"Google adatvédelmi irányelveivel"</a>" összhangban gyűjtjük és használjuk fel."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"A funkció engedélyezéséhez adjon egy Google-fiókot az eszközhöz"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Váltás más beviteli módra"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A nyelvkapcsoló gomb egyéb beviteli módokat is tartalmaz"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"A nyelvkapcsoló"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Megjelenítés, ha több beviteli nyelv engedélyezett"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Diajelző megjelenítése"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Vizuális jelzés Shift vagy Szimbólumok billentyűről csúsztatásnál"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Gombeltüntetés késése"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nincs késés"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Alapbeállítás"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Fő szótár"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Javítási ajánlások megjelenítése"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"A javasolt szavak megjelenítése gépelés közben"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mindig látszik"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Megjelenítés álló tájolásban"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Mindig rejtve"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Sértő szavak kizárása"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ne javasoljon esetlegesen sértő szavakat"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatikus javítás"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Hangbeviteli gomb"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nincs engedélyezett hangbeviteli módszer. Nézze meg a Nyelvi és beviteli beállításokat."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Visszajelzés küldése"</string>
-    <string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Nyelvek"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Súgó és visszajelzés"</string>
+    <string name="select_language" msgid="5709487854987078367">"Nyelvek"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Érintse meg újból a mentéshez"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"A mentéshez érintse meg itt"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Billentyűzettéma"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Fiókváltás"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nem választott fiókot"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Jelenleg használt fiók: <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Mégse"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Kijelentkezés"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Válassza ki a használni kívánt fiókot"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angol (brit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angol (amerikai)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spanyol (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish (hindi-angol)"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Szerb (latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angol (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angol (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"spanyol (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (hindi-angol, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Szerb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hagyományos)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirill)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nincs nyelv (ábécé)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Ábécé (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Ábécé (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Ábécé (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Ábécé (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Hangulatjel"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Billentyűzettéma"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Egyedi bevitelstílusok"</string>
     <string name="add_style" msgid="6163126614514489951">"Új stílus"</string>
     <string name="add" msgid="8299699805688017798">"Hozzáadás"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Engedélyezés"</string>
     <string name="not_now" msgid="6172462888202790482">"Most nem"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Ugyanez a bemenetstílus már létezik: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Hosszú nyomás késleltetése"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Gombnyomás rezgési időtartama"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Gombnyomás hangereje"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Külső szótárfájl olvasása"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nincs szótárfájl a Letöltések mappában."</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Válasszon ki egy szótárfájlt a telepítéshez."</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Valóban telepíti ezt a fájlt <xliff:g id="LANGUAGE_NAME">%s</xliff:g> nyelvhez?"</string>
-    <string name="error" msgid="8940763624668513648">"Hiba történt."</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Hosszú nyomás késleltetése"</string>
     <string name="button_default" msgid="3988017840431881491">"Alapértelmezett"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Üdvözli a(z) <xliff:g id="APPLICATION_NAME">%s</xliff:g>!"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"kézmozdulatokkal történő bevitellel"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Immár minden kedvenc alkalmazásában gépelhet a(z) <xliff:g id="APPLICATION_NAME">%s</xliff:g> segítségével."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Állítson be további nyelveket"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Befejeződött"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Alkalmazásikon megjelenítése"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Alkalmazásikon megjelenítése az indítóban"</string>
     <string name="app_name" msgid="6320102637491234792">"Szótárszolgáltató"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Szótárszolgáltató"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Szótárszolgáltatás"</string>
diff --git a/java/res/values-hy-rAM/strings-emoji-descriptions.xml b/java/res/values-hy-rAM/strings-emoji-descriptions.xml
index f41f2fc..7339db6 100644
--- a/java/res/values-hy-rAM/strings-emoji-descriptions.xml
+++ b/java/res/values-hy-rAM/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Թխվածքաբլիթ"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Շոկոլադի սալիկ"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Կոնֆետ"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Սառնաշաքար կոնֆետ"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Շաքարաքլոր"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Եփովի կրեմ"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Մեղրանոթ"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Տորթի կտոր"</string>
@@ -552,8 +552,8 @@
     <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Ճկուն սկավառակ"</string>
     <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Օպտիկական սկավառակ"</string>
     <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
-    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Ֆայլերի թղթապանակ"</string>
-    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ֆայլերի բաց թղթապանակ"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Ֆայլերի պանակ"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ֆայլերի բաց պանակ"</string>
     <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Ոլորված ծայրով էջ"</string>
     <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Թեքված էջ"</string>
     <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Օրացույց"</string>
diff --git a/java/res/values-hy-rAM/strings-talkback-descriptions.xml b/java/res/values-hy-rAM/strings-talkback-descriptions.xml
index 44784bd..014f499 100644
--- a/java/res/values-hy-rAM/strings-talkback-descriptions.xml
+++ b/java/res/values-hy-rAM/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Տեքստ չի մուտքագրվել"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>-ը շտկում է <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-ը՝ դարձնելով <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ստեղնը ինքնաշտկում է կատարում"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Առաջարկներ չկան"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Անհայտ տառանշան"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Հավելյալ նշաններ"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Մեծատառ I, վերևում կետիկ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Անհայտ նշան"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Անհայտ զմայլիկ"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ձանձրացող դեմք"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Շփոթված դեմք"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Արևային ակնոցներով դեմք"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Զարմացած դեմք"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Համբուրող դեմք"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Խոժոռված դեմք"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Լրացուցիչ տառանշաններով ստեղնաշարը հասանելի է"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Լրացուցիչ տառանշաններով ստեղնաշարը փակված է"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Լրացուցիչ առաջարկներով վահանակը հասանելի է"</string>
diff --git a/java/res/values-hy-rAM/strings.xml b/java/res/values-hy-rAM/strings.xml
index f606c4b..f98a586 100644
--- a/java/res/values-hy-rAM/strings.xml
+++ b/java/res/values-hy-rAM/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"Ներածման նախընտրանքներ"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Արտաքին տեսք"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Բազմալեզու տարբերակներ"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Ժեստերով մուտքագրման նախընտրանքներ"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Նախընտրանքներ"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Հաշիվներ և գաղտնիություն"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Արտաքին տեսք և դասավորություն"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Ժեստերով մուտքագրում"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Տեքստի ուղղում"</string>
-    <string name="settings_screen_advanced" msgid="7472408607625972994">"Ընդլայնված"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Հավելյալ"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Թեմա"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Միացնել բաժանված ստեղնաշարը"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Ստեղնաշարի համաժամեցում"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Համաժամեցումը միացված է"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Համաժամեցնել ձեր անհատական բառարանը սարքերի միջև"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Համաժամացնել հիմա"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Ջնջել ամպի տվյալները"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google- ից ջնջում է ձեր համաժամեցրած տվյալները"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Ձեր համաժամեցրած տվյալները ջնջվելու են ամպից: Շարունակե՞լ:"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Ջնջել"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Չեղարկել"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Ձեր անհատական բառարանը համաժամեցվելու և կրկնօրինակվելու է Google սերվերներում: Կարող են հավաքվել բառերի օգտագործման հաճախականության վիճակագրական տվյալներ՝ մեր արտադրանքների որակը բարելավելու նպատակով: Բոլոր տվյալները հավաքվելու և օգտագործվելու են "<a href="https://www.google.com/policies/privacy">"Google-ի Գաղտնիության քաղաքականության"</a>" դրույթների համաձայն:"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Այս հնարավորությունն ընձեռելու համար սարքում հավելեք Google հաշիվ"</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">"Լեզվի փոխարկման բանալին ընդգրկում է այլ մուտքագրման եղանակներ ևս"</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">"Ցուցադրել սահքի ցուցիչը"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Ցուցադրել տեսողական հուշումը Shift-ի կամ նշանների ստեղներից սահեցման ընթացքում"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Ձայնային մուտքագրման ստեղն"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ձայնային ներածման որևէ եղանակ միացված չէ։ Ստուգեք Լեզվի և ներածման կարգավորումները։"</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="language_selection_title" msgid="3666971864764478269">"Լեզուներ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Օգնություն և հետադարձ կապ"</string>
+    <string name="select_language" msgid="5709487854987078367">"Լեզուներ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Պահպանելու համար կրկին հպեք"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Պահելու համար հպեք այստեղ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Բառարանն առկա է"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Ստեղնաշարի թեման"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Փոխարկել հաշիվները"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Հաշիվ չի ընտրվել"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Ներկայումս օգտագործում է՝ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Լավ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Չեղարկել"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Դուրս գալ"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Ընտրեք հաշիվ՝ օգտագործելու համար"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Անգլերեն (ՄԹ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Անգլերեն (ԱՄՆ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Իսպաներեն (ԱՄՆ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Հինգլիշ"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Սերբերեն (Լատինական)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Անգլերեն (ՄԹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Անգլերեն (ԱՄՆ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Իսպաներեն (ԱՄՆ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Հինգլիշ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Սերբերեն (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ավանդական)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (կյուրեղյան)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (լատինական)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (սեղմ)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ոչ մի լեզվով (Այբուբեն)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Այբուբեն (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Այբուբեն (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Այբուբեն (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Զմայլիկներ"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Ստեղնաշարի թեման"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Պայծառ"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Բաց կապույտ"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Մուգ"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Բաց"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Մուտքագրման հատուկ ոճեր"</string>
     <string name="add_style" msgid="6163126614514489951">"Ավելացնել ոճ"</string>
     <string name="add" msgid="8299699805688017798">"Ավելացնել"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"Տեղադրե՞լ այս ֆայլը <xliff:g id="LANGUAGE_NAME">%s</xliff:g> լեզվի համար:"</string>
-    <string name="error" msgid="8940763624668513648">"Տեղի է ունեցել սխալ"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ստեղնի երկար սեղմման ուշացում"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Այժմ դուք կարող եք մուտքագրել ձեր բոլոր սիրելի հավելվածներում <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">"Ցուցադրել հավելվածի պատկերակը թողարկչում"</string>
     <string name="app_name" msgid="6320102637491234792">"Բառարանի մատակարար"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Բառարանի մատակարար"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Բառարանի ծառայություն"</string>
@@ -171,7 +179,7 @@
     <string name="cancel_download_dict" msgid="7843340278507019303">"Չեղարկել"</string>
     <string name="delete_dict" msgid="756853268088330054">"Ջնջել"</string>
     <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Ձեր բջջային սարքում ընտրված լեզվով առկա է բառարան:<br/> Խորհուրդ ենք տալիս &lt;b&gt;ներբեռնել&lt;/b&gt; <xliff:g id="LANGUAGE_NAME">%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; բաժինը:"</string>
-    <string name="download_over_metered" msgid="1643065851159409546">"Ներբեռնել հիմա (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>Մբ)"</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="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> լեզվի համար առկա է բառարան"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"Սեղմեք՝ վերանայելու և ներբեռնելու համար"</string>
diff --git a/java/res/values-in/strings-emoji-descriptions.xml b/java/res/values-in/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..9eade09
--- /dev/null
+++ b/java/res/values-in/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Tanda hak cipta"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Tanda terdaftar"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Tanda seru ganda"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Tanda tanya dan tanda seru"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Tanda merek dagang"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Sumber informasi"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Panah kanan kiri"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Panah atas bawah"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Panah barat laut"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Panah timur laut"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Panah tenggara"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Panah barat daya"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Panah melengkung ke kiri"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Panah melengkung ke kanan"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Jam tangan"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Jam pasir"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Segitiga hitam ganda mengarah ke kanan"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Segitiga hitam ganda mengarah ke kiri"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Segitiga hitam ganda mengarah ke atas"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Segitiga hitam ganda mengarah ke bawah"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Jam alarm"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Jam pasir dengan pasir mengalir"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Lingkaran bertuliskan huruf kapital M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Persegi kecil hitam"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Persegi kecil putih"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Segitiga hitam mengarah ke kanan"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Segitiga hitam mengarah ke kiri"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Persegi sedang putih"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Persegi sedang hitam"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Persegi kecil menengah putih"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Persegi kecil menengah putih"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Matahari hitam dengan cahaya"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Awan"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telepon hitam"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Kotak dengan tanda centang"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Patung dengan tetesan hujan"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Minuman panas"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Indeks menunjuk ke atas"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Wajah tersenyum putih"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taurus"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gemini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpio"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagitarius"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquarius"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Pisces"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Kartu sekop hitam"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Kartu keriting hitam"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Kartu hati hitam"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Kartu wajik hitam"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Mata air panas"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Simbol daur ulang universal hitam"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Simbol kursi roda"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Jangkar"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Tanda peringatan"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Tanda voltase tinggi"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Lingkaran sedang putih"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Lingkaran sedang hitam"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Sepak bola"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bisbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Manusia salju tanpa salju"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Matahari di belakang awan"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ofiukus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Dilarang masuk"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Gereja"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Air mancur"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bendera di lapangan golf"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Perahu layar"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tenda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Pompa bahan bakar"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Gunting hitam"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Tanda centang tebal putih"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Pesawat terbang"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Amplop"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Kepalan tangan diangkat"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Tangan diangkat"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Tanda kemenangan"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Pensil"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Ujung pena hitam"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Tanda centang tebal"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"X perkalian tebal"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Kilauan"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Delapan jeruji seperti tanda bintang"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Bintang hitam dengan delapan ujung runcing"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Kepingan salju"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Kilauan"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Tanda silang"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Tanda silang dalam kotak negatif"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Ornamen tanda tanya hitam"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ornamen tanda tanya putih"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ornamen tanda seru putih"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Simbol tanda seru tebal"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Bentuk hati berwarna hitam"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Tanda plus tebal"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Tanda minus tebal"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Tanda bagi tebal"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Panah hitam ke arah kanan"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Lingkaran ikal"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Lingkaran ikal ganda"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Panah mengarah ke kanan lalu ke belok ke atas"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Panah mengarah ke kanan lalu ke belok ke bawah"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Panah hitam ke kiri"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Panah hitam ke atas"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Panah hitam ke bawah"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Persegi besar hitam"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Persegi besar putih"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Bintang sedang putih"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Lingkaran besar tebal"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Tanda pisah bergelombang"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Tanda bagian awal"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Lingkaran bertuliskan ideograf selamat"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Lingkaran bertuliskan ideograf rahasia"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Naga merah ubin Mahjong"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Kartu permainan joker hitam"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Golongan darah A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Golongan darah B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Golongan darah O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Tempat parkir"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Golongan darah AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Persegi bertuliskan CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Persegi bertuliskan COOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Persegi bertuliskan FREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Persegi bertuliskan ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Persegi bertuliskan NEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Persegi bertuliskan N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Persegi bertuliskan OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Persegi bertuliskan SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Persegi bertuliskan UP dengan tanda seru"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Persegi bertuliskan VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Persegi bertuliskan huruf katakana koko"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Persegi bertuliskan katakana sa"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Persegi bertuliskan ideograf gratis"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Persegi bertuliskan ideograf kursi dipesan"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Persegi bertuliskan ideograf larangan"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Persegi bertuliskan ideograf lowongan"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Persegi bertuliskan ideograf penerimaan"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Persegi bertuliskan ideograf hunian penuh"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Persegi bertuliskan ideograf berbayar"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Persegi bertuliskan ideograf bulanan"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Persegi bertuliskan ideograf aplikasi"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Persegi bertuliskan ideograf diskon"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Persegi bertuliskan ideograf di bidang bisnis"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Lingkaran bertuliskan ideograf keuntungan"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Lingkaran bertuliskan terima"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Topan"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Berkabut"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Payung tertutup"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Malam dengan bintang"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Matahari terbit di atas pegunungan"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Matahari terbit"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Pemandangan kota saat senja"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Matahari terbenam di atas gedung"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Pelangi"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Jembatan saat malam"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Ombak"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Gunung berapi"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Bima sakti"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globe benua eropa-afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globe benua amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globe benua asia-australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globe dengan garis bujur"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbol bulan baru"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbol bulan sabit muda"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbol bulan seperempat pertama"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbol bulan hampir penuh"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbol bulan purnama"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbol bulan sesudah purnama"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbol bulan seperempat akhir"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbol bulan sabit tua"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Bulan sabit"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Bulan baru dengan wajah"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Bulan seperempat pertama dengan wajah"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Bulan seperempat akhir dengan wajah"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Bulan purnama dengan wajah"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Matahari dengan wajah"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Bintang bersinar"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Bintang jatuh"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanya"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Bibit"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Pohon cemara"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Tumbuhan peluruh"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Pohon palem"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Sakura"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Mawar"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Bunga sepatu"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Bunga matahari"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Sakura"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kelobot jagung"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Tanaman padi"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Rumput"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Daun semanggi"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Daun maple"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Daun jatuh"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Daun yang tertiup angin"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Jamur"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Terung"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Anggur"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Semangka"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Jeruk"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Lemon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Pisang"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Nanas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Apel merah"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Apel hijau"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pir"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Persik"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Ceri"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Stroberi"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Sepotong pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Iga sapi"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Paha ayam"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Biskuit"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Onigiri"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Nasi"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Nasi dan kari"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Semangkuk ramen"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spageti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Roti"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Kentang goreng"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Ubi manis panggang"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Udang goreng"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Kue ikan dengan desain pusaran"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Es krim lembut"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Es serut"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Es krim"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donat"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Kue"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Coklat batangan"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Permen"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Saus puding"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Pot madu"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Kue bolu"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bekal makanan"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Semangkuk makanan"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Memasak"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Garpu dan pisau"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Cangkir teh tanpa pegangan"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Cangkir dan botol sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Gelas anggur"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Gelas koktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Minuman tropis"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Gelas bir"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Mendentingkan gelas bir"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Botol bayi"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Pita"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Kado"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Kue ulang tahun"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Jack-o-lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Pohon natal"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Sinterklas"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Kembang api"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Percikan kembang api"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Tembakan kertas"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Confetti bentuk bola"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Pohon tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bendera disilangkan"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Dekorasi pinus"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Boneka jepang"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Bendera koi"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Lonceng angin"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Upacara melihat bulan"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Tas sekolah"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Topi wisuda"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Kuda komidi putar"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Bianglala"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Roller coaster"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Alat pancing dan ikan"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Kamera film"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Bioskop"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Headphone"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palet"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Topi tinggi"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Tenda sirkus"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Tiket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Papan tanda"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Seni drama"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video game"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Tembakan langsung"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Mesin slot"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Game dadu"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Boling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Kartu remi bunga"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Not balok"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Berbagai not balok"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Kibor"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Terompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Biola"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitur musik"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Kaos lari dengan selempang"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Bola dan raket tenis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski dan sepatu ski"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Ring dan bola basket"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bendera papan catur"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Peseluncur salju"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Pelari"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Peselancar"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Piala"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Balapan kuda"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Sepak bola Amerika"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Sepak bola rugbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Perenang"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Bangunan rumah"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Rumah dengan kebun"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Bangunan kantor"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Kantor pos Jepang"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Kantor pos Eropa"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Rumah sakit"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Mesin kasir otomatis"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel cinta"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Toko kelontong"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Sekolah"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Toko serba ada"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Pabrik"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lampion Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Istana Jepang"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Kastil Eropa"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Tikus besar"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Tikus kecil"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Sapi jantan"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Kerbau"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Sapi"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Macan tutul"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Kelinci"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kucing"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Naga"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Buaya"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Paus"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Siput"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Ular"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Kuda"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Domba jantan"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Kambing"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Domba"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Monyet"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Ayam jantan"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Ayam"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Anjing"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Babi"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Babi jantan"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Gajah"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Gurita"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Cangkang spiral"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Kutu"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Semut"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Lebah"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Kumbang koksi"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Ikan"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Ikan tropis"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Ikan buntal"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Kura-kura"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Anak ayam yang menetas"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Anak ayam"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Wajah anak ayam menghadap ke depan"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Burung"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Penguin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Unta arab"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Unta baktria"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Lumba-lumba"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Wajah tikus"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Wajah sapi"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Wajah harimau"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Wajah kelinci"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Wajah kucing"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Wajah naga"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Paus menyembur"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Wajah kuda"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Wajah monyet"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Wajah anjing"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Wajah babi"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Wajah katak"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Wajah hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wajah serigala"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Wajah beruang"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Wajah panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Hidung babi"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Jejak kaki anjing"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Mata"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Telinga"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Hidung"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mulut"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lidah"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Indeks tangan menunjuk ke atas"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Indeks tangan menunjuk ke bawah"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Indeks tangan menunjuk ke kiri"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Indeks tangan menunjuk ke kanan"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Tanda mengepal"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Tanda tangan melambai"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Tanda oke"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Tanda suka"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Tanda tidak suka"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Tanda tepuk tangan"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Tanda membuka tangan"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Mahkota"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Topi wanita"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Kacamata"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Dasi"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Kaos"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jins"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Gaun"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Pakaian wanita"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Tas dompet"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Tas tangan"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Dompet"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Sepatu pria"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sepatu atletik"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Sepatu hak tinggi"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandal wanita"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Bot wanita"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Jejak kaki"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Siluet patung dada"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Siluet patung dada"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Anak laki-laki"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Anak perempuan"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Pria"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Wanita"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Keluarga"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Pria dan wanita saling berpegangan tangan"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dua pria saling berpegangan tangan"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dua wanita saling berpegangan tangan"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polisi"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Wanita dengan telinga kelinci"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Pengantin wanita dengan tudung"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Orang berambut pirang"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Pria mengenakan gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Pria mengenakan serban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Pria tua"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Wanita tua"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bayi"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Pekerja konstruksi"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Putri raja"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogre Jepang"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Goblin Jepang"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Hantu"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Malaikat bayi"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Makhluk ekstraterestrial"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Makhluk asing"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Setan"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Tengkorak"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Petugas meja informasi"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Pengawal"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Penari"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lipstik"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Cat kuku"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Pijat wajah"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Potong rambut"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Tiang tukang cukur"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Semprotan"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pil"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Tanda ciuman"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Surat cinta"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Cincin"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Permata"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Ciuman"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Buket"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pasangan dengan tanda hati"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Pernikahan"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Hati yang berdebar"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Patah hati"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dua hati"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Hati yang berkilauan"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Tanda hati yang membesar"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hati yang terpanah"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Hati biru"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Hati hijau"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Hati kuning"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Hati ungu"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hati dengan pita"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Hati yang berputar"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Dekorasi hati"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Bentuk berlian degan titik di dalamnya"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Bohlam listrik"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Simbol marah"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bom"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Simbol tidur"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Simbol benturan"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Simbol cipratan keringat"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Tetesan"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Simbol tanda pisah"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Tumpukan kotoran"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bisep ditekuk"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Simbol pusing"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Balon ucapan"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Balon pemikiran"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Bunga putih"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbol angka 100"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Tas uang"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Nilai tukar mata uang"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Tanda dolar tebal"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kartu kredit"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Uang kertas dengan tanda yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Uang kertas dengan tanda dolar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Uang kertas dengan tanda euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Uang kertas dengan tanda poundsterling"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Uang dengan sayap"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Grafik dengan tren ke atas dan tanda yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Kursi"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Komputer pribadi"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Tas kantor"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Disk mini"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disket"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Piringan disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Folder file"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Buka folder file"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Halaman dengan gulungan"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Halaman menghadap ke atas"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Kalender dirobek"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Indeks kartu"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Grafik dengan tren meningkat"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Grafik dengan tren menurun"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Grafik batang"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Papan klip"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pin"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Pin bulat"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Penjepit kertas"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Penggaris lurus"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Penggaris segitiga"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Tab bookmark"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Buku besar"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Bloknot"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Bloknot dengan sampul dekoratif"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Buku tertutup"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Buku terbuka"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Buku hijau"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Buku biru"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Buku oranye"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Buku"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Lencana nama"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Gulungan perkamen"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Gagang telepon"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Mesin faks"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena satelit"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Pengeras suara ditujukan untuk publik"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Suara megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Baki keluaran"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Baki masukan"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Simbol email"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Amplop yang masuk"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Amplop dengan panah ke bawah di atas"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Kotak pos tertutup dengan bendera turun"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Kotak pos tertutup dengan bendera terangkat"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Kotak pos terbuka dengan bendera terangkat"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Kotak pos terbuka dengan bendera turun"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Kotak pos"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Terompet kantor pos"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Koran"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Ponsel"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Ponsel dengan panah ke kanan di sebelah kiri"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Mode getar"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Ponsel nonaktif"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Tidak boleh menggunakan ponsel"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena dengan simbol batang"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Kamera video"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisi"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Kaset video"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Panah melilit ke arah kanan"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Simbol ulang horizontal"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Simbol ulang sekali horizontal"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Simbol ulang vertikal dengan panah searah jarum jam"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Simbol ulang vertikal dengan panah berlawanan arah jarum jam"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbol kecerahan rendah"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbol kecerahan tinggi"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Simbol pengeras suara nonaktif"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Pengeras suara"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Speaker dengan satu gelombang suara"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Speaker dengan tiga gelombang suara"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Baterai"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Steker listrik"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Kaca pembesar mengarah ke kiri"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Kaca pembesar mengarah ke kanan"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Gembok dengan pena tinta"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Kunci dan gembok terkunci"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Kunci"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Gembok"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Gembok terbuka"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Bel"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Bel dengan tanda coret"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bookmark"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Simbol tautan"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Tombol radio"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Tulisan BACK dengan panah ke kiri di atas"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Tulisan END dengan panah ke kiri di atas"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Tulisan ON dengan tanda seru serta panah kiri kanan di atas"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Tulisan SOON dengan panah ke kiri di atas"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Tulisan TOP dengan panah ke kiri di atas"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbol khusus 18 tahun"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Cap tombol 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Simbol masukan untuk huruf kapital"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Simbol masukan untuk huruf kecil"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Simbol masukan untuk angka"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbol masukan untuk simbol"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Simbol masukan untuk huruf"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Api"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Obor listrik"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Kunci pas"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Palu"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Mur dan baut"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Pisau Jepang"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bola kristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Heksagram dengan titik di tengah"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Simbol Jepang untuk pemula"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Lambang trisula"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Tombol kotak hitam"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Tombol kotak putih"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Lingkaran besar merah"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Lingkaran besar biru"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Lingkaran besar oranye"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Permata besar biru"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Permata kecil oranye"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Permata kecil biru"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Segitiga merah menunjuk ke atas"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Segitiga merah menunjuk ke bawah"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Segitiga kecil merah menunjuk ke atas"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Segitiga kecil merah menunjuk ke bawah"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Jam menunjukkan pukul satu"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Jam menunjukkan pukul dua"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Jam menunjukkan pukul tiga"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Jam menunjukkan pukul empat"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Jam menunjukkan pukul lima"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Jam menunjukkan pukul enam"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Jam menunjukkan pukul tujuh"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Jam menunjukkan pukul delapan"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Jam menunjukkan pukul sembilan"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Jam menunjukkan pukul sepuluh"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Jam menunjukkan pukul sebelas"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Jam menunjukkan pukul dua belas"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Jam menunjukkan pukul setengah dua"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Jam menunjukkan pukul setengah tiga"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Jam menunjukkan pukul setengah empat"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Jam menunjukkan pukul setengah lima"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Jam menunjukkan pukul setengah enam"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Jam menunjukkan pukul setengah tujuh"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Jam menunjukkan pukul setengah delapan"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Jam menunjukkan pukul setengah sembilan"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Jam menunjukkan pukul setengah sepuluh"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Jam menunjukkan pukul setengah sebelas"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Jam menunjukkan pukul setengah dua belas"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Jam menunjukkan pukul setengah satu"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Gunung fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Menara Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Patung Liberty"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Siluet Jepang"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Wajah menyeringai"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Wajah meringis dengan mata tersenyum"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Wajah dengan air mata bahagia"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Wajah tersenyum dengan mulut terbuka"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Wajah tersenyum dengan mulut terbuka dan mata tersenyum"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Wajah tersenyum dengan mulut terbuka dan keringat dingin"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Wajah tersenyum dengan mulut terbuka dan mata tertutup rapat"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Wajah tersenyum dengan lingkaran cahaya"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Wajah tersenyum dengan tanduk"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Wajah dengan salah satu mata mengedip"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Wajah tersenyum dengan mata tersenyum"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Wajah sedang menikmati makanan lezat"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Wajah lega"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Wajah tersenyum dengan mata bentuk hati"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Wajah tersenyum dengan kacamata"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Wajah mencibir"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Wajah netral"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Wajah tanpa ekspresi"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Wajah tidak senang"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Wajah dengan keringat dingin"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Wajah murung"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Wajah bingung"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Wajah kacau"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Wajah mencium"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Wajah melempar ciuman"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Wajah mencium dengan mata tersenyum"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Wajah mencium dengan mata tertutup"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Wajah menjulurkan lidah"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Wajah menjulurkan lidah dengan salah satu mata berkedip"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Wajah menjulurkan lidah dengan mata tertutup rapat"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Wajah kecewa"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Wajah khawatir"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Wajah marah"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Wajah cemberut"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Wajah menangis"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Wajah gigih"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Wajah dengan ekspresi kemenangan"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Kecewa tapi berwajah lega"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Wajah merengut dengan mulut terbuka"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Wajah sedih"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Wajah takut"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Wajah letih"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Wajah mengantuk"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Wajah lelah"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Wajah meringis"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Wajah menangis keras"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Wajah dengan mulut terbuka"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Wajah hening"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Wajah dengan mulut terbuka dan keringat dingin"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Wajak berteriak dalam ketakutan"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Wajah kaget"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Wajah merona"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Wajah tidur"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Wajah pusing"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Wajah tanpa mulut"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Wajah dengan masker bedah"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Wajah menyeringai dengan mata tersenyum"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Wajah kucing dengan air mata bahagia"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Wajah kucing tersenyum dengan mulut terbuka"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Wajah kucing tersenyum dengan mata bentuk hati"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Wajah kucing dengan senyum sinis"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Wajah kucing mencium dengan mata tertutup"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Wajah kucing cemberut"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Wajah kucing menangis"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Wajah kucing letih"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Wajah dengan isyarat tidak setuju"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Wajah dengan isyarat oke"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Orang yang membungkuk dalam-dalam"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Monyet menutup mata"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Monyet menutup telinga"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Monyet menutup mulut"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Orang yang bahagia mengangkat satu tangan"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Orang bersorak dengan mengangkat kedua tangan"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Orang merengut"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Orang dengan wajah cemberut"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Orang dengan tangan terlipat"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Roket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Lokomotif uap"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Gerbong"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Kereta kecepatan tinggi"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Kereta kecepatan tinggi dengan ujung seperti peluru"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Kereta api"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Angkutan cepat"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Kereta listrik"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stasiun"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Trem"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Trem"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Bus yang melaju"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Bus listrik"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Halte bus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Bus mini"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulan"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Mobil pemadam kebakaran"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Mobil polisi"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Mobil polisi yang melaju"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taksi yang melaju"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Mobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Mobil yang melaju"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Mobil rumah"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Truk pengiriman"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Truk gandeng"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorel"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Jalur kereta gunung"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Kereta monorel suspensi"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Gondola gunung"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Kereta gantung"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Kapal"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Perahu dayung"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Perahu motor cepat"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Lampu lalu lintas mendatar"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Lampu lalu lintas tegak lurus"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Tanda kontruksi"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Lampu putar mobil polisi"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bendera segitiga di pos"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Pintu"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Tanda larangan masuk"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Simbol merokok"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Simbol dilarang merokok"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Simbol masukkan sampah di tempatnya"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbol jangan buang sampah sembarangan"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbol air minum"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbol air tidak dapat diminum"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Sepeda"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Sepeda dilarang melintas"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Pengendara sepeda"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Pengendara sepeda gunung"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pejalan kaki"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Pejalan kaki dilarang melintas"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Tempat anak menyebrang"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Simbol pria"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Simbol wanita"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Ruang istirahat"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Simbol bayi"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Pancuran"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Kamar mandi"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bak mandi"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kontrol paspor"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Bea cukai"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Klaim bagasi"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Bagasi tertinggal"</string>
+</resources>
diff --git a/java/res/values-in/strings-talkback-descriptions.xml b/java/res/values-in/strings-talkback-descriptions.xml
index f7334d9..fb6b6f9 100644
--- a/java/res/values-in/strings-talkback-descriptions.xml
+++ b/java/res/values-in/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Tidak ada teks yang dimasukkan"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> mengoreksi <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> menjadi <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> melakukan koreksi otomatis"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Tidak ada saran"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Karakter tak dikenal"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Simbol lainnya"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Huruf kapital I dengan aksen titik di bagian atas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol tak dikenal"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji tak dikenal"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Wajah bosan"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Wajah malu"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Wajah mengenakan kacamata hitam"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Wajah terkejut"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Wajah mencium"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Wajah merengut"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Karakter alternatif tersedia"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Karakter alternatif ditolak"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Saran alternatif tersedia"</string>
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 129a23c..49873b8 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar jika tombol ditekan"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Berbunyi jika tombol ditekan"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Muncul saat tombol ditekan"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferensi"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Akun &amp; Privasi"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Tampilan &amp; Tata Letak"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Ketikan Isyarat"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Koreksi teks"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Lanjutan"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktifkan keyboard terpisah"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sinkronisasi Keyboard Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinkronisasi diaktifkan"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Menyinkronkan kamus pribadi di perangkat"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinkronkan sekarang"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Menghapus data awan"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Menghapus data yang disinkronkan dari Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Data yang disinkronkan akan dihapus dari awan. Anda yakin?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Hapus"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Batal"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Kamus pribadi akan disinkronkan dan dicadangkan ke server Google. Informasi statistik tentang frekuensi kata dapat dikumpulkan untuk membantu menyempurnakan produk kami. Pengumpulan dan penggunaan data tunduk pada "<a href="https://www.google.com/policies/privacy">"Kebijakan Privasi Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Tambahkan akun Google ke perangkat ini untuk mengaktifkan fitur ini"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Beralih ke metode masukan lain"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tombol beralih bahasa juga mencakup metode masukan lain"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tombol pengalih bahasa"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Tampilkan saat beberapa bahasa masukan diaktifkan"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Tampilkan indikator geser"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Tampilkan isyarat visual saat menggeser dari tombol Shift/Simbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Tampilkan saran koreksi"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Tampilkan kata yang disarankan ketika mengetik"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Selalu tampilkan"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Tampilkan dalam mode potret"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Selalu sembunyikan"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokir kata tak pantas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Jangan sarankan kata yang berpotensi menyinggung"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Koreksi otomatis"</string>
@@ -77,7 +79,7 @@
     <string name="bigram_prediction_summary" msgid="3896362682751109677">"Gunakan kata sebelumnya dalam membuat saran"</string>
     <string name="gesture_input" msgid="826951152254563827">"Aktifkan pengetikan isyarat"</string>
     <string name="gesture_input_summary" msgid="9180350639305731231">"Masukkan kata dengan menggeser huruf ke kanan/kiri"</string>
-    <string name="gesture_preview_trail" msgid="3802333369335722221">"Tampilkan jalur isyarat"</string>
+    <string name="gesture_preview_trail" msgid="3802333369335722221">"Tampilkan jejak isyarat"</string>
     <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Pratinjau mengambang dinamis"</string>
     <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Lihat kata yang disarankan saat melakukan isyarat"</string>
     <string name="gesture_space_aware" msgid="2078291600664682496">"Isyarat frasa"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tombol masukan suara"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Tidak ada metode masukan suara yang diaktifkan. Periksa setelan Bahasan &amp; masukan."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Kirim masukan"</string>
-    <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Bahasa"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Bantuan &amp; masukan"</string>
+    <string name="select_language" msgid="5709487854987078367">"Bahasa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Sentuh di sini untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus yang tersedia"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema keyboard"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Beralih akun"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Tidak ada akun yang dipilih"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Saat ini menggunakan <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Oke"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Batal"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Keluar"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Pilih akun yang akan digunakan"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inggris (Inggris)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inggris (AS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanyol (AS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbia (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Inggris (Inggris)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Inggris (AS)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>) Spanyol (AS)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Sirilik)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Rapat)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Tidak ada bahasa (Abjad)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abjad (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abjad (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Abjad (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Abjad (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema keyboard"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Gaya masukan khusus"</string>
     <string name="add_style" msgid="6163126614514489951">"Tambah gaya"</string>
     <string name="add" msgid="8299699805688017798">"Tambahkan"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktifkan"</string>
     <string name="not_now" msgid="6172462888202790482">"Nanti saja"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sudah ada gaya masukan yang sama: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Penundaan tekan lama tombol"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durasi getar saat tekan tombol"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume suara saat tekan tombol"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Membaca file kamus eksternal"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Tidak ada file kamus di folder Unduhan"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih file kamus untuk dipasang"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Yakin ingin memasang file ini untuk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Terjadi kesalahan"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Penundaan tekan lama tombol"</string>
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Selamat datang di <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"dengan Ketikan Isyarat"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Sekarang Anda dapat mengetik di semua aplikasi favorit Anda dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurasikan bahasa tambahan"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Selesai"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Tampilkan ikon aplikasi"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Menampillkan ikon aplikasi di peluncur"</string>
     <string name="app_name" msgid="6320102637491234792">"Penyedia Kamus"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Penyedia Kamus"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Layanan Kamus"</string>
diff --git a/java/res/values-is-rIS/strings-talkback-descriptions.xml b/java/res/values-is-rIS/strings-talkback-descriptions.xml
index 978b079..b4f2a14 100644
--- a/java/res/values-is-rIS/strings-talkback-descriptions.xml
+++ b/java/res/values-is-rIS/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Engin texti sleginn inn"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> leiðréttir <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> yfir í <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> framkvæmir sjálfvirka leiðréttingu"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Engin tillaga"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Óþekktur stafur"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Fleiri tákn"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Hástafurinn I með depli"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Óþekkt tákn"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Óþekkt emoji-tákn"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Andlit sem leiðist"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Skömmustulegt andlit"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Andlit með sólgleraugu"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Andlit sem undrast"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Andlit sem kyssir"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Andlit með grettu"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Aukalegir stafir eru í boði"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Aukalegum stöfum lokað"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Aukalegar tillögur eru í boði"</string>
diff --git a/java/res/values-is-rIS/strings.xml b/java/res/values-is-rIS/strings.xml
index c5b489f..9e63a76 100644
--- a/java/res/values-is-rIS/strings.xml
+++ b/java/res/values-is-rIS/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Titringur þegar ýtt er á lykla"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Hljóð þegar ýtt er á lykil"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Stækkaðir stafir við innslátt"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Inntaksvalkostir"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Útlit"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Tungumálavalkostir"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Still. bendingainnsláttar"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Kjörstillingar"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Reikningar og persónuvernd"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Útlit og uppsetning"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Bendingainnsláttur"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Textaleiðrétting"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Ítarlegt"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Þema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Virkja skipt lyklaborð"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Samstilling Google lyklaborðs"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Kveikt er á samstillingu"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Samstilltu orðabókina þína á milli tækja"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Samstilla núna"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Eyða gögnum í skýi"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Eyðir samstilltum gögnum af Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Samstilltum gögnum frá þér verður eytt úr skýinu. Ertu viss?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Eyða"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Hætta við"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Orðabókin þín verður samstillt og afrituð á netþjóna Google. Hugsanlega verður talnagögnum um tíðni orða safnað til að gera vörur okkar betri. Söfnun og notkun allra upplýsinga fellur undir "<a href="https://www.google.com/policies/privacy">"persónuverndarstefnu Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Bættu Google reikningi við tækið til að virkja þennan eiginleika"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skipta um innsláttaraðferð"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Lykill til að skipta um mál inniheldur aðrar innsláttaraðferðir"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Lykill til að breyta tungumáli"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Sýna þegar mörg innsláttartungumál eru virk"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Sýna rennivísi"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Sýna myndræna vísbendingu þegar rennt er af Shift eða táknalykli"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Hunsunartöf lyklaglugga"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Engin töf"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Sjálfgefið"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Aðalorðabók"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Sýna leiðréttingartillögur"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Sýna orðatillögur við innslátt"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Sýna alltaf"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Sýna í skammsniði"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Fela alltaf"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Útiloka dónaleg orð"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ekki stinga upp á orðum sem kunna að vera dónaleg"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Sjálfv. leiðrétting"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Raddinntakslykill"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Engar innsláttaraðferðir fyrir rödd virkar. Kannaðu stillingar tungumáls og innsláttar."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Stilla innsláttaraðferðir"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Innsláttartungumál"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Senda inn álit"</string>
-    <string name="select_language" msgid="3693815588777926848">"Innsláttartungumál"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Tungumál"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hjálp og ábendingar"</string>
+    <string name="select_language" msgid="5709487854987078367">"Tungumál"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Snertu aftur til að vista"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Snertu hér til að vista"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Orðabók í boði"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Þema lyklaborðs"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Skipta um reikning"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Engir reikningar valdir"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> í notkun"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Í lagi"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Hætta við"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Skrá út"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Veldu reikning til að nota"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Enskt (Bretland)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Enskt (Bandaríkin)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spænskt (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbneskt (latneskt)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Enskt (Bretland) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Enskt (Bandaríkin) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spænskt (Bandaríkin) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbneskt (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (hefðbundið)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillískt)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latneskt)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lítið)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ekkert tungumál (stafróf)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Stafróf (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Stafróf (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Stafróf (tölva)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji-tákn"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Lyklaborðsþema"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Hvítt gegnsætt"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Blátt gegnsætt"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Dökkt"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Ljóst"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Sérsniðnar innsláttaraðferðir"</string>
     <string name="add_style" msgid="6163126614514489951">"Bæta stíl við"</string>
     <string name="add" msgid="8299699805688017798">"Bæta við"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Kveikja"</string>
     <string name="not_now" msgid="6172462888202790482">"Ekki núna"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Sama innsláttaraðferð er þegar fyrir hendi: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Töf áður en lykli er haldið inni"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Lengd lyklatitrings"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Styrkur lyklahljóða"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Lesa utanaðkomandi orðabókarskrá"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Engar orðabókarskrár í niðurhalsmöppunni"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Veldu orðabókarskrá til að setja upp"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Viltu setja upp þessa skrá fyrir <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Villa kom upp"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Töf áður en lykli er haldið inni"</string>
     <string name="button_default" msgid="3988017840431881491">"Sjálfgefið"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Velkomin(n) í <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"með bendingainnslætti"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nú geturðu notað <xliff:g id="APPLICATION_NAME">%s</xliff:g> til að skrifa í öllum uppáhaldsforritunum þínum."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Stilla önnur tungumál"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Lokið"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Sýna forritstákn"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Sýna forritstákn í ræsiforritinu"</string>
     <string name="app_name" msgid="6320102637491234792">"Orðabókarveita"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Orðabókarveita"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Orðabókarþjónusta"</string>
diff --git a/java/res/values-it/strings-emoji-descriptions.xml b/java/res/values-it/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..9fccbf1
--- /dev/null
+++ b/java/res/values-it/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Simbolo di copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Simbolo di marchio registrato"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Doppio punto esclamativo"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Punto esclamativo e punto di domanda"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Simbolo del marchio registrato"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informazioni"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Freccia a sinistra e a destra"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Freccia in giù e in su"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Freccia nord ovest"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Freccia nord est"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Freccia sud est"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Freccia sud ovest"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Freccia a sinistra con gancio"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Freccia a destra con gancio"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Orologio"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Clessidra"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Doppio triangolo nero verso destra"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Doppio triangolo nero verso sinistra"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Doppio triangolo nero verso l\'alto"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Doppio triangolo nero verso il basso"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Sveglia"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Clessidra con sabbia che scorre"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Lettera M maiuscola cerchiata"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Quadrato piccolo pieno"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Quadrato piccolo vuoto"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triangolo nero verso destra"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triangolo nero verso sinistra"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Triangolo medio vuoto"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Triangolo medio pieno"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Quadrato medio piccolo vuoto"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Quadrato medio piccolo pieno"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sole nero con raggi"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nuvola"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telefono"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Casella selezionata"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Ombrello con gocce di pioggia"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Bevanda calda"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Indice alzato"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Faccina che sorride"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Ariete"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Toro"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gemelli"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancro"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leone"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Vergine"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Bilancia"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpione"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittario"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorno"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquario"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Pesci"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Picche"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Fiori"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Cuori"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Quadri"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Sorgente termale"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Simbolo universale del riciclo"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Simbolo della sedia a rotelle"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ancora"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Simbolo di attenzione"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Simbolo dell\'alta tensione"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Cerchio medio vuoto"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Cerchio medio pieno"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Pallone da calcio"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Palla da baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Pupazzo di neve"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sole coperto"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ofiuco"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Divieto di accesso"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Chiesa"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontana"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandiera in buca"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Barca a vela"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tenda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Pompa di benzina"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Forbici"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Segno di spunta grande vuoto"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Aereo"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Busta"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Pugno alzato"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Mano alzata"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Segno di vittoria"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Matita"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Pennino"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Segno di spunta pieno"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Segno di moltiplicazione pieno"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Stelline"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisco a otto punte"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Stella a otto punte"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Fiocco di neve"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Scintilla"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Croce"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Croce in negativo con quadrato"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Punto di domanda pieno"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Punto di domanda vuoto"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Punto esclamativo vuoto"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Punto esclamativo pieno"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Cuore nero pieno"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Segno più"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Segno meno"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Segno diviso"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Freccia nera verso destra"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Occhiello"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Doppio occhiello"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Freccia curva da sinistra diretta verso l\'alto"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Freccia curva da sinistra diretta verso il basso"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Freccia nera verso sinistra"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Freccia nera verso l\'alto"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Freccia nera verso il basso"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Quadrato grande pieno"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Quadrato grande vuoto"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Stella media vuota"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Cerchio grande con contorno"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Trattino ondulato"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Simbolo di cambio parte"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideogramma \"congratulazioni\" cerchiato"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideogramma \"segreto\" cerchiato"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Tessera del drago rosso Mahjong"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Joker nero delle carte"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Gruppo sanguigno A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Gruppo sanguigno B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Gruppo sanguigno O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parcheggio"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Gruppo sanguigno AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Simbolo quadrato CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Simbolo quadrato Cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Simbolo quadrato Free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Simbolo quadrato ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Simbolo quadrato New"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Simbolo quadrato NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Simbolo quadrato OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Simbolo quadrato SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Simbolo quadrato UP con punto esclamativo"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Simbolo quadrato VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Parola giapponese \"qui\""</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Parola giapponese \"servizio\""</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogramma quadrato \"gratis\""</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogramma quadrato \"posto prenotato\""</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogramma quadrato \"divieto\""</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogramma quadrato \"vacanza\""</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogramma quadrato \"consenso\""</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogramma quadrato \"al completo\""</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogramma quadrato \"a pagamento\""</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogramma quadrato \"mensile\""</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogramma quadrato \"richiesta\""</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogramma quadrato \"sconto\""</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogramma quadrato \"in funzione\""</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideogramma rotondo \"vantaggio\""</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideogramma rotondo \"accetta\""</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Nebbia"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Ombrello chiuso"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Notte stellata"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Alba sulle montagne"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Alba"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Città al tramonto"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Tramonto"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arcobaleno"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Ponte di notte"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Onda"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulcano"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Via Lattea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globo Europa-Africa"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globo Americhe"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globo Asia-Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo con meridiani"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbolo della luna nuova"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbolo della luna crescente"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbolo del primo quarto di luna"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbolo della gibbosa crescente"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbolo della luna piena"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbolo della gibbosa calante"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbolo dell\'ultimo quarto di luna"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbolo della luna calante"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Luna crescente"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Luna nuova con faccina"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Primo quarto di luna con faccina"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Ultimo quarto di luna con faccina"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Luna piena con faccina"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sole con faccina"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Stella che brilla"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Stella cadente"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Nocciola"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Germoglio"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Albero sempreverde"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Albero deciduo"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipano"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Fiore di ciliegio"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Ibisco"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Girasole"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Fiore"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Pannocchia"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Spiga di riso"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Pianta"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Quadrifoglio"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Foglia d\'acero"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Foglia caduta"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Foglia al vento"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Fungo"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Pomodoro"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Melanzana"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uva"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melone"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Anguria"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarino"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limone"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Mela rossa"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Mela verde"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pesca"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Ciliegie"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Fragola"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Fetta di pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Carne con osso"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Coscia di pollo"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Galletta di riso"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Arancino di riso"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Riso bollito"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Riso al curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Ramen"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pane"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patatine fritte"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Patata arrosto"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Gambero fritto"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Crocchetta di pesce con decorazione a spirale"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Cono gelato"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Granita"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Coppa gelato"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Ciambella"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biscotto"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barretta di cioccolato"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Caramella"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lecca lecca"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Budino"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Vaso di miele"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Fetta di torta"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Piatto pronto"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Ciotola di cibo"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Padella"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Forchetta e coltello"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tazza senza manico"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Bottiglia e tazza di sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Bicchiere di vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Bicchiere da cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Cocktail tropicale"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Boccale di birra"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Brindisi con boccali di birra"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberon"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Fiocco"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Pacchetto regalo"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Torta di compleanno"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Zucca di Halloween"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Albero di Natale"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Babbo Natale"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fuochi d\'artificio"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Stella filante"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Palloncino"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Spara coriandoli"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Palla di coriandoli"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Bambù decorato"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bandiere incrociate"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Pino decorato"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Bambole giapponesi"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Aquilone a forma di carpa"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Campana al vento"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Festa della contemplazione della luna"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Zaino di scuola"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Cappello da laureato"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cavallo da giostra"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ruota panoramica"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Montagne russe"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Canna da pesca con pesce"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microfono"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Cinepresa"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Cuffie"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Tavolozza dei colori"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cilindro"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Tendone da circo"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Biglietto"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Ciak"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Maschere"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videogioco"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Bersaglio"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Slot machine"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliardo"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dado da gioco"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Carte dei fiori"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota musicale"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Note musicali"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Sassofono"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Chitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Tastiera"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Tromba"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violino"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Pentagramma"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Maglia da corsa con fascia"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Racchetta e pallina da tennis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Sci e scarpone da sci"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Pallone da basket e canestro"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandiera a scacchi"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Omino in snowboard"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Omino che corre"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Omino che fa surf"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Coppa"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Ippica"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Football americano"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Pallone da rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Omino che nuota"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Casa"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa con giardino"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Uffici"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Ufficio postale giapponese"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Ufficio postale europeo"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Ospedale"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banca"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bancomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Motel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Autogrill"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Scuola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Centro commerciale"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabbrica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lanterna rossa"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Casa giapponese"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castello"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Ratto"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Topo"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Bue"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Bufalo"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Mucca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Coniglio"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gatto"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drago"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Coccodrillo"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balena"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Lumaca"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Serpente"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cavallo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ariete"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Capra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Pecora"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Scimmia"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gallo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Gallina"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Cane"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Maiale"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Cinghiale"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Polpo"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Conchiglia a spirale"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insetto"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Formica"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Ape"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Coccinella"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Pesce"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Pesce tropicale"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Pesce palla"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tartaruga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pulcino che esce dall\'uovo"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pulcino"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pulcino visto di fronte"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Uccellino"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pinguino"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Barboncino"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedario"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Cammello"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfino"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Faccina di topo"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Faccina di mucca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Faccina di tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Faccina di coniglio"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Faccina di gatto"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Faccina di drago"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Balena che spruzza acqua"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Faccina di cavallo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Faccina di scimmia"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Faccina di cane"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Faccina di maiale"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Faccina di rana"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Faccina di criceto"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Faccina di lupo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Faccina di orso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Faccina di panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Naso di maiale"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Impronte di zampe"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Occhi"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Orecchio"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Naso"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Bocca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lingua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Indice verso l\'alto"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Indice verso il basso"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Indice verso sinistra"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Indice verso destra"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Pugno chiuso"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Mano che saluta"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Mano che fa OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Pollice alzato"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Pollice abbassato"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Mani che applaudono"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Mani aperte"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Corona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Cappello da donna"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Occhiali da vista"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Cravatta"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Maglietta"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Abito"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Vestiti da donna"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Porta monete"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Borsa"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Borsetta"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Scarpa da uomo"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Scarpa da ginnastica"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Scarpa con il tacco"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandalo da donna"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Stivali da donna"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Impronte"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Profilo di persona"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Profilo di due persone"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Bambino"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Bambina"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Uomo"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Donna"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Famiglia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Uomo e donna mano nella mano"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Due uomini mano nella mano"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Due donne mano nella mano"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Poliziotto"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Coniglietta"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Sposa con il velo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persona con i capelli biondi"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Uomo con zucchetto"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Uomo con turbante"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Uomo anziano"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Donna anziana"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Neonato"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Operaio edile"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Principessa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Orco giapponese"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Goblin giapponese"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Angioletto"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Alieno extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Mostro alieno"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Diavoletto"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Teschio"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Punto informazioni"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guardia"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Omino che balla"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rossetto"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Smalto per unghie"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Massaggio facciale"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Taglio di capelli"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barbiere"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Siringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pastiglia"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Segno delle labbra"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Lettera d\'amore"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anello"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Diamante"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bacio"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Mazzo di fiori"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Coppia con cuore"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Matrimonio"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Cuore che batte"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Cuore infranto"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Due cuori"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Cuore con stelline"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Cuore che cresce"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Cuore con freccia"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Cuore blu"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Cuore verde"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Cuore giallo"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Cuore viola"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Cuore con fiocco"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Cuori che girano"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Decorazione con cuore"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Forma di diamante con punto centrale"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Lampadina"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Simbolo della rabbia"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Simbolo del sonno"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Simbolo di collisione"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Simbolo bagno di sudore"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Goccia"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Nuvola di polvere"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Cacca"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bicipite teso"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Simbolo della testa che gira"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Fumetto"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Nuvoletta"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Fiorellino"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbolo dei cento punti"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Sacco per soldi"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Cambio di valuta"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Simbolo del dollaro"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Carta di credito"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banconota con il simbolo dello yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banconota con il simbolo del dollaro"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banconota con il simbolo dell\'euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banconota con il simbolo della sterlina"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Soldi con le ali"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Grafico ascendente con simbolo dello yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Posto a sedere"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personal computer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Valigetta"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppy disk"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disco ottico"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Cartella di file"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Cartella di file aperta"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Pagina arricciata"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Pagina vista di fronte"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendario"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendario a strappo"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Schedario"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Grafico ascendente"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Grafico discendente"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Grafico a barre"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Portablocco"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Puntina"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Puntina con testa arrotondata"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Graffetta"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Righello"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Squadra"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Linguette segnalibro"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Registro"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Taccuino"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Taccuino con copertina decorata"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Libro chiuso"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Libro aperto"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Libro verde"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Libro blu"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Libro arancione"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Libri"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Tesserino per nome"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Pergamena"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Cornetta del telefono"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Cercapersone"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antenna satellitare"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Altoparlante"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafono"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Posta in uscita"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Posta in entrata"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pacco"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Simbolo dell\'email"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Posta in arrivo"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Busta con sopra una freccia verso il basso"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Cassetta postale chiusa con bandierina in giù"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Cassetta postale chiusa con bandierina in su"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Cassetta postale aperta con bandierina in su"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Cassetta postale aperta con bandierina in giù"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Cassetta delle lettere"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Corno postale"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Quotidiano"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Cellulare"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Cellulare con freccia verso destra a sinistra"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Modalità vibrazione"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Cellulare spento"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Cellulare con simbolo di divieto"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna con tacche"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotocamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videocamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisione"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocassetta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Frecce incrociate verso destra"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Circuito aperto in senso orario con freccia sinistra e destra"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Circuito aperto in senso orario con freccia sinistra e destra e numero uno cerchiato sovrapposto"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Circuito aperto in senso orario con freccia verso l\'alto e verso il basso"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Circuito aperto in senso antiorario con freccia verso l\'alto e verso il basso"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbolo di bassa luminosità"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbolo di alta luminosità"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altoparlante con simbolo di divieto"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altoparlante"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altoparlante con un\'onda sonora"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altoparlante con tre onde sonore"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batteria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Spina elettrica"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lente di ingrandimento verso sinistra"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lente di ingrandimento verso destra"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lucchetto con penna stilo"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Lucchetto chiuso con chiave"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Chiave"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lucchetto"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Lucchetto aperto"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Campana"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Campana con simbolo di divieto"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Segnalibro"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Simbolo di legame"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Pulsante opzione"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"Back\" con sopra freccia verso sinistra"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"End\" con sopra freccia verso sinistra"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"On\" e punto esclamativo con sopra freccia verso sinistra e destra"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"Soon\" con sopra freccia verso destra"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"Top\" con sopra freccia verso l\'alto"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbolo vietato ai minori di diciotto anni"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tasto dieci"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Simbolo di immissione per lettere maiuscole"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Simbolo di immissione per lettere minuscole"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Simbolo di immissione per numeri"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbolo di immissione per i simboli"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Simbolo di immissione per caratteri alfabetici"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fuoco"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Torcia elettrica"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Chiave inglese"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martello"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Bullone"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Coltello da cucina"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscopio"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescopio"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Sfera di cristallo"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Stella a sei punte con punto centrale"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Simbolo giapponese per \"principiante\""</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Simbolo del tridente"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Pulsante quadrato pieno"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Pulsante quadrato vuoto"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Cerchio rosso grande"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Cerchio blu grande"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Rombo arancione grande"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Rombo blu grande"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Rombo arancione piccolo"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Rombo blu piccolo"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triangolo rosso con punta verso l\'alto"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triangolo rosso con punta verso il basso"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triangolo rosso piccolo con punta verso l\'alto"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triangolo rosso piccolo con punta verso il basso"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Orologio che segna l\'una"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Orologio che segna le due"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Orologio che segna le tre"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Orologio che segna le quattro"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Orologio che segna le cinque"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Orologio che segna le sei"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Orologio che segna le sette"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Orologio che segna le otto"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Orologio che segna le nove"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Orologio che segna le dieci"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Orologio che segna le undici"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Orologio che segna le dodici"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Orologio che segna l\'una e mezza"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Orologio che segna le due e mezza"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Orologio che segna le tre e mezza"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Orologio che segna le quattro e mezza"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Orologio che segna le cinque e mezza"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Orologio che segna le sei e mezza"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Orologio che segna le sette e mezza"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Orologio che segna le otto e mezza"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Orologio che segna le nove e mezza"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Orologio che segna le dieci e mezza"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Orologio che segna le undici e mezza"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Orologio che segna le dodici e mezza"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Monte Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo Tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statua della Libertà"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Mappa del Giappone"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Faccina che sogghigna"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Faccina che sogghigna con gli occhi sorridenti"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Faccina con lacrime di gioia"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Faccina sorridente con la bocca aperta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Faccina che ride con la bocca aperta e gli occhi sorridenti"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Faccina sorridente con la bocca aperta e le gocce di sudore"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Faccina sorridente con la bocca aperta e gli occhi chiusi"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Faccina sorridente con l\'aureola"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Faccina sorridente con le corna"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Faccina che fa l\'occhiolino"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Faccina che sorride con gli occhi sorridenti"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Faccina che si lecca i baffi"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Faccina sollevata"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Faccina sorridente con gli occhi a forma di cuore"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Faccina sorridente con gli occhiali da sole"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Faccina che fa un sorrisetto"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Faccina neutra"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Faccina inespressiva"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Faccina contrariata"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Faccina sudata"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Faccina pensierosa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Faccina confusa"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Faccina frustrata"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Faccina che dà baci"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Faccina che manda un bacio"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Faccina che dà baci con gli occhi sorridenti"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Faccina che dà baci con gli occhi chiusi"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Faccina con la lingua fuori"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Faccina con la lingua fuori che fa l\'occhiolino"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Faccina con la lingua fuori e gli occhi chiusi"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Faccina delusa"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Faccina preoccupata"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Faccina arrabbiata"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Faccina imbronciata"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Faccina che piange"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Faccina perseverante"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Faccina trionfante"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Faccina delusa ma sollevata"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Faccina corrucciata con la bocca aperta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Faccina angosciata"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Faccina impaurita"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Faccina esausta"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Faccina assonnata"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Faccina stanca"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Faccina che fa una smorfia"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Faccina che piange disperata"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Faccina con la bocca aperta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Faccina sommessa"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Faccina sudata con la bocca aperta"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Faccina che grida di paura"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Faccina stupita"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Faccina con le guance rosse"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Faccina addormentata"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Faccina frastornata"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Faccina senza bocca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Faccina con mascherina di protezione"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Gatto che sogghigna con occhi sorridenti"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Gatto con lacrime di gioia"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Gatto sorridente con la bocca aperta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Gatto sorridente con gli occhi a forma di cuore"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Gatto con sorriso sarcastico"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Gatto che dà baci con gli occhi chiusi"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Gatto imbronciato"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Gatto che piange"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Gatto esausto"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Faccina con gesto di rifiuto"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Faccina con gesto OK"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persona che fa l\'inchino"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Scimmietta non vedo"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Scimmietta non sento"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Scimmietta non parlo"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Persona felice che alza una mano"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persona con le mani alzate in segno di giubilo"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Persona corrucciata"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persona con faccina imbronciata"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persona con le mani giunte"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Razzo"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Elicottero"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotiva a vapore"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagone"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Treno ad alta velocità"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Treno ad alta velocità con la punta arrotondata"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Treno"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metropolitana"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Metrotranvia"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stazione"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tram"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagone del tram"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autobus in arrivo"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Filobus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Fermata dell\'autobus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulanza"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Camion dei pompieri"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Auto della polizia"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Auto della polizia in arrivo"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi in arrivo"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobile"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automobile in arrivo"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Camper"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camion"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Bilico"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Trattore"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorotaia"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ferrovia di montagna"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Funivia"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Funicolare"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Funivia aerea"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Nave"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Barca a remi"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motoscafo"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semaforo orizzontale"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semaforo verticale"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Cartello area cantiere"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Lampeggiante della polizia"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bandierina rossa"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Cartello Divieto di accesso"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Simbolo della sigaretta"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Simbolo Vietato fumare"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Simbolo della raccolta rifiuti"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbolo Vietato gettare rifiuti"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbolo di acqua potabile"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbolo di acqua non potabile"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicletta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Divieto di transito alle biciclette"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista in mountain bike"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pedone"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Divieto di transito ai pedoni"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Attraversamento bambini"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Simbolo del bagno degli uomini"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Simbolo del bagno delle donne"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Bagni"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Simbolo del neonato"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilette"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Doccia"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bagno"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Vasca da bagno"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Controllo passaporto"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Dogana"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Ritiro bagagli"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Deposito bagagli"</string>
+</resources>
diff --git a/java/res/values-it/strings-talkback-descriptions.xml b/java/res/values-it/strings-talkback-descriptions.xml
index 8665530..6b23710 100644
--- a/java/res/values-it/strings-talkback-descriptions.xml
+++ b/java/res/values-it/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nessun testo inserito"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corregge <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> con <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> esegue la correzione automatica"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nessun suggerimento"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Carattere sconosciuto"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Maiusc"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Altri simboli"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiuscola, punto sovrascritto"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbolo sconosciuto"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji sconosciuta"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Faccina annoiata"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Faccina imbarazzata"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Faccina che indossa occhiali da sole"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Faccina sorpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Faccina che dà baci"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Faccina corrucciata"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Sono disponibili caratteri alternativi"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"I caratteri alternativi vengono ignorati"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sono disponibili suggerimenti alternativi"</string>
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 9b7f18c..fc5fed3 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrazione tasti"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Suono tasti"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Popup sui tasti"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferenze"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Account e privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aspetto e layout"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Digitazione gestuale"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Correzione testo"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avanzate"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Attiva tastiera divisa"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronizzazione tastiera Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"La sicronizzazione è attiva"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronizza il tuo dizionario personale sui dispositivi"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizza ora"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Elimina dati cloud"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"I dati sincronizzati vengono eliminati da Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"I tuoi dati sincronizzati verranno eliminati dalla cloud. Vuoi procedere?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Elimina"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Annulla"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Il·tuo·dizionario personale verrà·sincronizzato sui server di Google e ne verrà effettuato il backup. Potrebbero essere raccolte informazioni·statistiche·relative alla frequenza delle·parole·per migliorare i·nostri·prodotti. La·raccolta·e l\'utilizzo di tutte le informazioni·saranno·conformi·alle·"<a href="https://www.google.com/policies/privacy">"Norme sulla privacy di Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Per attivare la funzione, aggiungi un account Google al dispositivo"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Altri metodi immissione"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Il tasto per cambiare lingua offre altri metodi di immissione"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tasto cambio lingua"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostra quando sono attive più lingue di immissione"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostra indicatore scorrimento"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Visualizza indicatore durante scorrimento da Maiusc o Simbolo"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ritardo eliminaz. popup tasto"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Nessun ritardo"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinito"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dizionario principale"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostra suggerimenti correzioni"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Visualizza le parole suggerite durante la digitazione"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostra sempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostra in modalità verticale"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Nascondi sempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blocca parole offensive"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Non suggerire parole potenzialmente offensive"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correzione automatica"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tasto input vocale"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nessun metodo di immissione vocale abilitato. Controlla le impostazioni Lingua e input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Invia feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Lingue"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Guida e feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Lingue"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tocca qui per salvare"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema della tastiera"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Cambia account"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nessun account selezionato"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Attualmente in uso: <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Annulla"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Esci"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Seleziona un account da utilizzare"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglese (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglese (USA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spagnolo (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbo (latino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglese (Regno Unito) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglese (Stati Uniti) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spagnolo (Stati Uniti) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbo (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradizionale)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cirillico)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latino)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compatto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nessuna lingua (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema della tastiera"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Stili personalizzati"</string>
     <string name="add_style" msgid="6163126614514489951">"Aggiungi stile"</string>
     <string name="add" msgid="8299699805688017798">"Aggiungi"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Attiva"</string>
     <string name="not_now" msgid="6172462888202790482">"Non ora"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Esiste già uno stile di inuput uguale: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ritardo pressione lunga tasti"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Durata vibraz. pressione tasto"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume audio a pressione tasto"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Leggi file dizionario esterno"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nessun file di dizionario nella cartella Download"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Seleziona un file di dizionario da installare"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vuoi davvero installare questo file per <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Si è verificato un errore"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ritardo pressione lunga tasti"</string>
     <string name="button_default" msgid="3988017840431881491">"Predefinito"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Benvenuto in <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"con la Digitazione gestuale"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Ora puoi digitare in tutte le tue app preferite con <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configura altre lingue"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Terminato"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostra icona app"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostra l\'icona dell\'app in Avvio applicazioni"</string>
     <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Servizio dizionario"</string>
diff --git a/java/res/values-iw/strings-emoji-descriptions.xml b/java/res/values-iw/strings-emoji-descriptions.xml
index 975ca10..fc4435a 100644
--- a/java/res/values-iw/strings-emoji-descriptions.xml
+++ b/java/res/values-iw/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"עוגייה"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"חפיסת שוקולד"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"סוכרייה"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"סוכרייה על מקל"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"רפרפת"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"סיר דבש"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"עוגת פירות"</string>
@@ -556,8 +556,8 @@
     <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"תיקיית קבצים פתוחה"</string>
     <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"דף עם גלילה מלמטה"</string>
     <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"דף פונה כלפי מעלה"</string>
-    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"לוח שנה"</string>
-    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"לוח שנה נתלש"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"יומן"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"יומן נתלש"</string>
     <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"כרטסת"</string>
     <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"תרשים עם מגמת עלייה"</string>
     <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"תרשים עם מגמת ירידה"</string>
@@ -590,7 +590,7 @@
     <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"מגש דואר יוצא"</string>
     <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"מגש דואר נכנס"</string>
     <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"חבילה"</string>
-    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"סמל דוא\"ל"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"סמל אימייל"</string>
     <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"מעטפה נכנסת"</string>
     <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"מעטפה ועליה חץ למטה"</string>
     <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"תיבת דואר סגורה עם דגל מורד"</string>
diff --git a/java/res/values-iw/strings-talkback-descriptions.xml b/java/res/values-iw/strings-talkback-descriptions.xml
index a43b64e..afadfbd 100644
--- a/java/res/values-iw/strings-talkback-descriptions.xml
+++ b/java/res/values-iw/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"לא הוזן טקסט"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> מתקן את <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ל-<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> מבצע תיקון אוטומטי"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"אין הצעה"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"תו לא מוכר"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"סמלים נוספים"</string>
@@ -57,7 +58,7 @@
     <string name="announce_keyboard_mode" msgid="6698257917367823205">"מציג מקלדת <xliff:g id="KEYBOARD_MODE">%s</xliff:g>"</string>
     <string name="keyboard_mode_date" msgid="6597407244976713364">"תאריך"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"תאריך ושעה"</string>
-    <string name="keyboard_mode_email" msgid="1239682082047693644">"דוא\"ל"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"אימייל"</string>
     <string name="keyboard_mode_im" msgid="3812086215529493501">"העברת הודעות"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"מספרים"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"מספרי טלפון"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"‏I גדולה, נקודה מעל"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"סמל לא מוכר"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"‏Emoji לא מוכר"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"פרצוף משועמם"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"פרצוף נבוך"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"פרצוף עם משקפי שמש"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"פרצוף מופתע"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"פרצוף מנשק"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"פרצוף זועף"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"תווים חלופיים זמינים"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"תווים חלופיים נדחים"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"הצעות חלופיות זמינות"</string>
diff --git a/java/res/values-iw/strings.xml b/java/res/values-iw/strings.xml
index d36d3ce..2acc08c 100644
--- a/java/res/values-iw/strings.xml
+++ b/java/res/values-iw/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"העדפות קלט"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"מראה"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"אפשרויות ריבוי שפות"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"העדפות של הקלדת החלקה"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"העדפות"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"חשבונות ופרטיות"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"מראה ופריסות"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"הקלדת החלקה"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"תיקון טקסט"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"מתקדם"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"עיצוב"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"הפעל מקלדת מפוצלת"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"‏סנכרון מקלדת Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"הסנכרון פועל"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"סנכרן את המילון האישי בין מכשירים"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"סנכרן עכשיו"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"מחק נתונים בענן"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"‏מוחק את הנתונים המסונכרנים שלך מ-Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"הנתונים המסונכרנים שלך יימחקו מהענן. האם אתה בטוח?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"מחק"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"בטל"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"‏המילון האישי שלך יסונכרן ויגובה בשרתי Google. ייתכן שהמידע הסטטיסטי לגבי תדירות מילים ייאסף כדי לעזור בשיפור המוצרים שלנו. איסוף המידע והשימוש בו יעשו בהתאם ל"<a href="https://www.google.com/policies/privacy">"מדיניות הפרטיות של Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"‏הוסף חשבון Google במכשיר הזה כדי להפעיל את התכונה הזו"</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">"מתג החלפת השפה מכסה גם שיטות קלט אחרות"</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">"הצג את סמן ההסטה"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"‏הצג סימון ויזואלי בעת הסטה מ-Shift או ממקשי סמלים"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"מקש קלט קולי"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"לא הופעלו שיטות של קלט קולי. בדוק את הגדרות השפה והקלט."</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="language_selection_title" msgid="3666971864764478269">"שפות"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"עזרה ומשוב"</string>
+    <string name="select_language" msgid="5709487854987078367">"שפות"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"גע שוב כדי לשמור"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"גע כאן כדי לשמור"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"עיצוב מקלדת"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"החלף חשבונות"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"לא נבחרו חשבונות"</string>
+    <string name="account_selected" msgid="2846876462199625974">"משתמש כרגע ב-<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"אישור"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"בטל"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"צא"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"בחר באיזה חשבון חשבון להשתמש"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"אנגלית (בריטניה)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"אנגלית (ארה\"ב)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ספרדית (ארצות הברית)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"אנגלית הודית"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"סרבית (באותיות לטיניות)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"אנגלית (בריטניה)‏ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"אנגלית (ארה\"ב) ‏(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ספרדית (ארה\"ב) ‏(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"אנגלית הודית (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"סרבית (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (מסורתית)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (קירילית)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (לטינית)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (קומפקטית)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ללא שפה (אלף-בית)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"‏אלף-בית (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"‏אלף-בית (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"‏אלף-בית (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"אמוג\'י"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"עיצוב מקלדת"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"לבן מלא"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"כחול מלא"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"שחור כהה"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"לבן בהיר"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"סגנונות קלט מותאמים אישית"</string>
     <string name="add_style" msgid="6163126614514489951">"הוסף סגנון"</string>
     <string name="add" msgid="8299699805688017798">"הוסף"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"האם אתה באמת רוצה להתקין את הקובץ הזה עבור <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"אירעה שגיאה"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"השהיית לחיצה ארוכה על מקש"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"כעת תוכל להקליד בכל האפליקציות המועדפות עליך באמצעות <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">"הצג את סמל האפליקציה במפעיל"</string>
     <string name="app_name" msgid="6320102637491234792">"ספק המילון"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ספק המילון"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"שירות מילון"</string>
diff --git a/java/res/values-ja/strings-emoji-descriptions.xml b/java/res/values-ja/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..2e674c8
--- /dev/null
+++ b/java/res/values-ja/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"コピーライトのマーク"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"登録商標のマーク"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"二重感嘆符"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"感嘆符疑問符"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"トレードマーク"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"情報ソース"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"左右の矢印"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"上下の矢印"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"左上の矢印"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"右上の矢印"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"右下の矢印"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"左下の矢印"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"左に戻る矢印"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"右に戻る矢印"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"腕時計"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"砂時計"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"黒い右向きの二重三角"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"黒い左向きの二重三角"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"黒い上向きの二重三角"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"黒い下向きの二重三角"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"目覚まし時計"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"使用中の砂時計"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"丸付きM"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"黒い極小四角"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"白い極小四角"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"黒い右向きの三角"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"黒い左向きの三角"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"白い中四角"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"黒い中四角"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"白い小四角"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"黒い小四角"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"黒い太陽と日光"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"雲"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"黒い電話"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"ONのチェックボックス"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"傘と雨だれ"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"温かい飲み物"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"白い上向き指差し"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"白い笑顔"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"牡羊座"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"牡牛座"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"双子座"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"蟹座"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"獅子座"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"乙女座"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"天秤座"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"蠍座"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"射手座"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"山羊座"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"水瓶座"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"魚座"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"黒いスペード"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"黒いクラブ"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"黒いハート"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"黒いダイヤ"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"温泉"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"黒いリサイクルのマーク"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"車椅子のマーク"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"アンカー"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"警告のマーク"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"高圧のマーク"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"白い中丸"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"黒い中丸"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"サッカーボール"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"野球ボール"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"雪だるまと雪"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"雲の後ろの太陽"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"へびつかい座"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"進入禁止"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"教会"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"噴水"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"ゴルフのホールと旗"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"ヨット"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"テント"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"ガソリンスタンド"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"黒いはさみ"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"白い太いチェックマーク"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"飛行機"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"封筒"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"グー"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"パー"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"チョキ"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"鉛筆"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"黒いペン先"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"太いチェックマーク"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"太い乗算記号"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"キラキラ"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"8点アスタリスク"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"黒い8稜星"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"雪マーク"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"スパークル"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"バツマーク"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"黒い囲み付きバツマーク"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"黒い装飾疑問符"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"白い装飾疑問符"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"白い装飾感嘆符"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"太い感嘆符"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"太い黒いハート"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"太いプラス記号"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"太いマイナス記号"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"太い除算記号"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"黒い右矢印"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"ループ"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"二重ループ"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"左から上向き矢印"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"左から下向き矢印"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"黒い左矢印"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"黒い上矢印"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"黒い下矢印"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"黒い大四角"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"白い大四角"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"白い中星"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"太い大きい丸"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"波ダッシュ"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"歌記号"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"丸付き祝"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"丸秘"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"麻雀牌の中"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"トランプの黒のジョーカー"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"血液型のA"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"血液型のB"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"血液型のO"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"駐車場"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"血液型のAB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"囲み付きCL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"囲み付きCOOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"囲み付きFREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"囲み付きID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"囲み付きNEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"囲み付きNG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"囲み付きOK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"囲み付きSOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"囲み付きUP!"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"囲み付きVS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"囲み付きココ"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"囲み付きサービス"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"囲み付き無料"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"囲み付き指定席"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"囲み付き禁止"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"囲み付き空き"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"囲み付き合格"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"囲み付き満車"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"囲み付き有料"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"囲み付き月極め"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"囲み付き申し込み"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"囲み付き割引"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"囲み付き営業中"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"丸付きお得"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"丸付き可能"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"台風"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"霧"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"閉じた傘"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"夜空と星"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"山の上の太陽"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"日の出"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"夕方の街並み"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"ビルの上の夕日"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"虹"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"夜の橋"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"波"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"火山"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"天の川"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"ヨーロッパとアフリカの地球"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"アメリカ大陸の地球"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"アジアとオーストラリアの地球"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"地球と子午線"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"新月の記号"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"満ちていく三日月の記号"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"上弦の半月の記号"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"凸月の記号"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"満月の記号"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"やや欠け月の記号"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"下弦の半月の記号"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"欠けていく三日月の記号"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"三日月"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"顔付き新月"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"顔付き上弦の月"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"顔付き下弦の月"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"顔付き満月"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"顔付き太陽"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"輝く星"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"流れ星"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"クリ"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"双葉"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"針葉樹"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"広葉樹"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"ヤシの木"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"サボテン"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"チューリップ"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"サクラ"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"バラ"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"ハイビスカス"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"ヒマワリ"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"花"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"トウモロコシ"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"稲穂"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"ハーブ"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"四つ葉のクローバー"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"モミジの葉"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"落ち葉"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"風に舞う葉"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"キノコ"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"トマト"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"ナス"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"ブドウ"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"メロン"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"スイカ"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"ミカン"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"レモン"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"バナナ"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"パイナップル"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"赤いリンゴ"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"青いリンゴ"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"洋ナシ"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"モモ"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"サクランボ"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"イチゴ"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ハンバーガー"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"ピザの一切れ"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"骨付き肉"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"チキンの足"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"おせんべい"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"おにぎり"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"ごはん"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"カレー"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"ラーメン"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"スパゲッティ"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"食パン"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"フライドポテト"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"やきいも"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"だんご"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"おでん"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"お寿司"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"エビフライ"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"なると"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"ソフトクリーム"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"かき氷"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"アイスクリーム"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ドーナツ"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"クッキー"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"板チョコ"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"キャンディ"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"ぺろぺろキャンディ"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"プリン"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ハチミツのポット"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ショートケーキ"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"お弁当"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"鍋物"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"料理"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ナイフとフォーク"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"湯のみ"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"お銚子とおちょこ"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"ワイングラス"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"カクテルグラス"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"トロピカルドリンク"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"ビールジョッキ"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"乾杯"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ほ乳瓶"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"リボン"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"プレゼントの包み"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"バースデーケーキ"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"ジャックランタン"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"クリスマスツリー"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"サンタクロース"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"花火"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"線香花火"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"風船"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"クラッカー"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"くす玉"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"七夕飾り"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"祝日のマーク"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"門松"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"お雛様"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"こいのぼり"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"風鈴"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"お月見"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"ランドセル"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"卒業式の角帽"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"メリーゴーランド"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"観覧車"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"ジェットコースター"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"釣り竿と魚"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"マイク"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"映画カメラ"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"映画"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"ヘッドフォン"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"パレット"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"シルクハット"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"サーカステント"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"チケット"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"カチンコ"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"演劇"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"ビデオゲーム"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"当選弓矢"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"スロットマシン"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"ビリヤード"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"サイコロ"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"ボウリング"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"花札"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"音符"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"複数の音符"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"サックス"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"ギター"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"鍵盤"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"トランペット"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"バイオリン"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"楽譜"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"ランニングシャツとタスキ"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"テニスのラケットとボール"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"スキーとスキー靴"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"バスケットボールとゴール"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"チェッカーフラグ"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"スノーボーダー"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"ランナー"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"サーファー"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"トロフィー"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"競馬"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"アメリカンフットボール"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"ラグビー"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"水泳"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"家"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"家と庭"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"オフィスビル"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"日本の郵便局"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"ヨーロッパの郵便局"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"病院"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"銀行"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ATM"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ホテル"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"ラブホテル"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"コンビニ"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"学校"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"デパート"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"工場"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"赤ちょうちん"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"日本の城"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"ヨーロッパの城"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"ネズミ"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"ハツカネズミ"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"雄ウシ"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"水牛"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"乳牛"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"ヒョウ"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"ウサギ"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"ネコ"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ドラゴン"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"ワニ"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"クジラ"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"カタツムリ"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"ヘビ"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"ウマ"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"雄ヒツジ"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"ヤギ"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"ヒツジ"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"サル"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"オンドリ"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"ニワトリ"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"イヌ"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"ブタ"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"イノシシ"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ゾウ"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"タコ"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"巻き貝"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"毛虫"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"アリ"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"ミツバチ"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"テントウムシ"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"魚"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"熱帯魚"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"フグ"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"カメ"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"孵化したヒヨコ"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"ヒヨコ"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"正面向きのヒヨコ"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"鳥"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"ペンギン"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"コアラ"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"プードル"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"ヒトコブラクダ"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"フタコブラクダ"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"イルカ"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"ネズミの顔"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"ウシの顔"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"トラの顔"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"ウサギの顔"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"ネコの顔"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ドラゴンの顔"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"クジラの潮吹き"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"ウマの顔"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"サルの顔"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"イヌの顔"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"ブタの顔"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"カエルの顔"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"ハムスターの顔"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"オオカミの顔"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"クマの顔"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"パンダの顔"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"ブタの鼻"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"イヌの足跡"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"目"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"耳"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"鼻"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"口"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"舌"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"上を指す白い手の甲"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"下を指す白い手の甲"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"左を指す白い手の甲"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"右を指す白い手の甲"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"ゲンコツのマーク"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"手をふるマーク"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"手でOKのマーク"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"サムズアップのマーク"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"サムズダウンのマーク"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"拍手のマーク"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"おっはーのマーク"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"王冠"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"女性の帽子"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"メガネ"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ネクタイ"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Tシャツ"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ジーンズ"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"ドレス"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"着物"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"ビキニ"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"婦人服"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"がま口"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ハンドバッグ"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"ポーチ"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"男性の靴"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"スニーカー"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ハイヒール"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"女性のサンダル"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"女性のブーツ"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"足跡"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"上半身の人影"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"複数の人影"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"男の子"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"女の子"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"男性"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"女性"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"家族"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"手をつなぐ男女"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"手をつなぐ男性同士"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"手をつなぐ女性同士"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"警官"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"バニーガール"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"ベールをかぶった花嫁"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"金髪の白人"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"中国人"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"インド人"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"おじいさん"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"おばあさん"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"赤ちゃん"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"工事現場の人"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"お姫様"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"なまはげ"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"天狗"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"お化け"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"エンゼル"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"宇宙人"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"エイリアン"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"悪魔"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"ドクロ"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"受付"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"衛兵"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"ダンサー"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"口紅"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"マニキュア"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"エステ"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"美容院"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"床屋の看板柱"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"注射器"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"薬"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"キスマーク"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"ラブレター"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"指輪"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"宝石"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"キス"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"花束"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"カップルとハート"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"結婚式"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"揺れるハート"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"ハートブレイク"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"2つのハート"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"光るハート"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"ドキドキしているハート"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"矢が刺さっているハート"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"青色のハート"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"緑色のハート"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"黄色のハート"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"紫色のハート"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"ハートとリボン"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"回転するハート"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"ハートの装飾"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"菱型の中に点"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"電球"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"怒っているマーク"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"爆弾"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"眠っているマーク"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"衝突のマーク"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"飛び散るアセのマーク"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"汗"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"ダッシュのマーク"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"うんち"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"力こぶ"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"クラクラのマーク"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"吹き出し"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"吹き出しコメント"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"白い花"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"100点のマーク"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"ドル袋"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"両替"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"太いドル記号"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"クレジットカード"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"円の紙幣"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ドルの紙幣"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ユーロの紙幣"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ポンドの紙幣"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"羽の生えた紙幣"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"上昇のグラフと円記号"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"座席"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"パソコン"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"書類カバン"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"MD"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"フロッピーディスク"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"CD"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"フォルダ"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"開いているフォルダ"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"カールした書類"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"正面向きの書類"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"カレンダー"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"日めくりカレンダー"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"カード索引"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"上昇のグラフ"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"下降のグラフ"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"棒グラフ"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"クリップボード"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"押しピン"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"丸い押しピン"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"クリップ"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"定規"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"三角定規"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"ページに付けたタブ"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"帳簿"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"ノート"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"きれいな表紙のノート"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"閉じた本"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"開いた本"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"緑色の本"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"青色の本"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"オレンジ色の本"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"複数の本"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"名札"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"スクロール"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"メモ"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"受話器"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"ポケベル"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"ファックス"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"パラボラアンテナ"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"拡声器"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"メガホン"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"送信トレイ"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"受信トレイ"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"段ボール"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"メールのマーク"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"メールの受信"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"メールの送信"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"送信のないメールボックス"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"送信するメールボックス"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"受信したメールボックス"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"受信のないメールボックス"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"郵便ポスト"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"郵便の角笛"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"新聞紙"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"携帯電話"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"左に右矢印が付いた携帯電話"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"マナーモード"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"携帯電話の電源をOFF"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"携帯電話の使用禁止"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"圏内のアンテナ"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"カメラ"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"ビデオカメラ"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"テレビ"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"ラジオ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"ビデオテープ"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"シャッフルを表す矢印"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"リピートを表す矢印"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"リプレイを表す矢印"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"再読み込みを表す矢印"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"逆再読み込みを表す矢印"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"弱い輝度のマーク"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"強い輝度のマーク"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"無音のスピーカー"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"スピーカー"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"小さい音量のスピーカー"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"大きい音量のスピーカー"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"電池"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"コンセント"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"左に傾いた虫めがね"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"右に傾いた虫めがね"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ロックとペン"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"閉じたロックと鍵"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"鍵"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"ロック"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"開いたロック"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"ベル"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"無音のベル"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"ブックマーク"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"リンクのマーク"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ラジオボタン"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"BACKの上に左矢印"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"ENDの上に左矢印"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ON!の上に左右の矢印"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"SOONの上に右矢印"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"TOPの上に上矢印"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18禁のマーク"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"キーキャップ10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"大文字の入力マーク"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"小文字の入力マーク"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"数字の入力マーク"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"記号の入力マーク"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"英字の入力マーク"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"炎"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"懐中電灯"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"レンチ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"ハンマー"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ボルトとナット"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"包丁"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"ピストル"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"顕微鏡"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"望遠鏡"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"水晶玉"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"六芒星"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"日本の初心者マーク"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"錨のエンブレム"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"黒い四角いボタン"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"白い四角いボタン"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"大きい赤い丸"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"大きい青い丸"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"大きいオレンジ色の菱型"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"大きい青色の菱型"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"小さいオレンジ色の菱型"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"小さい青色の菱型"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"上向きの赤い三角"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"下向きの赤い三角"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"上向きの小さい赤い三角"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"下向きの小さい赤い三角"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"1時の時計"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"2時の時計"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"3時の時計"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"4時の時計"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"5時の時計"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"6時の時計"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"7時の時計"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"8時の時計"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"9時の時計"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"10時の時計"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"11時の時計"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"12時の時計"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"1時半の時計"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"2時半の時計"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"3時半の時計"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"4時半の時計"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"5時半の時計"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"6時半の時計"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"7時半の時計"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"8時半の時計"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"9時半の時計"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"10時半の時計"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"11時半の時計"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"12時半の時計"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"富士山"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"東京タワー"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"自由の女神"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"日本のシルエット"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"モヤイ像"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"ニヤリとした顔"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"ニヤリとした笑顔"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"泣き笑いの顔"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"口を開けた笑顔"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"口と目が笑った顔"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"口を開けて冷や汗の笑顔"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"照れた笑顔"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"昇天の笑顔"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"角の生えた笑顔"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"ウインクした顔"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"ニコニコした笑顔"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"おいしい顔"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"ほっとした顔"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"目がハートの笑顔"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"サングラスをかけた笑顔"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"冷笑の顔"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"標準の顔"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"無表情の顔"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"横目の顔"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"冷や汗の顔"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"考えている顔"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"混乱した顔"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"悲しい顔"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"キスしている顔"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"投げキスの顔"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"キスしている笑顔"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"目を閉じてキスしている顔"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"ペロリと舌を出した顔"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"アッカンベーの顔"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"イーの顔"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"落胆した顔"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"不安な顔"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"怒った顔"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"ふくれっ面"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"泣き顔"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"がまんしている顔"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"勝ち誇った顔"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"ヤレヤレとした顔"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"ドキッっとした顔"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"苦悩に満ちた顔"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"青ざめた顔"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"うんざりした顔"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"あくびした顔"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"疲れた顔"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"しかめっ面"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"大泣きの顔"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"ポカーンとした顔"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"シーンとした顔"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"あせって冷や汗の顔"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"悲鳴をあげている顔"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"びっくりした顔"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"赤くなった顔"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"寝顔"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"クラクラしている顔"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"口のない顔"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"マスクした顔"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"ニヤリとした笑顔のネコ"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"泣き笑いのネコ"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"口を開けた笑顔のネコ"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"目がハートの笑顔のネコ"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"苦笑しているネコ"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"目を閉じてキスしている顔のネコ"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"ふくれっ面のネコ"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"泣き顔のネコ"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"うんざりした顔のネコ"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"NGのジェスチャーと顔"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OKのジェスチャーと顔"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"深くお辞儀している人"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"見ざる"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"聞かざる"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"言わざる"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"片手を上げてハッピーの人"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"万歳している人"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"しょんぼりしている人"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"ふくれっ面の人"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"手を合わせている人"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"ロケット"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ヘリコプター"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"蒸気機関車"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"電車"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"新幹線"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"旧型新幹線"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"列車"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"地下鉄"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"路面電車"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"駅"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"市内電車"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"市街電車"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"バス"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"対向のバス"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"トロリーバス"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"バス停"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"マイクロバス"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"救急車"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"消防車"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"パトカー"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"対向のパトカー"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"タクシー"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"対向のタクシー"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"車"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"対向車"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"RV車"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"トラック"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"トレーラー"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"トラクター"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"モノレール"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"山岳鉄道"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"空中鉄道"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"ケーブルカー"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ロープウェイ"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"船"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"ボート"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"競艇ボート"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"横型の信号機"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"縦型の信号機"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"工事中のマーク"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"パトカーのランプ"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"ポストの三角の旗"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"ドア"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"進入禁止のマーク"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"喫煙のマーク"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"禁煙のマーク"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"ゴミ箱のマーク"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"ポイ捨て禁止のマーク"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"飲料水のマーク"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"飲めない水のマーク"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"自転車"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"自転車乗り入れ禁止"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"自転車に乗る人"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"マウンテンバイクの人"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"歩行者"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"歩行禁止"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"学童横断路"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"男性のマーク"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"女性のマーク"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"公衆トイレ"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"赤ちゃんのマーク"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"トイレ"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"水洗トイレ"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"シャワー"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"お風呂"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"浴槽"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"入国手続き"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"税関"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"手荷物受取所"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"コインロッカー"</string>
+</resources>
diff --git a/java/res/values-ja/strings-talkback-descriptions.xml b/java/res/values-ja/strings-talkback-descriptions.xml
index e4f5db5..c884973 100644
--- a/java/res/values-ja/strings-talkback-descriptions.xml
+++ b/java/res/values-ja/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"テキストが入力されていません"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>は<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>を<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>に修正します"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g>で自動修正が実行されます"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"候補はありません"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"不明な文字"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"記号拡張"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"大文字I、上点"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"不明な記号"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"不明な絵文字"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"退屈そうな顔"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"恥ずかしそうな顔"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"サングラスをかけた顔"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"驚いた顔"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"キスしている顔"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"しかめっ面の顔"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"代替文字が利用可能です"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"代替文字が消去されます"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"代替候補が利用可能です"</string>
diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml
index 741dbb6..55305b8 100644
--- a/java/res/values-ja/strings.xml
+++ b/java/res/values-ja/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"キー操作バイブ"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"キー操作音"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"キー押下時ポップアップ"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"設定"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"アカウントとプライバシー"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"外観とレイアウト"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ジェスチャー入力"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"テキストの修正"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"詳細設定"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"テーマ"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"スプリットキーボードを有効にする"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Googleキーボードの同期"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"同期はON"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"端末間で単語リストを同期する"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"今すぐ同期"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"クラウドデータの削除"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Googleから同期データを削除します"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"クラウドから同期データを削除します。よろしいですか?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"削除"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"キャンセル"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"単語リストがGoogleのサーバーと同期され、サーバーにバックアップされます。Googleのサービス改善を目的として、語句の使用頻度に関する統計情報が収集される場合があります。収集した情報およびその利用方法は、"<a href="https://www.google.com/policies/privacy">"Googleプライバシーポリシー"</a>"に準拠します。"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"この機能を有効にするには端末にGoogleアカウントを追加してください"</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">"言語切り替えキーは他の入力方法にも対応しています"</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">"スライドインジケーターを表示"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shiftまたは記号キーからスライドするとビジュアルキューを表示します"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"音声入力キー"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"有効になっている音声入力方法がありません。[言語と入力]設定をご確認ください。"</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="language_selection_title" msgid="3666971864764478269">"言語"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ヘルプとフィードバック"</string>
+    <string name="select_language" msgid="5709487854987078367">"言語"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"保存するにはもう一度タップ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ここをタップして保存します"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"キーボードのテーマ"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"アカウントの切り替え"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"アカウントが選択されていません"</string>
+    <string name="account_selected" msgid="2846876462199625974">"現在 <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> を使用しています"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"キャンセル"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ログアウト"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"使用するアカウントの選択"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英語 (英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英語 (米国)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"スペイン語 (米国)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ヒングリッシュ"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"セルビア語(ラテン文字)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英語(英国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英語(米国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"スペイン語(米国)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ヒングリッシュ(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"セルビア語(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(伝統言語)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(キリル文字)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(ラテン文字)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(コンパクト)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"言語なし(アルファベット)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"アルファベット(QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"アルファベット(QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"アルファベット(Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"アルファベット(PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"絵文字"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"キーボードのテーマ"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"カスタム入力スタイル"</string>
     <string name="add_style" msgid="6163126614514489951">"スタイル追加"</string>
     <string name="add" msgid="8299699805688017798">"追加"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"この<xliff:g id="LANGUAGE_NAME">%s</xliff:g>のファイルをインストールしますか?"</string>
-    <string name="error" msgid="8940763624668513648">"エラーが発生しました"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"キーの長押し時間"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"これで、お気に入りのすべてのアプリで<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">"ランチャーにアプリアイコンを表示します"</string>
     <string name="app_name" msgid="6320102637491234792">"辞書提供元"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"辞書提供元"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"辞書"</string>
diff --git a/java/res/values-ka-rGE/strings-talkback-descriptions.xml b/java/res/values-ka-rGE/strings-talkback-descriptions.xml
index 5d23b09..fa250db 100644
--- a/java/res/values-ka-rGE/strings-talkback-descriptions.xml
+++ b/java/res/values-ka-rGE/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"ტექსტი შეყვანილი არ არის"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> შეასწორებს <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-ს <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>-ად"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ასრულებს ავტოკორექციას"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"შემოთავაზება არ არის"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"უცნობი სიმბოლო"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"დამატებითი სიმბოლოები"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"უცნობი სიმბოლო"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"უცნობი emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"შეწუხებული სახე"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"შერცხვენილი სახე"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"სახე მზის სათვალით"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"გაოცებული სახე"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"კოცნის სახე"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"წარბშეჭმუხნილი სახე"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ალტერნატიული სიმბოლოები ხელმისაწვდომია"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ალტერნატიული სიმბოლოები გამოტოვებულია"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ალტერნატიული შეთავაზებები ხელმისაწვდომია"</string>
diff --git a/java/res/values-ka-rGE/strings.xml b/java/res/values-ka-rGE/strings.xml
index 17e6b7e..451eb39 100644
--- a/java/res/values-ka-rGE/strings.xml
+++ b/java/res/values-ka-rGE/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"შეყვანის პარამეტრები"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"იერსახე"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"მრავალენობრივი ვარიანტები"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"ჟესტით შეყვ. პარამეტრები"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"პარამეტრები"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"ანგარიშები &amp; კონფიდენციალურობა"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"იერსახე &amp; განლაგებები"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ჟესტებით წერა"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"ტექსტის კორექცია"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"გაფართოებული"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"თემა"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"გაყოფილი კლავიატურის გააქტიურება"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google კლავიატურის სინქრონიზება"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"სინქრონიზება ჩართულია"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"აწარმოეთ თქვენი პერს. ლექსიკონის სინქ. მოწყობილობების მასშტაბით"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ახლა სინქრონიზაცია"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ღრუბლის მონაცემების წაშლა"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"წაშლის Google-თან თქვენს სინქრონიზებულს მონაცემებს"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"თქვენი სინქ. მონაც. წაიშლება ღრუბ. სივრციდან. დარწმუნებული ხართ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"წაშლა"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"გაუქმება"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"თქვენი პერსონალური ლექსიკონი სინქრონიზდება და შეინახება სარეზერვოდ Google სერვერებზე. ჩვენი პროდუქტების გასაუმჯობესებლად, შეიძლება შეგროვდეს სტატისტიკური ინფორმაცია სიტყვების სიხშირის შესახებ. ნებისმიერი ინფორმაციის შეგროვება და გამოყენება "<a href="https://www.google.com/policies/privacy">"Google-ის კონფიდენციალურობის პოლიტიკასთან"</a>" შესაბამისობაში იქნება."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ფუნქციის ჩასართავად, გთხოვთ მოწყობილობას Google ანგარიში დაამატოთ"</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">"ენის გადართვის ღილაკს შეყვანის სხვა მეთოდებსაც შეიცავს"</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">"გასრიალების ინდიკატ. ჩვენება"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"ხმოვანი შეყვანის კლავიში"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ხმოვანი შეყვანის მეთოდები ჩართული არ არის. შეამოწმეთ ენის &amp; შეყვანის პარამეტრები."</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="language_selection_title" msgid="3666971864764478269">"ენები"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"დახმარება და უკუკავშირი"</string>
+    <string name="select_language" msgid="5709487854987078367">"ენები"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"შეეხეთ ისევ შესანახად"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"აქ შეეხეთ, რომ შეინახოს"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ხელმისაწვდომია ლექსიკონი"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"კლავიატურის თემა"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ანგარიშების გადართვა"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ანგარიშები არჩეული არ არის"</string>
+    <string name="account_selected" msgid="2846876462199625974">"ამჟამად გამოიყენება <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"კარგი"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"გაუქმება"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"გამოსვლა"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"აირჩიეთ გამოსაყენებელი ანგარიში"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ინგლისური (გართ. სამ.)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ინგლისური (აშშ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ესპანური (აშშ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ჰინგლისური"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"სერბული (ლათინური)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ინგლისური (გაერთ.სამ.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ინგლისური (აშშ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ესპანური (აშშ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ჰინგლისური (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"სერბული (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ტრადიციული)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (კირილიცა)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ლათინური)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (კომპაქტური)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ენის გარეშე (ანბანი)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ანბანი (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ანბანი (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ანბანი (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"სიცილაკები"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"კლავიატურის თემა"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"ჰოლო-თეთრი"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"ჰოლო-ლურჯი"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"მუქი მასალა"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"ღია მასალა"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"შეყვანის სტილების კონფიგურაცია"</string>
     <string name="add_style" msgid="6163126614514489951">"სტილის დამატება"</string>
     <string name="add" msgid="8299699805688017798">"დამატება"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"ნამდვილად გსურთ ამ ფაილის <xliff:g id="LANGUAGE_NAME">%s</xliff:g>-ისთვის ინსტალაცია?"</string>
-    <string name="error" msgid="8940763624668513648">"წარმოიშვა შეცდომა"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"კლავიშზე გრძელი დაჭერის დაყოვნება"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ამიერიდან შეძლებთ ყველა სასურველ აპში <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">"გაშვების ხატულის ჩვენება გამშვებში"</string>
     <string name="app_name" msgid="6320102637491234792">"ლექსიკონის პროვაიდერი"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ლექსიკონის პროვაიდერი"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"ლექსიკონის სერვისი"</string>
diff --git a/java/res/values-kk-rKZ/strings-action-keys.xml b/java/res/values-kk-rKZ/strings-action-keys.xml
index 0214423..1183117 100644
--- a/java/res/values-kk-rKZ/strings-action-keys.xml
+++ b/java/res/values-kk-rKZ/strings-action-keys.xml
@@ -20,19 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for label_go_key (4033615332628671065) -->
-    <skip />
-    <!-- no translation found for label_next_key (5586407279258592635) -->
-    <skip />
-    <!-- no translation found for label_previous_key (1421141755779895275) -->
-    <skip />
-    <!-- no translation found for label_done_key (7564866296502630852) -->
-    <skip />
-    <!-- no translation found for label_send_key (482252074224462163) -->
-    <skip />
+    <string name="label_go_key" msgid="4033615332628671065">"Өту"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"Келесі"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"Алдыңғы"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Дайын"</string>
+    <string name="label_send_key" msgid="482252074224462163">"Жіберу"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Іздеу"</string>
-    <!-- no translation found for label_pause_key (2225922926459730642) -->
-    <skip />
-    <!-- no translation found for label_wait_key (5891247853595466039) -->
-    <skip />
+    <string name="label_pause_key" msgid="2225922926459730642">"Кідірту"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"Күту"</string>
 </resources>
diff --git a/java/res/values-kk-rKZ/strings-config-important-notice.xml b/java/res/values-kk-rKZ/strings-config-important-notice.xml
new file mode 100644
index 0000000..9bb8dc3
--- /dev/null
+++ b/java/res/values-kk-rKZ/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"Ұсыныстарды жақсарту үшін хабарлардан және терілген деректерден үйрену"</string>
+</resources>
diff --git a/java/res/values-kk-rKZ/strings-emoji-descriptions.xml b/java/res/values-kk-rKZ/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..87c5556
--- /dev/null
+++ b/java/res/values-kk-rKZ/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Авторлық құқық белгісі"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Тіркелген белгі"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Қос леп белгісі"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Леп белгісі мен сұрақ белгісі"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Сауда белгісі"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Ақпарат көзі"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Сол оң көрсеткісі"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Жоғары төмен көрсеткісі"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Солтүстік батыс көрсеткісі"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Солтүстік шығыс көрсеткісі"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Оңтүстік шығыс көрсеткісі"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Оңтүстік батыс көрсеткісі"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Ілгегі бар солға көрсеткісі"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Ілгегі бар оңға көрсеткісі"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Сағат"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Құм сағат"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Қара, оңға бағытталған қос үшбұрыш"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Қара, солға бағытталған қос үшбұрыш"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Қара, жоғары бағытталған қос үшбұрыш"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Қара, төмен бағытталған қос үшбұрыш"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Оятқыш"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Құм ағып жатқан құм сағат"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"m дөңгелек латын бас әрпі"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Қара, шағын шаршы"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Ақ, шағын шаршы"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Қара, оңға бағытталған үшбұрыш"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Қара солға бағытталған үшбұрыш"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Ақ, орташа шаршы"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Қара, орташа шаршы"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Ақ, орташа, шағын шаршы"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Қара, орташа, шағын шаршы"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Сәулелері бар қара күн"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Бұлт"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Қара телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Құсбелгісі бар дауыс беру шаршысы"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Жаңбыр тамшылары бар қолшатыр"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Ыстық сусын"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Ақ, жоғары бағытталған сұқ саусақ"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Ақ, күлімсіреген бет"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Тоқты"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Торпақ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Егіздер"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Шаян"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Арыстан"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Бикеш"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Таразы"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Сарышаян"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Қауыс"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Таутеке"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Суқұйғыш"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Балықтар"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Қара қарға түсі"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Қара шыбын түсі"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Қара түйе табан түсі"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Қара қиық түсі"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Ыстық бастаулар"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Қара әмбебап қайта өңдеу таңбасы"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Инвалидтік кресло таңбасы"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Зәкір"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Ескерту белгісі"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Жоғары кернеу белгісі"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Орташа, ақ шеңбер"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Орташа, қара шеңбер"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Футбол добы"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бейсбол"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Қарсыз аққала"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Бұлт артындағы күн"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Жылан алып жүруші"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Жазба жоқ"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Шіркеу"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Бұрқақ"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Тесіктегі жалау"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Желкенді кеме"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Шатыр"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Отын сорабы"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Қара қайшы"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Ақ, қалың құсбелгі"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Ұшақ"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Хатқалта"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Көтерілген жұдырық"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Көтерілген қол"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Жеңіс қолы"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Қарындаш"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Қара қауырсын"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Қалың құсбелгі"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Қалың көбейту x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Ұшқындар"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Сегіз бұрыштық жұлдыз"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Сегіз бұрыштық қара жұлдыз"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Қар ұшқыны"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Ұшқын"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Сызу белгісі"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Негатив шаршыдағы сызу белгісі"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Қара сұрақ белгісі өрнегі"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ақ сұрақ белгісі өрнегі"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ақ леп белгісі өрнегі"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Қалың леп белгісі таңбасы"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Қатты қара жүрек"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Қалың қосу белгісі"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Қалың алу белгісі"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Қалың бөлу белгісі"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Қара оңға көрсеткісі"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Ілмек"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Қос ілмек"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Оңға бағытталған, содан кейін жоғары қарай қиғаштаған көрсеткі"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Оңға бағытталған, содан кейін төмен қарай қиғашталған көрсеткі"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Солға қара көрсеткісі"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Жоғары қара көрсеткісі"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Төменге қара көрсеткісі"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Қара, үлкен шаршы"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Ақ, үлкен шаршы"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Ақ, орташа жұлдыз"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Қалың, үлкен шеңбер"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Толқынды сызық"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Бөліктің өзгеруі белгісі"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Құттықтау дөңгелек идеограммасы"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Шеңбердегі құпия идеограммасы"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Маджонг плиткасы: қызыл айдаһар"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Ойын картасы: қара джокер"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Қан түрі: A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Қан түрі: B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Қан түрі: O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Тұрақ орны"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Қан түрі: AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Шаршыдағы CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Шаршыдағы «cool»"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Шаршыдағы «free»"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Шаршыдағы ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Шаршыдағы «new»"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Шаршыдағы «N G»"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Шаршыдағы «OK»"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Шаршыдағы «SOS»"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Шаршыдағы «Up» және леп белгісі"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Шаршыдағы «vs»"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Осы жерде шаршыдағы катакана"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Шаршыдағы катакана қызметі"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Шаршыдағы тегін идеограммасы"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Шаршыдағы кейінге сақталған идеограммасы"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Шаршыдағы тыйым салу идеограммасы"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Шаршыдағы вакансия идеограммасы"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Шаршыдағы қабылдау идеограммасы"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Шаршыдағы толық айналысу идеограммасы"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Шаршыдағы төленген идеограммасы"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Шаршыдағы ай сайын идеограммасы"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Шаршыдағы қолданба идеограммасы"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Шаршыдағы жеңілдік идеограммасы"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Шаршыдағы бос емес идеограммасы"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Артықшылық дөңгелек идеограммасы"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Қабылдау дөңгелек идеограммасы"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Тұманды"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Жабық қолшатыр"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Жұлдызды түн"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Таулардың үстінде күн шығуы"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Күн шығуы"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Ымырт жабылған кездегі қала пейзажы"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Ғимараттар үстіндегі күннің батуы"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Кемпірқосақ"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Түндегі көпір"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Су толқыны"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Құс жолы"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Жер шары: Еуропа-Африка"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Жер шары: Америка континенттері"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Жер шары: Азия-Австралия"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Меридиандар бар жер шары"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Жаңа ай таңбасы"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Толып жатқан жарты ай таңбасы"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Бірінші ширек ай таңбасы"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Толып жатқан дөңес ай таңбасы"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Толық ай таңбасы"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Кішірейіп жатқан дөңес ай таңбасы"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Соңғы ширек ай таңбасы"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Кішірейіп жатқан жарты ай таңбасы"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Жарты ай"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Беті бар жаңа ай"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Беті бар бірінші ширек айы"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Беті бар соңғы ширек айы"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Беті бар толық ай"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Беті бар күн"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Жарық жұлдыз"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Метеор"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Каштан"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Көшет"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Мәңгі жасыл ағаш"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Жапырақты ағаш"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Пальма"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Қызғалдақ"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Шиенің гүлдеуі"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Раушан"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Гибискус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Күнбағыс"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Гүлдеу"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Жүгері собығы"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Күріш масағы"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Шөп"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Төрт жапырақты жоңышқа"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Үйеңкі жапырағы"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Түскен жапырақ"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Желде шайқалған жапырақ"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Саңырауқұлақ"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Қызанақ"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Баялды"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Жүзім"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Қауын"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Қарбыз"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Танжерин"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банан"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Қызыл алма"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Жасыл алма"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Алмұрт"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Шабдалы"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Шиелер"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Құлпынай"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Гамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Пицца тілімі"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Сүйектегі ет"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Құс аяғы"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Күріш крекері"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Күріш шаригі"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Әзірленген күріш"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Карри және күріш"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Бумен әзірлеу ыдысы"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Спагетти"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Нан"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Француз картобы"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Қуырылған жаңа картоп"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Одэн"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Қуырылған асшаян"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Шырмауық дизайны бар балық торты"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Жұмсақ балмұздақ"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Мұз жоңқасы"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Балмұздақ"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Майға пісірілген бүйрекше бәліш"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Печенье"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Шоколад плиткасы"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Кәмпит"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Мұз кәмпит"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Пісірілген крем"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Бал қыш құмырасы"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Жеміс салындысы бар қаттама торт"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Тамақ қорабы"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Тамақ қыш құмырасы"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Әзірлеу"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Шанышқы мен пышақ"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Тұтқасыз шай шыныаяғы"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Саке бөтелкесі мен шыныаяғы"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Шарап стаканы"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Коктейль стаканы"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропикалық сусын"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Сыра саптыаяғы"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Соқтықтырылған сыра саптыаяқтары"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Нәресте бөтелкесі"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Таспа"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Оралған сыйлық"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Туған күн торты"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Джектің майшамы"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Рождестволық шырша"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Аяз ата"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Отшашулар"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Бенгал оты"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Әуе шары"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Шартылдақ"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Конфетти шары"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Танабата ағашы"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Айқас жалаулар"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Қарағай әшекейі"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Жапондық қуыршақтар"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Тұқы түріндегі желді көрсеткіш"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Жел қоңырауы"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Айды көру салтанаты"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Мектеп сөмкесі"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Оқу бітіру қалпағы"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Әткеншек аты"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Шолу дөңгелегі"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Американдық төбешіктер"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Қармақ және балық"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Бейнекамера"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кинотеатр"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Құлақаспап"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Суретшінің палитрасы"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Цилиндр"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Цирк шатыры"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Билет"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Шартылдағы бар нумератор"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Орындау өнер түрлері"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Бейне ойын"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Тікелей тию"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Ойын автоматы"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Бильярд"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Ойын кубигі"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Боулинг"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Гүл ойын карталары"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музыкалық нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Бірнеше музыкалық нота"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гитар"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Музыкалық пернетақта"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Керней"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Скрипка"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Партитура"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Лентасы бар жүгіру майкасы"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Теннис ракеткасы және кішкене доп"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Шаңғы және шаңғы бәтеңкесі"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскетбол және себет"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Торлы жалау"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордист"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Жүгіруші"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Серфер"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Жүлде"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Ат жарысы"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Американдық футбол"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Регби футболы"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Жүзуші"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Үй соғу"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Бағы бар үй"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Кеңсе соғу"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Жапондық пошта"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Еуропалық пошта"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Аурухана"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банк"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Қонақ үй"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Махаббат қонақ үйі"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Шағын супермаркет"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Мектеп"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Әмбебап дүкен"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Зауыт"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Изакайя шамы"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Жапондық сарай"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Еуропалық сарай"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Егеуқұйрық"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Тышқан"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Өгіз"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Азиялық енеке"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Сиыр"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Қоян"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Мысық"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Айдаһар"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Қолтырауын"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Ұлу"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Жылан"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Жылқы"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Қой"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Ешкі"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Қой"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Маймыл"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Қораз"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Тауық"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Ит"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Шошқа"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Аю"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Піл"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Сегізаяқ"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Шиыршық тәрізді бақалшық"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Жәндік"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Құмырсқа"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Ара"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Қызыл қоңыз"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Балық"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропикалық балық"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Ине қарынды балық"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Тасбақа"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Жұмыртқаны жарып шыққан балапан"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Балапан"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Алға қарап тұрған балапан"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Құс"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудель"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Жалғыз өркешті түйме"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Қос өркешті түйе"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Дельфин"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Тышқанның тұмсығы"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Сиырдың тұмсығы"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Тигрдің тұмсығы"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Қоянның тұмсығы"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Мысықтың беті"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Айдаһардың тұмсығы"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Су шашыратып жатқан кит"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Жылқының тұмсығы"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Маймылдың тұмсығы"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Иттің беті"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Шошқаның тұмсығы"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Бақаның тұмсығы"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Аламанның беті"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Қасқырдың тұмсығы"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Аюдың тұмсығы"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Панданың тұмсығы"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Шошқаның танауы"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Табан іздері"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Көздер"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Құлақ"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Мұрын"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ауыз"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Тіл"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Ақ жоғарыға бағытталған қолдың сыртқы жағындағы сұқ саусақ"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Ақ төменге бағытталған қолдың сыртқы жағындағы сұқ саусақ"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Ақ сол жаққа бағытталған алақанның сырт жағындағы сұқ саусақ"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Ақ оң жаққа бағытталған алақанның сырт жағындағы сұқ саусақ"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Жұдырық белгісі"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Қол бұлғау белгісі"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Жарайды белгісі"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Басбармақ жоғары белгісі"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Басбармақ төмен белгісі"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Шапалақтау белгісі"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Ашық қолдар белгісі"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Корона"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Әйелдер қалпағы"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Көзілдірік"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Галстук"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Футболка"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Джинсы"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Көйлек"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Әйелдердің киімдері"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Әмиян"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Қол сөмкесі"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Әмиян"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Еркектер туфлиі"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Спорт аяқ киімі"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Өкшесі биік туфли"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Әйелдер сандалы"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Әйелдер бәтеңкесі"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Іздер"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Мүсіннің силуэты"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Бюсттердің силуэты"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Бала"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Қыз"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Еркек"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Әйел"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Отбасы"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Қолдарын ұстасып тұрған әйел мен еркек"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Қолдарын ұстасып тұрған екі еркек"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Қолдарын ұстасып тұрған екі әйел"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полиция офицері"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Қоян құлақтары бар әйел"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Бетпердесі бар қалыңдық"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Сары шашты адам"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Гуа пи мао киген адам"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Сәлдесі бар еркек"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Кәрі еркек"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Кәрі әйел"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Нәресте"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Құрылыс жұмысшысы"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцесса"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Жапондық огр"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Жапондық гоблин"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Елес"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Нәресте періште"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Басқа планеталық"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Басқа планеталық құбыжық"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Сайтанның баласы"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Бассүйек"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Анықтама беретін орын қызметкері"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Гвардияшы"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Биші"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Далап"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Тырнаққа арналған лак"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Бетті уқалау"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Шаш үлгісі"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Шиыршық ақ-қызыл бояуы бар баған"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Домалақ дәрі"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Сүю белгісі"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Махаббат хаты"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Сақина"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Асыл тас"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Сүю"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Жүрек бар жұп"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Үйлену"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Соғып тұрған жүрек"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Жарылған жүрек"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Екі жүрек"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Жарқыраған жүрек"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Өсіп жатқан жүрек"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Оқ бар жүрек"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Көк жүрек"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Жасыл жүрек"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Сары жүрек"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Күлгін жүрек"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Лентасы бар жүрек"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Айналып жатқан жүректер"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Жүрек әшекейі"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Ішінде нүкте бар бриллиант пішіні"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Электр шам"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Ашу таңбасы"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Ұйықтау таңбасы"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Соқтығысу таңбасы"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Шашыраған тер таңбасы"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Кішкентай тамшы"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Сызықша таңбасы"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Нәжіс"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Ширатылған бицепстер"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Бас айналу таңбасы"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Сөз шеңбері"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Ой шеңбері"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Ақ гүл"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Жүз нүкте таңбасы"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Ақша толған сөмке"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Валюта айырбастау"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Ауыр доллар белгісі"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Несие картасы"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Йена белгісі бар банкнота"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Доллар белгісі бар банкнот"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Еуро белгісі бар банкнота"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Фунт белгісі бар банкнота"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Сақиналар бар ақша"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Жоғары қарай тренді және йена белгісі бар диаграмма"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Орындық"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Жеке компьютер"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Портфель"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Шағын диск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптикалық диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Тіркеу қалтасы"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ашық тіркеу қалтасы"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Оралған шеті бар бет"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Жоғары қарап тұрған бет"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Күнтізбе"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Жыртпалы күнтізбе"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Картотека"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Жоғары қарай тренді бар диаграмма"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Төмен қарай тренді бар диаграмма"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Гистограмма"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Буфер"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Канцеляриялық бүркеншікті шеге"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Дөңгелек бүркеншікті шеге"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Қағаз қыстырғыш"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Түзу сызғыш"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Үшбұрыштық сызғыш"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Бетбелгілер"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Бас кітап"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Жазу кітапшасы"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Безендірілген мұқабасы бар жазу кітапшасы"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Жабық кітап"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Ашық кітап"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Жасыл кітап"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Көк кітап"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Сарғылт кітап"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Кітаптар"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Ат бейджигі"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Айналдыру"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Жаднама"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефон қабылдағышы"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пейджер"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Жерсерік антеннасы"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Дыбыстандыру және күшейту жүйесінің дыбыс зорайтқышы"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Рухтандыру мегафоны"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Шығыс науасы"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Кіріс науасы"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Бума"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Электрондық пошта таңбасы"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Кіріс хатқалта"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Үстінде төменге көрсеткісі бар хатқалта"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Төмен түсірілген жалаушасы бар жабық пошта жәшігі"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Көтерілген жалауша бар жабық пошта жәшігі"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Көтерілген жалаушасы бар ашық пошта жәшігі"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Төмен түсірілген жалаушасы бар ашық пошта жәшігі"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Пошта жәшігі"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Пошталық мүйіз"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Газет"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобильдік телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Сол жағында оңға көрсеткісі бар мобильдік телефон"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Діріл режимі"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Мобильдік телефон өшірулі"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Мобильдік телефондар жоқ"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Жолақтары бар антенна"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Бейнекамера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Теледидар"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Бейнетаспа"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Оңға бұралған көрсеткілер"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Сағат тілімен оңға және солға ашық дөңгелек көрсеткілер"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Дөңгелек бір қабаттасу бар сағат тілімен оңға және солға ашық дөңгелек көрсеткілер"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Сағат тілімен төменге және оңға ашық дөңгелек көрсеткілер"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Сағат тіліне кері төмен және жоғары қарай ашық дөңгелек көрсеткілер"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Төмен жарықтық таңбасы"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Жоғары жарықтық таңбасы"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Дыбысты өшіру сызығы бар динамик"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Динамик"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Бір дыбыстық толқыны бар динамик"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Үш дыбыстық толқыны бар динамик"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батарея"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Аша"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Солға бағытталған үлкейту әйнегі"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Оңға бағытталған үлкейту әйнегі"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Сиялы қаламсап бар құлып"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Кілт бар жабық құлып"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Кілт"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Құлып"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Ашық құлып"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Қоңырау"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Дыбысты өшіру сызығы бар қоңырау"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Бетбелгі"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Түйін таңбасы"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Айырып-қосқыш"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Үстінде солға көрсеткісі бар «Back»"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Үстінде солға көрсеткісі бар «End»"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Үстінде солға оңға көрсеткісі бар леп белгісі бар қосулы «On»"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Үстінде оңға көрсеткісі бар «Soon»"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Үстінде жоғары көрсеткісі бар «Top»"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Он сегіз жастан төмен емес таңбасы"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Он пернесі"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Латын бас әріптері үшін енгізу таңбасы"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Латын кіші әріптері үшін енгізу таңбасы"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Сандар үшін енгізу таңбасы"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Таңбалар үшін енгізу таңбасы"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Латын әріптері үшін енгізу таңбасы"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Өрт"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Қалта шам"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Гайка кілті"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Балға"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Гайка мен болт"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Пышақ"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пистолет"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Кристалл шар"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Ортасында нүкте бар алты бұрышты жұлдыз"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Бастаушы жапондық таңбасы"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Үш ашалы айыр эмблемасы"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Қара шаршы түймесі"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Ақ шаршы түймесі"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Үлкен қызыл шеңбер"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Үлкен көк шеңбер"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Үлкен сарғылт бриллиант"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Үлкен көк бриллиант"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Шағын сарғылт бриллиант"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Шағын көк бриллиант"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Жоғары бағытталған қызыл үшбұрыш"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Төмен қарап тұрған қызыл үшбұрыш"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Жоғары бағытталған шағын қызыл үшбұрыш"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Төмен бағытталған шағын қызыл үшбұрыш"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Циферблат: бір сағат"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Циферблат: екі сағат"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Циферблат: үш сағат"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Циферблат: төрт сағат"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Циферблат: бес сағат"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Циферблат: алты сағат"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Циферблат: жеті сағат"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Циферблат: сегіз сағат"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Циферблат: тоғыз сағат"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Циферблат: он сағат"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Циферблат: он бір сағат"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Циферблат: он екі сағат"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Циферблат: бір жарым"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Циферблат: екі жарым"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Циферблат: үш жарым"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Циферблат: төрт жарым"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Циферблат: бес жарым"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Циферблат: алты жарым"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Циферблат: жеті жарым"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Циферблат: сегіз жарым"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Циферблат: тоғыз жарым"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Циферблат: он жарым"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Циферблат: он бір жарым"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Циферблат: он екі жарым"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Фудзи тауы"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токио мұнарасы"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Еркіндік статуясы"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Жапондықтың силуэты"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Моаи"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Ыржиып күліп тұрған бет"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Күлімсіреген көздері бар ыржиып күліп тұрған бет"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Қуаныштан жас шыққан бет"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Аузы ашық күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Аузы ашық және көздері күлімсіреп тұрған күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Аузы ашық және салқын тері бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Аузы ашық және көздері қатты жұмылған күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Галосы бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Мүйіздері бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Жымиған бет"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Күлімсіреп тұрған көздері бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Тәтті тамақтан ләззат алып жатқан бет"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Жеңілдік сезінген бет"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Жүрек пішінді көздері бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Көзілдірік бар күлімсіреген бет"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Миығынан күлген бет"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Бейтарап бет"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Эмоциясыз бет"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Таң қалмаған бет"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Салқын тер бар бет"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Мұңды бет"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Абдыраған бет"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Қысылған бет"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Сүю беті"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Сүю жіберген бет"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Күлімсіреп тұрған көздері бар сүю беті"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Көздері жабық сүю беті"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Тілі шығып тұрған бет"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Тілі шығып тұрған және жымиған көзі бар бет"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Тілі шығып тұрған және қатты жабылған көздері бар бет"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Көңілі қалған бет"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Алаңдаған бет"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Ашулы бет"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Ернін бұлтитқан бет"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Жылап жатқан бет"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Табанды бет"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Триумфтық қарас бар бет"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Көңілі қалған, бірақ жеңілдік сезінген бет"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Аузы ашық, қабағын түйген бет"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Қайғылы бет"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Қорыққан бет"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Қажыған бет"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Ұйқылы бет"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Шаршаған бет"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Бет-аузын қисайтқан бет"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Қатты жылап жатқан бет"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Аузы ашық бет"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Жекіргендегі бет"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Аузы ашық және салқын тер бар бет"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Қорқыныштан айқайлаған бет"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Таң қалған бет"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Қызарған бет"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Ұйықтап жатқан бет"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Басы айналған бет"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Аузы жоқ бет"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Медициналық маска бар бет"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Күлімсіреген көздері бар ыржиып күліп тұрған мысық беті"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Қуаныштан шыққан жас бар мысық беті"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Аузы ашық, күлімсіреген мысық беті"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Жүрек пішінді көздері бар күлімсіреген мысық беті"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Қыжырта өтірік күлімсіреген мысық беті"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Көздері жабық, сүйіп жатқан мысық беті"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Ернін бұлтитқан мысық беті"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Жылап жатқан мысық беті"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Қажыған мысық беті"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Жақсы емес қимылы бар бет"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Жарайды қимылы бар бет"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Қатты иілген адам"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Жаманды көріп тұрмаған маймыл"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Жаманды естімейтін маймыл"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Жаман сөйлемейтін маймыл"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Бір қолын көтерген бақытты адам"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Қуанғаннан екі қолын көтерген адам"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Қабағын түйген адам"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Ернін бұлтитқан беті бар адам"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Қолдарын жинаған адам"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Тікұшақ"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Бумен жүретін локомотив"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Вагон"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Жылдамдығы жоғары пойыз"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Оқ тұмсығы бар жылдамдығы жоғары пойыз"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Пойыз"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Монорельс"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станция"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвай"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Трамвай вагоны"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Келе жатқан автобус"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Троллейбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобус аялдамасы"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Микроавтобус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Жедел жәрдем көлігі"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Өрт сөндіру машинасы"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полиция көлігі"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Келе жатқан полиция көлігі"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Келе жатқан такси"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автокөлік"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Келе жатқан автокөлік"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Тұрғын көлік"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Жеткізу жүк көлігі"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Автопойыз"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Монорельс"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Тау пойыз жолы"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Аспалы темір жолы"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Таудағы арқан жолы"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Аспалы арқан жол"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Кеме"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Қайық"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Жылдам жүретін катер"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Көлденең бағдаршам"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Тік бағдаршам"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Құрылыс белгісі"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Полиция көліктерінің айналатын шамы"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Бағандағы үшбұрыштық жалау"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Есік"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Кірмеу белгісі"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Темекі шегу белгісі"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Темекі шекпеу белгісі"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Қоқысты орнына лақтырыңыз таңбасы"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Қоқыс лақтырмаңыз таңбасы"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Ауыз су таңбасы"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ауыз су емес таңбасы"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Велосипедтерге тыйым салынған"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Велосипедші"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Тау велосипедшісі"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Жолаушы"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Жолаушыларға тыйым салынған"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Балалар өтіп жатыр"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Еркектер таңбасы"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Әйелдер таңбасы"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Демалу бөлмесі"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Нәресте таңбасы"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Дәретхана"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Әжетхана"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Душ"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Ванна"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Ванна"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Паспортты бақылау"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Кеден"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Бағажды беру"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Қалдырылған багаж"</string>
+</resources>
diff --git a/java/res/values-kk-rKZ/strings-talkback-descriptions.xml b/java/res/values-kk-rKZ/strings-talkback-descriptions.xml
index 2d61bde..106d3c5 100644
--- a/java/res/values-kk-rKZ/strings-talkback-descriptions.xml
+++ b/java/res/values-kk-rKZ/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"Дауыстап айтылған құпия сөз пернелерін есту үшін гарнитураны қосыңыз."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"Ағымдағы мәтін – %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"Мәтін енгізілмеген"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> дегенді <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> деп түзетеді"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> автоматты түрде түзетуді орындайды"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ұсыныс жоқ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Белгісіз таңба"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Қосымша таңбалар"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shift"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Таңбалар"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shift"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"Жою"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Таңбалар"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Әріптер"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Сандар"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Параметрлер"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Tab"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Бос орын"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Дауыспен енгізу"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Эмодзи"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Қайтару"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Іздеу"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Нүкте"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Тілді ауыстыру"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Келесі"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Алдыңғы"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Shift қосылған"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"Caps lock қосылған"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Таңбалар режимі"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"Қосымша таңбалар режимі"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Әріптер режимі"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Телефон режимі"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Телефон таңбалары режимі"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Пернетақта жасырылды"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"<xliff:g id="KEYBOARD_MODE">%s</xliff:g> пернетақтасы көрсетілген"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"күн"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"күн мен уақыт"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"электрондық пошта"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"хабар алмасу"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"сан"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"телефон"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"мәтін"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"уақыт"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Жақындағылар"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Адамдар"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Заттар"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Табиғат"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Орындар"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Таңбалар"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Эмотикондар"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"Бас <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"Бас I"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Үстінде нүктесі бар бас I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Белгісіз таңба"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Белгісіз эмодзи"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Зеріккен бет"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Қысылған бет"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Көзілдірік киген бет"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Таңданған бет"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Сүю беті"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Қабағын түйген бет"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Баламалы таңбалар қол жетімді"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Баламалы таңбалар еленбейді"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Баламалы ұсыныстар қол жетімді"</string>
diff --git a/java/res/values-kk-rKZ/strings.xml b/java/res/values-kk-rKZ/strings.xml
index 24c99b3..99d9cf7 100644
--- a/java/res/values-kk-rKZ/strings.xml
+++ b/java/res/values-kk-rKZ/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Пернені басқан кездегі діріл"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Пернені басу кезіндегі дыбыс"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Пернені басқан кездегі ашылмалы мәзір"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Қалауларыңыз"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Есептік жазбалар және құпиялық"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Сыртқы түр және орналасулар"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Қимыл арқылы теру"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Мәтінді түзету"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Кеңейтілген"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тақырып"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Бөлінген пернетақтаны қосу"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google пернетақтасын синхрондау"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхрондау қосылды"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Жеке сөздікті құрылғылар арасында синхрондау"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Қазір синхрондау"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Бұлтты деректерді жою"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Синхрондалған деректерді Google жүйесінен жояды"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Синхрондалған деректер бұлттан жойылады. Сіз сенімдісіз бе?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Жою"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Бас тарту"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Жеке сөздігіңіз синхрондалады және Google серверлеріне сақтық көшірмесі жасалады. Сөз жиілігінің статистикалық ақпараты өнімдерімізді жақсарту үшін жинақталуы мүмкін. Барлық ақпаратты жинау және пайдалану "<a href="https://www.google.com/policies/privacy">" Google құпиялылық саясатына "</a>"сәйкес орындалады."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Мүмкіндікті қосу үшін құрылғыға Google есептік жазбасын қосыңыз"</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">"Тілді ауыстыру пернесі басқа енгізу әдістерін де қамтиды"</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">"Жылжыту индикаторын көрсету"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shift немесе Таңба пернелерінен жылжыту кезіндегі көрнекі сөзкөмекті көрсету"</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>
@@ -51,8 +56,7 @@
     <string name="settings_system_default" msgid="6268225104743331821">"Жүйе әдепкісі"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Контакт аттарын ұсыну"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Ұсыныстар мен түзетулер үшін контакт аттарын пайдалану"</string>
-    <!-- no translation found for use_personalized_dicts (5167396352105467626) -->
-    <skip />
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"Жекелендірілген ұсыныстар"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> жақсарту"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"Қос бос орын кезеңі"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"Бос орынға екі рет түрту бос орыннан кейінгі кезеңді енгізеді"</string>
@@ -63,9 +67,6 @@
     <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>
@@ -81,35 +82,37 @@
     <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>
-    <!-- no translation found for gesture_space_aware (2078291600664682496) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware_summary (4371385818348528538) -->
-    <skip />
+    <string name="gesture_space_aware" msgid="2078291600664682496">"Фраза қимылы"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Бос орын пернесіне сырғыту арқылы қимылдар барысында бос орындарды енгізу"</string>
     <string name="voice_input" msgid="3583258583521397548">"Дауыстық енгізу пернесі"</string>
-    <!-- no translation found for voice_input_disabled_summary (8141750303464726129) -->
-    <skip />
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Дауыспен енгізу әдістері қосылмаған. «Тіл және енгізу параметрлері» тармағын тексеріңіз."</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="language_selection_title" msgid="3666971864764478269">"Тілдер"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Анықтама және кері байланыс"</string>
+    <string name="select_language" msgid="5709487854987078367">"Тілдер"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Сақтау үшін қайта түртіңіз"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Сақтау үшін осы жерді түртіңіз"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Сөздік қолжетімді"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Пернетақта тақырыбы"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Есептік жазбаларды ауыстыру"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Есептік жазбалар таңдалмаған"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Қазіргі уақытта <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> пайдаланылуда"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Жарайды"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Бас тарту"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Шығу"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Пайдаланатын есептік жазбаны таңдау"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ағылшын (ҰБ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ағылшын (АҚШ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испан (АҚШ)"</string>
-    <!-- no translation found for subtype_with_layout_en_GB (1931018968641592304) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_US (8809311287529805422) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_es_US (510930471167541338) -->
-    <skip />
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <skip />
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Серб (латын жазуы)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ағылшын (Құрама Корольдік) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ағылшын (АҚШ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испан (АҚШ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Серб (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (дәстүрлі)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (шағын)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Тіл жоқ (әліпби)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Әліпби (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Әліпби (QWERTZ)"</string>
@@ -117,18 +120,8 @@
     <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Әліпби (Dvorak)"</string>
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Әліпби (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Әліпби (ДК)"</string>
-    <!-- no translation found for subtype_emoji (7483586578074549196) -->
-    <skip />
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="subtype_emoji" msgid="7483586578074549196">"Эмодзи"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"Пернетақта тақырыбы"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Реттелетін енгізу стильдері"</string>
     <string name="add_style" msgid="6163126614514489951">"Стиль қосу"</string>
     <string name="add" msgid="8299699805688017798">"Қосу"</string>
@@ -140,15 +133,9 @@
     <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_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>
-    <!-- no translation found for read_external_dictionary_confirm_install_message (4782116251651288054) -->
-    <skip />
-    <string name="error" msgid="8940763624668513648">"Қате болды"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Пернені ұзақ басу кідірісі"</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>
@@ -166,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Қазір барлық таңдаулы қолданбаларда <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">"Іске қосу құралындағы қолданба белгішесін көрсету"</string>
     <string name="app_name" msgid="6320102637491234792">"Сөздік провайдері"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Сөздік провайдері"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Сөздік қызметі"</string>
@@ -186,24 +171,19 @@
     <string name="check_for_updates_now" msgid="8087688440916388581">"Жаңарту"</string>
     <string name="last_update" msgid="730467549913588780">"Соңғы жаңартылған"</string>
     <string name="message_updating" msgid="4457761393932375219">"Жаңартуларды тексеру"</string>
-    <!-- no translation found for message_loading (5638680861387748936) -->
-    <skip />
+    <string name="message_loading" msgid="5638680861387748936">"Жүктеу…"</string>
     <string name="main_dict_description" msgid="3072821352793492143">"Негізгі сөздік"</string>
     <string name="cancel" msgid="6830980399865683324">"Болдырмау"</string>
-    <!-- no translation found for go_to_settings (3876892339342569259) -->
-    <skip />
+    <string name="go_to_settings" msgid="3876892339342569259">"Параметрлер"</string>
     <string name="install_dict" msgid="180852772562189365">"Орнату"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"Болдырмау"</string>
     <string name="delete_dict" msgid="756853268088330054">"Жою"</string>
-    <!-- no translation found for should_download_over_metered_prompt (1583881200688185508) -->
-    <skip />
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Мобильдік құрылғыда таңдалған тіл үшін сөздік қол жетімді.&lt;br/&gt; Теру тәжірибесін жақсарту үшін <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> сөздігін &lt;b&gt;жүктеу&lt;/b&gt; ұсынылады.&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>
-    <!-- no translation found for dict_available_notification_title (4583842811218581658) -->
-    <skip />
+    <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> үшін сөздік қол жетімді"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"Қарап шығу және жүктеп алу үшін басу"</string>
-    <!-- no translation found for toast_downloading_suggestions (6128155879830851739) -->
-    <skip />
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"<xliff:g id="LANGUAGE_NAME">%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>
diff --git a/java/res/values-km-rKH/strings-emoji-descriptions.xml b/java/res/values-km-rKH/strings-emoji-descriptions.xml
index 757df50..e9b8780 100644
--- a/java/res/values-km-rKH/strings-emoji-descriptions.xml
+++ b/java/res/values-km-rKH/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"ខូគី"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"​​សូកូឡា"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"ស្ករគ្រាប់"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"ស្ករ​គ្រាប់​មាន​ដង​​កាន់"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"សង់ខ្យា"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ថូ"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"នំ​ខេក"</string>
diff --git a/java/res/values-km-rKH/strings-talkback-descriptions.xml b/java/res/values-km-rKH/strings-talkback-descriptions.xml
index e5b7860..5e99209 100644
--- a/java/res/values-km-rKH/strings-talkback-descriptions.xml
+++ b/java/res/values-km-rKH/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"គ្មាន​អត្ថបទ​​​បាន​បញ្ចូល"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> កែ <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ទៅ​ជា <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> អនុវត្ត​ការ​កែ​ស្វ័យ​ប្រវត្តិ"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"គ្មានការផ្តល់យោបល់ទេ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"មិន​ស្គាល់​តួអក្សរ"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"និមិត្ត​សញ្ញា​​ច្រើន​ទៀត"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"សញ្ញា İ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"មិន​ស្គាល់​និមិត្តសញ្ញា"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"មិន​ស្គាល់​សញ្ញា​អារម្មណ៍"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"មុខ​អផ្សុក"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"មុខ​ខ្មាស​​អៀន"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"ពាក់​វ៉ែនតា​"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"មុខ​ភ្ញាក់ផ្អើល"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"មុខ​ថើប"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"មុខ​ចង​ចិញ្ចើម"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"តួអក្សរ​ជំនួស​អាច​ប្រើ​បាន"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"បាន​បដិសេធ​តួអក្សរ​ជំនួស"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ការ​ស្នើ​ជំនួស​អាច​ប្រើ​បាន"</string>
diff --git a/java/res/values-km-rKH/strings.xml b/java/res/values-km-rKH/strings.xml
index 1c64583..26ca12d 100644
--- a/java/res/values-km-rKH/strings.xml
+++ b/java/res/values-km-rKH/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"ចំណូលចិត្ត​បញ្ចូល"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"រូបរាង"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"ជម្រើស​ភាសា​​ច្រើន"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"ចំណូលចិត្តបញ្ចូលកាយវិការ"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ចំណូលចិត្ត"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"គណនី &amp;amp ភាពឯកជន"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"រូបរាង &amp;amp ប្លង់"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"កាយវិការ​បញ្ចូល"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"ការ​កែ​​អត្ថបទ"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"កម្រិត​ខ្ពស់"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"រូបរាង"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"បើក​ការ​បំបែក​ក្ដារចុច"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"សមកាលកម្មលើក្តារចុច Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"សមកាលម្មត្រូវបានបើក"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ធ្វើសមកាលកម្មបញ្ជីឯកសារផ្ទាល់ខ្លួនឆ្លងឧបករណ៍"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ធ្វើសម្មកាលកម្មឥឡូវនេះ"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"លុបទិន្នន័យក្លោត"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"លុបទិន្នន័យដែលបានធ្វើសមកាលកម្មរបស់អ្នកចេញពី Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ទិន្នន័យធ្វើសមកាលកម្មរបស់អ្នកនឹងត្រូវបានលុបពីពពក។ តើអ្នកប្រាកដទេ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"លុប"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"បោះបង់"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"បញ្ជីឯកសារផ្ទាល់ខ្លួនរបស់អ្នកនឹងត្រូវបានធ្វើសមកាលកម្ម និងបម្រុងទុកនៅក្នុងម៉ាស៊ីនមេ Google។ ព័ត៌មានស្ថិតិនៃចំនួនពាក្យដែលឧស្សាហ៍ប្រើអាចត្រូវបានប្រមូលដើម្បីធ្វើឲ្យផលិតផលរបស់ពួកយើងប្រសើរជាងមុន។ ការប្រមូល និងការប្រើប្រាស់ព័ត៌មាន នឹងត្រូវអនុលោមតាម "<a href="https://www.google.com/policies/privacy">"គោលការណ៍ភាពឯកជនរបស់ Google"</a>"។"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"សូមបន្ថែមគណនី Google ទៅឧបករណ៍នេះដើម្បីបើកដំណើរការលក្ខណៈពិសេសនេះ"</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">"គ្រាប់ចុច​ប្ដូរ​ភាសា​តាម​វិធីសាស្ត្រ​បញ្ចូល​ផ្សេងទៀត"</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">"បង្ហាញ​ទ្រនិច​បង្ហាញ​ស្លាយ"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"បង្ហាញ​​សញ្ញា​មើល​​ឃើញ​ខណៈ​ពេល​ដែល​រុញ​ពី​ឆ្វេង ឬ​​គ្រាប់​ចុច​​និមិត្ត​សញ្ញា"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"គ្រាប់​ចុច​បញ្ចូល​​សំឡេង"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"គ្មាន​វិធីសាស្ត្រ​បញ្ចូល​សំឡេង​បាន​បើក។ ពិនិត្យ​មើល​ការ​កំណត់​ភាសា &amp; ការ​បញ្ចូល។"</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="language_selection_title" msgid="3666971864764478269">"ភាសា"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ជំនួយ &amp; មតិ​ត្រឡប់"</string>
+    <string name="select_language" msgid="5709487854987078367">"ភាសា"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ប៉ះ​ម្ដង​ទៀត​ ដើម្បី​រក្សា​ទុក"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ប៉ះ​ទីនេះ​ដើម្បី​រក្សាទុក"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"មាន​វចនានុក្រម"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"រូបរាង​ក្ដារចុច"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ប្ដូរ​គណនី"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"មិន​បាន​ជ្រើស​គណនី"</string>
+    <string name="account_selected" msgid="2846876462199625974">"កំពុង​ប្រើ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"យល់ព្រម"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"បោះបង់"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ចេញ"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"ជ្រើស​គណនី​ដើម្បី​ប្រើ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"អង់គ្លេស (​អង់គ្លេស)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"អង់គ្លេស (សហរដ្ឋ​អាមេរិក)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"អេស្ប៉ាញ (សហរដ្ឋ​អាមេរិក​)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"សើប (ឡាតាំង​)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"អង់គ្លេស (ចក្រភព​អង់គ្លេស) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"អង់គ្លេស (អាមេរិក) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"អេស្ប៉ាញ (អាមេរិក) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"សើប (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (អក្សរ​ពេញ)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ស៊ីរី)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ឡាតាំង)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (បង្រួម)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"គ្មាន​ភាសា (អក្សរ​ក្រម)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"តាម​លំដាប់​អក្សរក្រម (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"តាម​លំដាប់​អក្សរក្រម (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"តាម​លំដាប់​អក្សរក្រម (កុំព្យូទ័រ)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"សញ្ញា​អារម្មណ៍"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"រូបរាង​ក្ដារចុច"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"ស​ផ្លេកៗ​"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"ខៀវ​ខ្ចី"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"ងងឹត"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"ភ្លឺ"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"រចនាប័ទ្ម​បញ្ចូល​ផ្ទាល់ខ្លួន"</string>
     <string name="add_style" msgid="6163126614514489951">"បន្ថែម​រចនាប័ទ្ម"</string>
     <string name="add" msgid="8299699805688017798">"បន្ថែម"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"ពិត​ជា​ដំឡើង​ឯកសារ​នេះ​សម្រាប់ <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"មាន​កំហុស"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ពន្យារពេល​​​ចុច​គ្រាប់​ចុច​ឲ្យ​​យូរ"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ឥឡូវ​​អ្នក​អាច​​វាយ​បញ្ចូល​នៅ​ក្នុង​​កម្មវិធី​​ពេញ​ចិត្ត​របស់​អ្នក​ទាំងអស់​ជាមួយ <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">"បង្ហាញ​រូប​តំណាង​កម្មវិធី​នៅ​ក្នុង​កម្ម​​វិធី​ចាប់ផ្ដើម"</string>
     <string name="app_name" msgid="6320102637491234792">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"កម្មវិធី​ផ្ដល់​វចនានុក្រម"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"សេវាកម្ម​​វចនានុក្រម"</string>
diff --git a/java/res/values-kn-rIN/strings-emoji-descriptions.xml b/java/res/values-kn-rIN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..a013c27
--- /dev/null
+++ b/java/res/values-kn-rIN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"ಹಕ್ಕುಸ್ವಾಮ್ಯದ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"ನೋಂದಾವಣಿ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"ಎರಡು ಆಶ್ಚರ್ಯಕರ ಚಿಹ್ನೆಗಳು"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"ಆಶ್ಚರ್ಯಸೂಚಕ ಪ್ರಶ್ನೆ ಗುರುತು"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"ಟ್ರೇಡ್‌ಮಾರ್ಕ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"ಮಾಹಿತಿ ಮೂಲ"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"ಎಡ ಬಲ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"ಮೇಲೆ ಕೆಳಗೆ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"ವಾಯುವ್ಯ ದಿಕ್ಕಿನ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"ಈಶಾನ್ಯ ದಿಕ್ಕಿನ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"ಅಗ್ನೇಯ ದಿಕ್ಕಿನ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"ನೈಋತ್ಯ ದಿಕ್ಕಿನ ಬಾಣದ ಗುರುತು"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"ಕೊಕ್ಕೆ ಆಕಾರದ ಎಡ ದಿಕ್ಕಿನ ಬಾಣ"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"ಕೊಕ್ಕೆ ಆಕಾರದ ಬಲ ದಿಕ್ಕಿನ ಬಾಣ"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"ವಾಚ್"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"ಹವರ್‌ಗ್ಲಾಸ್"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"ಬಲಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ದ್ವಿ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"ಎಡಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ದ್ವಿ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"ಮೇಲಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ದ್ವಿ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"ಕೆಳಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ದ್ವಿ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"ಆಲಾರಾಂ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"ಸುರಿಯುತ್ತಿರುವ ಮರಳಿನ ಹವರ್‌ಗ್ಲಾಸ್"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"ವೃತ್ತದೊಳಗಿನ ಲ್ಯಾಟೀನ್ ದೊಡ್ಡಕ್ಷರ ಎಮ್"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"ಕಪ್ಪು ಬಣ್ಣದ ಸಣ್ಣ ಚೌಕ"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"ಬಿಳಿ ಬಣ್ಣದ ಸಣ್ಣ ಚೌಕ"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"ಬಲಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"ಎಡಕ್ಕೆ ಸೂಚಿಸುವ ಕಪ್ಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"ಬಿಳಿ ಬಣ್ಣದ ಮಧ್ಯಮ ಚೌಕ"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"ಕಪ್ಪು ಬಣ್ಣದ ಮಧ್ಯಮ ಚೌಕ"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"ಬಿಳಿ ಬಣ್ಣದ ಮಧ್ಯಮ ಆಕಾರದ ಸಣ್ಣ ಚೌಕ"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"ಕಪ್ಪು ಬಣ್ಣದ ಮಧ್ಯಮ ಆಕಾರದ ಸಣ್ಣ ಚೌಕ"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"ಕಪ್ಪು ಕಿರಣಗಳ ಸೂರ್ಯ"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"ಮೇಘ"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"ಕಪ್ಪು ಟೆಲಿಫೋನ್"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"ಟಿಕ್ ಗುರುತಿನ ಬ್ಯಾಲೆಟ್ ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"ಮಳೆ ಹನಿಗಳೊಂದಿಗೆ ಕೊಡೆ"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"ಬಿಸಿ ಪಾನೀಯ"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"ಮೇಲ್ಮುಖ ಸೂಚನೆ"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"ಬಿಳಿ ಬಣ್ಣದ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"ಮೇಷ ರಾಶಿ"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"ವೃಷಭ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"ಮಿಥುನ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"ಕರ್ಕಾಟಕ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"ಸಿಂಹ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"ಕನ್ಯಾ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"ತುಲಾ ರಾಶಿ"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"ಕಟಕ ರಾಶಿ"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"ಧನು ರಾಶಿ"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"ಮಕರ ರಾಶಿ"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"ಕುಂಭ ರಾಶಿ"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"ಮೀನ ರಾಶಿ"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"ಬ್ಲ್ಯಾಕ್ ಸ್ಪೇಡ್ ಸ್ಯೂಟ್"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"ಬ್ಲ್ಯಾಕ್ ಕ್ಲಬ್ ಸ್ಯೂಟ್"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"ಬ್ಲ್ಯಾಕ್ ಹಾರ್ಟ್ ಸ್ಯೂಟ್"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"ಬ್ಲ್ಯಾಕ್ ಡೈಮಂಡ್ ಸ್ಯೂಟ್"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"ಹಾಟ್ ಸ್ಪ್ರಿಂಗ್ಸ್"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"ಕಪ್ಪು ಬಣ್ಣದ ಸಾರ್ವಜನಿಕ ಮರುಬಳಕೆಯ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"ವೀಲ್‌ಚೇರ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"ಆಂಕರ್"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"ಎಚ್ಚರಿಕೆ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"ಹೈ ವೋಲ್ಟೇಜ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"ಮಧ್ಯಮ ಬಿಳಿ ಬಣ್ಣದ ವೃತ್ತ"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"ಮಧ್ಯಮ ಕಪ್ಪು ಬಣ್ಣದ ವೃತ್ತ"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"ಸಾಕರ್ ಬಾಲ್"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"ಬೇಸ್‌ಬಾಲ್"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"ಹಿಮವಿಲ್ಲದ ಸ್ನೋಮ್ಯಾನ್"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"ಮೋಡದ ಮರೆಯಲ್ಲಿ ಸೂರ್ಯ"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ಆಪ್ಯೂಕಸ್"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"ಪ್ರವೇಶವಿಲ್ಲ"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"ಚರ್ಚ್"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"ಕಾರಂಜಿ"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"ಕುಳಿಯಲ್ಲಿ ಧ್ವಜ"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"ಹಾಯಿದೋಣಿ"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"ಟೆಂಟ್"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"ಇಂಧನ ಪಂಪ್"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"ಕಪ್ಪು ಕತ್ತರಿ"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"ಗಾಢ ಬಿಳಿ ಬಣ್ಣದ ಟಿಕ್ ಗುರುತು"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"ಏರ್‌ಪ್ಲೇನ್"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"ಎನ್ವಲಪ್"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"ಎತ್ತಿಹಿಡಿದ ಬಿಗಿಮುಷ್ಟಿ"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"ಮೇಲೆತ್ತಿದ ಕೈ"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"ವಿಜಯದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"ಪೆನ್ಸಿಲ್‌"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"ಕಪ್ಪು ಮುಳ್ಳು"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"ಗಾಢವಾದ ಟಿಕ್ ಗುರುತು"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"ಗಾಢ ಬಣ್ಣದ ಗುಣಾಕಾರ x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"ಬೆಳಕುಗಳು"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"ಎಂಟು ಗೆರೆಗಳುಳ್ಳ ನಕ್ಷತ್ರ"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"ಎಂಟು ಬಿಂದುಗಳುಳ್ಳ ಕಪ್ಪು ನಕ್ಷತ್ರ"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"ಸ್ನೋಫ್ಲೇಕ್"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"ಸ್ಪಾರ್ಕಲ್"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"ಅಡ್ಡ ಗುರುತು"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"ನಕಾರಾತ್ಮಕ ಚೌಕಾಕೃತ ಅಡ್ಡ ಗುರುತು"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"ಕಪ್ಪು ಬಣ್ಣದ ಪ್ರಶ್ನೆ ಗುರುತು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"ಬಿಳಿ ಬಣ್ಣದ ಪ್ರಶ್ನೆ ಗುರುತು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"ಬಿಳಿ ಬಣ್ಣದ ಆಶ್ಚರ್ಯಸೂಚಕ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"ಗಾಢ ಬಣ್ಣದ ಆಶ್ಚರ್ಯಸೂಚಕ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"ಗಾಢ ಕಪ್ಪಗಿನ ಹೃದಯದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"ಗಾಢ ಬಣ್ಣದ ಸಂಕಲನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"ಗಾಢ ಬಣ್ಣದ ವ್ಯವಕಲನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"ಗಾಢ ಬಣ್ಣದ ಭಾಗಾಕಾರ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"ಕಪ್ಪು ಬಣ್ಣದ ಎಡದಿಕ್ಕಿನ ಬಾಣ"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"ಸುರುಳಿ ಕುಣಿಕೆ"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"ಎರಡು ಸುರುಳಿ ಕುಣಿಕೆ"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"ಬಲಕ್ಕೆ ಸೂಚಿಸುತ್ತಾ ಮೇಲಕ್ಕೆ ಬಾಗುವ ಬಾಣ"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"ಬಲಕ್ಕೆ ಸೂಚಿಸುತ್ತಾ ಕೆಳಮುಖವಾಗಿ ಬಾಗಿರುವ ಬಾಣ"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"ಬಲದಿಕ್ಕಿನ ಕಪ್ಪು ಬಣ್ಣದ ಬಾಣ"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"ಮೇಲ್ಮುಖವಾದ ಕಪ್ಪು ಬಣ್ಣದ ಬಾಣ"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"ಕೆಳಮುಖವಾದ ಕಪ್ಪು ಬಣ್ಣದ ಬಾಣ"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"ಕಪ್ಪು ಬಣ್ಣದ ದೊಡ್ಡ ಚೌಕ"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"ಬಿಳಿ ಬಣ್ಣದ ದೊಡ್ಡ ಚೌಕ"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"ಬಿಳಿ ಬಣ್ಣದ ಮಧ್ಯಮ ಚೌಕ"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"ದೊಡ್ಡ ಗಾತ್ರದ ವೃತ್ತ"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"ವೇವಿ ಡ್ಯಾಶ್"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"ಭಾಗ ಪರ್ಯಾಯ ಗುರುತು"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"ವೃತ್ತಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ಅಭಿನಂದನೆ"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"ವೃತ್ತಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ರಹಸ್ಯ"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"ಮಹ್ಜಾಂಗ್ ಟೈಲ್ ಕೆಂಪು ಡ್ರ್ಯಾಗನ್"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"ಪ್ಲೇಯಿಂಗ್ ಕಾರ್ಡ್ ಬ್ಲ್ಯಾಕ್ ಜೋಕರ್"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"ರಕ್ತದ ಗುಂಪು A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"ರಕ್ತದ ಗುಂಪು B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"ರಕ್ತದ ಗುಂಪು O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"ವಾಹನ ನಿಲುಗಡೆ ಸ್ಥಳ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"ರಕ್ತದ ಗುಂಪು AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"ಚೌಕಾಕಾರದ CL ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"ಚೌಕಾಕಾರದ ಕೂಲ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"ಚೌಕಾಕಾರದ ಉಚಿತ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ಚೌಕಾಕಾರದ ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"ಚೌಕಾಕಾರದ ಹೊಸ"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"ಚೌಕಾಕಾರದ N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"ಚೌಕಾಕಾರದ ಸರಿ"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"ಚೌಕಾಕಾರದ SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"ಆಶ್ಚರ್ಯಕರ ಚಿಹ್ನೆಯಿಂದ ಚೌಕಾಕೃತ"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"ಚೌಕಾಕಾರದ ವಿರುದ್ಧ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"ಚೌಕಾಕಾರದ ಕಟಕಾನಾ ಇಲ್ಲಿ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"ಚೌಕಾಕಾರದ ಕಟಕಾನಾ ಸೇವಾ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"ಚೌಕಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ಚಾರ್ಜ್-ಮುಕ್ತ"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಕಾಯ್ದಿರಿಸಿದ-ಆಸನ"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ನಿಷೇಧ"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಖಾಲಿಹುದ್ದೆ"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಸಮ್ಮತಿ"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಸಂಪೂರ್ಣ ಆಕ್ಯುಪೆನ್ಸಿ"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"ಚೌಕಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ಪಾವತಿ"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಮಾಸಿಕ"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ಅಪ್ಲಿಕೇಶನ್"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"ಚೌಕಾಕೃತ ಈಡಿಯೋಗ್ರಾಫ್ ರಿಯಾಯಿತಿ"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"ಚೌಕಾಕೃತ ವ್ಯಾಪಾರದ ಈಡಿಯೋಗ್ರಾಫ್"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"ವೃತ್ತಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ಪ್ರಯೋಜನ"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"ವೃತ್ತಾಕಾರದ ಈಡಿಯೋಗ್ರಾಫ್ ಸಮ್ಮತಿ"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"ಸೈಕ್ಲೋನ್"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"ಮಸುಕು"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"ಮುಚ್ಚಿದ ಛತ್ರಿ"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"ನಕ್ಷತ್ರಗಳಿಂದ ತುಂಬಿದ ರಾತ್ರಿ"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"ಪರ್ವತಗಳ ತಪ್ಪಲಿನಲ್ಲಿ ಸೂರ್ಯೋದಯ"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"ಸೂರ್ಯೋದಯ"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"ಮುಸ್ಸಂಜೆಯ ನಗರವೈಭವ"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"ಕಟ್ಟಡಗಳ ನಡುವೆ ಸೂರ್ಯಾಸ್ತ"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"ಕಾಮನಬಿಲ್ಲು"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"ರಾತ್ರಿಯಲ್ಲಿ ಸೇತುವೆ ನೋಟ"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"ನೀರಿನ ಅಲೆಗಳು"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"ಅಗ್ನಿಪರ್ವತ"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"ಕ್ಷೀರಪಥ"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"ಅರ್ಥ್ ಗ್ಲೋಬ್ ಯೂರೋಪ್-ಆಫ್ರಿಕಾ"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"ಅರ್ಥ್ ಗ್ಲೋಬ್ ಅಮೆರಿಕಾಸ್"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"ಅರ್ಥ್ ಗ್ಲೋಬ್ ಎಷ್ಯಾ-ಆಸ್ಟ್ರೇಲಿಯಾ"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"ಮೆರಿಡಿಯನ್‌ಗಳಿಂದ ಕೂಡಿದ ಗ್ಲೋಬ್"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"ಹುಣ್ಣಿಮೆಯ ಚಂದ್ರ"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"ಅರ್ಧಚಂದ್ರದ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"ಮೊದಲ ಭಾಗದ ಚಂದ್ರನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"ಮುಂದಕ್ಕೆ ಉಬ್ಬಿದ ಚಂದ್ರನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"ಪೂರ್ಣ ಚಂದ್ರ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"ಕ್ಷೀಣಿಸುವ ಚಂದ್ರನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"ಕೊನೆಯ ಭಾಗದ ಚಂದ್ರನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"ಕ್ಷೀಣಿಸುತ್ತಿರುವ ಅರ್ಧಚಂದ್ರನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"ಅರ್ಧಚಂದ್ರ"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"ಮುಖವಿರುವ ಚಂದ್ರಾಕೃತಿ"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"ಮುಖವಿರುವ ಹುಣ್ಣಿಮೆ ಚಂದ್ರನ ಮೊದಲ ಭಾಗ"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"ಮುಖವಿರುವ ಹುಣ್ಣಿಮೆ ಚಂದ್ರನ ಕೊನೆಯ ಭಾಗ"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"ಮುಖವಿರುವ ಪೂರ್ಣ ಚಂದ್ರ"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"ಮುಖವುಳ್ಳ ಸೂರ್ಯನ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"ಬೆಳಗುವ ನಕ್ಷತ್ರ"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"ಶೂಟಿಂಗ್ ಸ್ಟಾರ್"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"ಚೆಸ್ಟ್‌ನಟ್"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"ಮೊಳಕೆ"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"ನಿತ್ಯಹರಿದ್ವರ್ಣದಿಂದ ಕೂಡಿದ ಮರ"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"ಎಲೆ ಉದುರುವ ಮರ"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"ತಾಳೆ ಮರ"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"ಪಾಪಾಸು ಕಳ್ಳಿ"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"ಟುಲಿಪ್"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"ಚೆರ್ರಿ ಬ್ಲಾಸಮ್"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"ಗುಲಾಬಿ"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"ದಾಸವಾಳ"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"ಸೂರ್ಯಕಾಂತಿ‌"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"ಬ್ಲಾಸಮ್"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"ಸುಲಿದ ಮೆಕ್ಕೆ ಜೋಳ"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"ಭತ್ತದ ತೆನೆ"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"ಮೂಲಿಕೆ"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"ನಾಲ್ಕು ಎಲೆಯ ಮೂರೆಲೆ ಗಿಡ"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"ಮ್ಯಾಪಲ್ ಲೀಫ್"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"ಉದುರಿರುವ ಎಲೆ"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"ಗಾಳಿಯಲ್ಲಿ ತೇಲುತ್ತಿರುವ ಎಲೆ"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"ಅಣಬೆ"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"ಟೊಮ್ಯಾಟೊ"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"ಬದನೆಕಾಯಿ"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"ದ್ರಾಕ್ಷಿ"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"ಕರಬೂಜ ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"ಕಲ್ಲಂಗಡಿ ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"ಕಿತ್ತಳೆ ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"ನಿಂಬೆ"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"ಬಾಳೆಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"ಅನಾನಾಸ್ ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"ಕೆಂಪು ಸೇಬು"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"ಹಸಿರು ಸೇಬು"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"ಪೇರು ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"ಪೀಚ್‌ ಹಣ್ಣು"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"ಚೆರ್ರಿಗಳು"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"ಸ್ಟ್ರಾಬೆರಿ"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ಹ್ಯಾಮ್‌ಬರ್ಗರ್"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"ಪಿಜ್ಜಾ ತುಂಡು"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"ಮೂಳೆ ಮಾಂಸ"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"ಕೋಳಿಯ ಕಾಲುಮೂಳೆ ಮಾಂಸ"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"ರೈಸ್ ಕ್ರ್ಯಾಕರ್"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"ಅನ್ನದ ಮುದ್ದೆ"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"ಬೇಯಿಸಿದ ಅನ್ನ"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"ಅನ್ನ ಮತ್ತು ಮೇಲೋಗರ"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"ಆವಿ ಬಟ್ಟಲು"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"ಸ್ಪಾಗೆಟ್ಟಿ"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ಬ್ರೆಡ್"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"ಫ್ರೆಂಚ್ ಫ್ರೈಸ್"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"ಹುರಿದ ಸಿಹಿ ಆಲೂಗೆಡ್ಡೆ"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"ಡ್ಯಾಂಗೊ"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ಓಡನ್"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"ಸುಶಿ"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"ಹುರಿದ ಸೀಗಡಿ"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"ಸುಳಿಯ ವಿನ್ಯಾಸದ ಫಿಶ್ ಕೇಕ್"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"ಮೃದು ಐಸ್ ಕ್ರೀಂ"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"ಶೇವಡ್ ಐಸ್ ಕ್ರೀಂ"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ಐಸ್ ಕ್ರೀಂ"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ಡೋನಟ್"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"ಕುಕಿ"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"ಚಾಕೊಲೇಟ್ ಬಾರ್"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"ಕ್ಯಾಂಡಿ"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"ಕಸ್ಟರ್ಡ್"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ಜೇನಿನ ಮಡಕೆ"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ಶಾರ್ಟ್‌ಕೇಕ್"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"ಬೆಂಟ್ ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"ಆಹಾರದ ಡಬ್ಬಿ"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"ಅಡಿಗೆ"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ಫೋರ್ಕ್ ಮತ್ತು ಚಾಕು"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"ಹಿಡಿ ಇಲ್ಲದ ಟೀಕಪ್"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"ಸೇಕ್ ಬಾಟಲ್ ಮತ್ತು ಕಪ್"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"ವೈನ್ ಗ್ಲಾಸ್"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"ಕಾಕ್‌ಟೇಲ್ ಗ್ಲಾಸ್"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"ಉಷ್ಣವಲಯದ ಪಾನೀಯ"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"ಬಿಯರ್ ಮಗ್"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ತಾಗಿಸುತ್ತಿರುವ ಬಿಯರ್ ಮಗ್‌ಗಳು"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ಬೇಬಿ ಬಾಟಲ್"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ರಿಬ್ಬನ್"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"ಸುತ್ತಿದ ಉಡುಗೊರೆ"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"ಹುಟ್ಟುಹಬ್ಬದ ಕೇಕ್"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"ಜಾಕ್-ಓ-ಲಾಟೀನು"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"ಕ್ರಿಸ್‌ಮಸ್ ಟ್ರೀ"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"ಫಾದರ್ ಕ್ರಿಸ್‌ಮಸ್"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"ಸುಡುಮದ್ದುಗಳು"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"ಸುಡುಮದ್ದು ಚಿತ್ತಾರ"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"ಬಲೂನ್"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"ಪಾರ್ಟಿ ಪಾಪ್ಪರ್"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"ಬಣ್ಣದ ಚೆಂಡು"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"ಟ್ಯಾನಾಬಾಟಾ ಟ್ರೀ"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"ಅಡ್ಡಲಾದ ಧ್ವಜಗಳು"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"ಪೈನ್ ಅಲಂಕಾರ"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"ಜಾಪನೀಸ್ ಗೊಂಬೆಗಳು"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"ಕಾರ್ಪ್ ಪತಾಕೆ"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"ಗಾಳಿಯ ಸಾಲುಗಂಟೆ"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"ಚಂದ್ರ ವೀಕ್ಷಣೆ ಸಮಾರಂಭ"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"ಶಾಲೆಯ ಸಣ್ಣ ಚೀಲ"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"ಪದವಿ ಕ್ಯಾಪ್"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"ಕರೋಸೆಲ್ ಕುದುರೆ"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"ಫೆರ್ರಿಸ್ ಚಕ್ರ"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"ರೋಲರ್ ಕೋಸ್ಟರ್"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"ಮೀನಿನ ಗಾಳ ಮತ್ತು ಮೀನು"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"ಮೈಕ್ರೋಫೋನ್‌"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"ಚಲನಚಿತ್ರದ ಕ್ಯಾಮರಾ"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"ಚಲನಚಿತ್ರ"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"ಹೆಡ್‌ಫೋನ್"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"ಕಲಾವಿದರ ಪ್ಯಾಲೆಟ್"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"ಮೇಲಿನ ಟೊಪ್ಪಿಗೆ"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"ಸರ್ಕಸ್ ಟೆಂಟ್"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"ಟಿಕೆಟ್"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"ಕ್ಲಾಪ್ಪರ್ ಬೋರ್ಡ್"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"ಪ್ರದರ್ಶನ ಕಲೆಗಳು"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"ವಿಡಿಯೋ ಗೇಮ್"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"ನೇರ ಹೊಡೆತ"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"ಸ್ಲಾಟ್ ಯಂತ್ರ"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"ಬಿಲಿಯರ್ಡ್ಸ್"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"ಗೇಮ್ ಡೈ"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"ಬೌಲಿಂಗ್"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"ಫ್ಲವರ್ ಪ್ಲೇಯಿಂಗ್ ಕಾರ್ಡ್ಸ್"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"ಮ್ಯೂಸಿಕಲ್ ನೋಟ್"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"ಬಹು ಮ್ಯೂಸಿಕಲ್ ನೋಟ್ಸ್"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"ಸ್ಯಾಕ್ಸೋಫೋನ್"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"ಗಿಟಾರು"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"ಮ್ಯೂಸಿಕಲ್ ಕೀಬೋರ್ಡ್"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ತುತ್ತೂರಿ"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"ಪಿಟೀಲು"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"ಮ್ಯೂಸಿಕಲ್ ಸ್ಕೋರ್"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"ತೂಗುಪಟ್ಟಿ ಇರುವ ರನ್ನಿಂಗ್ ಶರ್ಟ್"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"ಟೆನಿಸ್ ರಾಕೆಟ್ ಮತ್ತು ಚೆಂಡು"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"ಸ್ಕೀ ಮತ್ತು ಸ್ಕೀ ಬೂಟ್"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"ಬ್ಯಾಸ್ಕೆಟ್‌ಬಾಲ್ ಮತ್ತು ಹುಪ್"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"ಚೌಕಗಳಿರುವ ಧ್ವಜ"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"ಸ್ನೋಬೋರ್ಡರ್"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"ರನ್ನರ್"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"ಕಡಲಲೆ ಸವಾರಿ ಕ್ರೀಡಾಪಟು"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ಟ್ರೋಫಿ"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"ಕುದುರೆ ರೇಸಿಂಗ್"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"ಅಮೆರಿಕನ್‌ ಫುಟ್‌‌ಬಾಲ್‌"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"ರಗ್ಬಿ ಫುಟ್‌ಬಾಲ್‌"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"ಈಜುಗಾರ"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"ಮನೆಯ ಕಟ್ಟಡ"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"ತೋಟದ ಮನೆ"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"ಕಚೇರಿ ಕಟ್ಟಡ"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"ಜಾಪನೀಸ್ ಅಂಚೆ ಕಚೇರಿ"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"ಯೂರೋಪಿಯನ್ ಅಂಚೆ ಕಚೇರಿ"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"ಆಸ್ಪತ್ರೆ"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ಬ್ಯಾಂಕ್"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ಸ್ವಯಂಚಾಲಿತ ಹಣ ಪಾವತಿ ಯಂತ್ರ"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ಹೋಟೆಲ್‌"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"ಲವ್ ಹೋಟೆಲ್"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"ಕನ್ವೀನಿಯನ್ಸ್ ಸ್ಟೋರ್"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"ಶಾಲೆ"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ಡಿಪಾರ್ಟ್‌ಮೆಂಟ್ ಸ್ಟೋರ್"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"ಕಾರ್ಖಾನೆ"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"ಇಝಾಕಾಯ ಲಾಟೀನು"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"ಜಪಾನೀಸ್ ಕೋಟೆ"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"ಯುರೋಪಿಯನ್ ಕೋಟೆ"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"ಇಲಿ"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"ಇಲಿ"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"ಎತ್ತು"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"ಎಮ್ಮೆ"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"ಹಸು"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"ಚಿರತೆ"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"ಮೊಲ"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"ಬೆಕ್ಕು"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ಡ್ರ್ಯಾಗನ್‌"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"ಮೊಸಳೆ"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"ತಿಮಿಂಗಿಲ"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"ಬಸವನ ಹುಳು"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"ಹಾವು"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"ಕುದುರೆ"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"ಠಗರು"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"ಮೇಕೆ"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"ಕುರಿ"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"ಕೋತಿ"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"ಬಿಳಿ ಹುಂಜ"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"ಕೋಳಿಮರಿ"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"ನಾಯಿ"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"ಹಂದಿ"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"ಗಂಡು ಹಂದಿ"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ಆನೆ"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ಆಕ್ಟೊಪಸ್"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"ಶಂಖ"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"ಕೀಟ"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"ಇರುವೆ"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"ಜೇನುನೊಣ"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"ಹೆಣ್ಣು ಜೀರುಂಡೆ"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"ಮೀನು"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ಉಷ್ಣವಲಯದ ಮೀನು"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ಬ್ಲೋಫಿಶ್‌‌"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"ಆಮೆ"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"ಕೋಳಿಮರಿ"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"ಸಣ್ಣ ಕೋಳಿಮರಿ"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"ಎದುರುಗಾಣುತ್ತಿರುವ ಕೋಳಿಮರಿ"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"ಪಕ್ಷಿ"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"ಪೆಂಗ್ವಿನ್"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"ಕೋಲಾಲ"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"ಪೂಡ್ಲ್‌"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"ಸವಾರಿ ಒಂಟೆ"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"ಬ್ಯಾಕ್ಟ್ರಿಯನ್ ಒಂಟೆ"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"ಡಾಲ್ಫಿನ್"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"ಇಲಿ ಮುಖ"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"ಹಸು ಮುಖ"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"ಹುಲಿ ಮುಖ"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"ಮೊಲದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ಡ್ರ್ಯಾಗನ್ ಮುಖ"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"ನೀರನ್ನು ಚುರಕಿ ಹೊಡೆಯುವ ತಿಮಿಂಗಿಲ"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"ಕುದುರೆ ಮುಖ"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"ಕೋತಿಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"ನಾಯಿಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"ಹಂದಿ ಮುಖ"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"ಕಪ್ಪೆ ಮುಖ"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"ಹ್ಯಾಮ್‌ಸ್ಟರ್ ಮುಖ"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"ತೋಳದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"ಕರಡಿ ಮುಖ"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"ಪಾಂಡಾ ಮುಖ"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"ಹಂದಿಯ ಮೂಗು"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"ಹೆಜ್ಜೆ ಗುರುತುಗಳು"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"ಕಣ್ಣುಗಳು"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"ಕಿವಿ"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"ಮೂಗು"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"ಬಾಯಿ"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"ನಾಲಿಗೆ"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"ಮೇಲ್ಮುಖದ ಕೈಬೆರಳು"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"ಕೆಳಮುಖದ ಕೈಬೆರಳು"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"ಎಡಕ್ಕೆ ಸೂಚಿಸುವ ಕೈಬೆರಳು"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"ಬಲಕ್ಕೆ ಸೂಚಿಸುವ ಕೈಬೆರಳು"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"ಬಿಗಿಮುಷ್ಠಿಯ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"ಬೀಸುತ್ತಿರುವ ಕೈ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"ಸರಿ ಸೂಚನೆಯ ಕೈಬೆರಳಿನ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"ಒಪ್ಪಿಗೆ ಸೂಚನೆಯ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"ಅಸಮ್ಮತಿ ಸೂಚನೆಯ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"ಚಪ್ಪಾಳೆ ಕೈಗಳ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"ತೆರೆದ ಕೈಗಳ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"ಕಿರೀಟ"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"ಹೆಂಗಸರ ಟೋಪಿ"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"ಕನ್ನಡಕ"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ಕತ್ತಿನ ಟೈ"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"ಟಿ-ಶರ್ಟ್"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ಜೀನ್ಸ್"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"ಉಡುಪು"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"ಸೊಂಟಪಟ್ಟಿ ಕಟ್ಟಿದ ಉಡುಗೆ"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"ಹೆಂಗಸರ ಒಳ ಉಡುಪು"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"ಹೆಂಗಸರ ಬಟ್ಟೆ"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ಪರ್ಸ್"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ಕೈಚೀಲ"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"ಕೈಚೀಲ"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"ಪುರುಷರ ಶೂ"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"ಅಥ್ಲೆಟಿಕ್ ಶೂ"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ಎತ್ತರದ-ಹಿಮ್ಮಡಿಯ ಶೂ"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"ಸ್ತ್ರೀಯರ ಚಪ್ಪಲಿ"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"ಸ್ತ್ರೀಯರ ಬೂಟು"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"ಹೆಜ್ಜೆಗುರುತುಗಳು"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"ನೆರಳುಚಿತ್ರದಲ್ಲಿ ಪ್ರತಿಮೆ"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"ನೆರಳುಚಿತ್ರದಲ್ಲಿ ಪ್ರತಿಮೆಗಳು"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"ಹುಡುಗ"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"ಹುಡುಗಿ"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"ಪುರುಷ"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ಸ್ತ್ರೀ"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"ಕುಟುಂಬ"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"ಕೈ ಹಿಡಿದುಕೊಂಡಿರುವ ಪುರುಷ ಮತ್ತು ಸ್ತ್ರೀ"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"ಕೈ ಹಿಡಿದುಕೊಂಡಿರುವ ಇಬ್ಬರು ಪುರುಷರು"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"ಕೈ ಹಿಡಿದಿರುವ ಇಬ್ಬರು ಸ್ತ್ರೀಯರು"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"ಪೊಲೀಸ್ ಅಧಿಕಾರಿ"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"ಬನ್ನಿ ಕಿವಿಗಳನ್ನು ಧರಿಸಿರುವ ಸ್ತ್ರೀ"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"ಮುಸುಕು ಹೊದ್ದಿರುವ ಸ್ತ್ರೀ"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"ಹೊಂಬಣ್ಣದ ಕೂದಲುಳ್ಳ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"ಗುವ ಪೈ ಮಾವೋ ಧರಿಸಿರುವ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"ಪೇಟ ತೊಟ್ಟಿರುವ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"ವೃದ್ಧ"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"ವೃದ್ಧೆ"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"ಮಗು"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"ಕಟ್ಟಡ ನಿರ್ಮಾಣ ಕಾರ್ಮಿಕ"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"ರಾಜಕುಮಾರಿ"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"ಜಾಪನೀಸ್ ರಾಕ್ಷಸ"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"ಜಾಪನೀಸ್ ಗಾಬ್ಲಿನ್"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"ಪ್ರೇತ"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"ಪುಟ್ಟ ರಾಜಕುಮಾರಿ"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"ಅನ್ಯಲೋಕ ಜೀವಿ"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"ಏಲಿಯನ್ ದೈತ್ಯ"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"ದೆವ್ವದ ಕೂಸು"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"ತಲೆಬುರುಡೆ"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"ಮಾಹಿತಿ ಡೆಸ್ಕ್ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"ಕಾಪುದಳದ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"ನೃತ್ಯಗಾರ್ತಿ"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"ಲಿಪ್‌ಸ್ಟಿಕ್"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"ಉಗುರು ಬಣ್ಣ"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"ಮುಖ ಮರ್ಧನ"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"ಕ್ಷೌರ"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"ಬಾರ್ಬರ್ ಪೋಲ್"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"ಸಿರಿಂಜ್"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ಮಾತ್ರೆ"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"ಮುತ್ತಿನ ಗುರುತು"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"ಪ್ರೇಮ ಪತ್ರ"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"ಉಂಗುರ"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"ವಜ್ರ"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"ಮುತ್ತು"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"ಪುಷ್ಪಗುಚ್ಛ"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"ಹೃದಯ ಜೋಡಿ"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"ವಿವಾಹ"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"ಹೃದಯ ಬಡಿತ"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"ಒಡೆದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"ಎರಡು ಹೃದಯಗಳು"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"ಮಿನುಗುತ್ತಿರುವ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"ಉಬ್ಬುತ್ತಿರುವ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"ಬಾಣದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"ನೀಲಿ ಬಣ್ಣದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"ಹಸಿರು ಬಣ್ಣದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"ಹಳದಿ ಬಣ್ಣದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"ನೇರಳೆ ಬಣ್ಣದ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"ರಿಬ್ಬನ್‌ನಿಂದ ಸುತ್ತುವರೆದಿರುವ ಹೃದಯ"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"ಗಿರಕಿಹೊಡೆಯುತ್ತಿರುವ ಹೃದಯಗಳು"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"ಹೃದಯಾಲಂಕಾರ"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"ಚುಕ್ಕೆ ಇರುವ ವಜ್ರಾಕಾರ"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"ಎಲೆಕ್ಟ್ರಿಕ್ ಲೈಟ್ ಬಲ್ಬ್"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"ಕೋಪದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"ಬಾಂಬ್"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"ಮಲಗುವ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"ಘರ್ಷಣೆಯ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"ಚಿಮ್ಮುವ ಬೆವರಿನ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"ನೀರಿನ ಹನಿ"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"ಡ್ಯಾಶ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"ಪೂ ಪೈಲ್"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"ಬಾಗಿದ ತೋಳು"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"ಡಿಜ್ಜಿ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"ಭಾಷಣದ ಬಲೂನ್"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"ಚಿಂತನಶೀಲ ಬಲೂನ್"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"ಬಿಳಿ ಹೂವು"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"ನೂರು ಅಂಕಗಳ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"ಹಣದ ಚೀಲ"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"ಕರೆನ್ಸಿ ವಿನಿಮಯ"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"ಹೆವಿ ಡಾಲರ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ಯೆನ್ ಚಿಹ್ನೆಯ ಬ್ಯಾಂಕ್‌ನೋಟ್"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ಡಾಲರ್ ಚಿಹ್ನೆಯ ಬ್ಯಾಂಕ್‌ನೋಟ್"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ಯೂರೋ ಚಿಹ್ನೆಯ ಬ್ಯಾಂಕ್‌ನೋಟ್"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ಪೌಂಡ್ ಚಿಹ್ನೆಯ ಬ್ಯಾಂಕ್‌ನೋಟ್"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"ರೆಕ್ಕೆ ಇರುವ ಹಣ"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"ಮೇಲಕ್ಕೇರುತ್ತಿರುವ ಪ್ರವೃತ್ತಿಯ ಚಾರ್ಟ್ ಮತ್ತು ಯೆನ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"ಆಸನ"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"ಪರ್ಸನಲ್ ಕಂಪ್ಯೂಟರ್"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"ಬ್ರೀಫ್‌ಕೇಸ್"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"ಮಿನಿ ಡಿಸ್ಕ್"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ಫ್ಲಾಪಿ ಡಿಸ್ಕ್‌"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ಆಪ್ಟಿಕಲ್‌ ಡಿಸ್ಕ್‌"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"ಡಿವಿಡಿ"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"ಫೈಲ್ ಫೋಲ್ಡರ್"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"ತೆರೆದ ಫೈಲ್ ಫೋಲ್ಡರ್"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"ಮುದುಡಿಕೊಂಡಿರುವ ಪುಟ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"ಮೇಲ್ಮುಖವಾಗಿರುವ ಪುಟ"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"ಕ್ಯಾಲೆಂಡರ್"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ಟಿಯರ್-ಆಫ್-ಕ್ಯಾಲೆಂಡರ್"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"ಕಾರ್ಡ್ ಇಂಡೆಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"ಮೇಲಕ್ಕೇರುತ್ತಿರುವ ಪ್ರವೃತ್ತಿಯ ಚಾರ್ಟ್"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"ಕೆಳಗಿಳಿಯುತ್ತಿರುವ ಪ್ರವೃತ್ತಿಯ ಚಾರ್ಟ್"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"ಬಾರ್ ಚಾರ್ಟ್"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"ಪುಶ್‌ಪಿನ್"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"ದುಂಡು ಪಿನ್"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"ಕಾಗದದ ಕ್ಲಿಪ್"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"ನೇರ ಅಳತೆಮಾಪಕ"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"ತ್ರಿಕೋನ ಮಾಪಕ"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"ಬುಕ್‌ಮಾರ್ಕ್ ಟ್ಯಾಬ್‌ಗಳು"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"ಲೆಡ್ಜರ್"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"ನೋಟ್‌ಬುಕ್"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"ಅಲಂಕಾರಿಕ ಕವರ್‌ನ ನೋಟ್‌ಬುಕ್"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"ಮುಚ್ಚಿದ ಪುಸ್ತಕ"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"ತೆರೆದ ಪುಸ್ತಕ"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"ಹಸಿರು ಬಣ್ಣದ ಪುಸ್ತಕ"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"ನೀಲಿ ಬಣ್ಣದ ಪುಸ್ತಕ"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"ಕಿತ್ತಳೆ ಬಣ್ಣದ ಪುಸ್ತಕ"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"ಪುಸ್ತಕಗಳು"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"ಹೆಸರಿನ ಬ್ಯಾಡ್ಜ್"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"ಸ್ಕ್ರಾಲ್"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"ಮೆಮೊ"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"ಟೆಲಿಫೋನ್ ರಿಸೀವರ್"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"ಪೇಜರ್"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"ಫ್ಯಾಕ್ಸ್ ಯಂತ್ರ"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"ಉಪಗ್ರಹ ಆಂಟೆನಾ"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"ಸಾರ್ವಜನಿಕ ಧ್ವನಿವರ್ಧಕ"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ಹರ್ಷೋದ್ಗಾರದ ಧ್ವನಿವರ್ಧಕ"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"ಔಟ್‌ಬಾಕ್ಸ್ ಟ್ರೇ"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ಇನ್‌ಬಾಕ್ಸ್ ಟ್ರೇ"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"ಪ್ಯಾಕೇಜ್"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ಇಮೇಲ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ಒಳಬರುವ ಹೊದಿಕೆ"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ಮೇಲ್ಭಾಗದಲ್ಲಿ ಕೆಳಮುಖ ಬಾಣವಿರುವ ಎನ್ವಲಪ್"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"ಕೆಳಮುಖ ಫ್ಲ್ಯಾಗ್ ಚಿಹ್ನೆ ಇರುವ ಮುಚ್ಚಿದ ಮೇಲ್‌ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"ಫ್ಲ್ಯಾಗ್ ಚಿಹ್ನೆ ಮೇಲ್ಮುಖವಾಗಿರುವ ಮುಚ್ಚಿದ ಮೇಲ್‌ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"ಫ್ಲ್ಯಾಗ್ ಚಿಹ್ನೆ ಮೇಲ್ಮುಖವಾಗಿರುವ ತೆರೆದ ಮೇಲ್‌ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"ಕೆಳಮುಖವಾಗಿರುವ ಫ್ಲ್ಯಾಗ್ ಚಿಹ್ನೆ ತೆರೆದ ಮೇಲ್‌ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"ಪೋಸ್ಟ್‌ಬಾಕ್ಸ್"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"ಪೋಸ್ಟ್ ಹಾರ್ನ್"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"ವೃತ್ತಪತ್ರಿಕೆ"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"ಮೊಬೈಲ್‌ ಫೋನ್"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"ಎಡಕ್ಕೆ ಬಲದಿಕ್ಕಿಗೆ ಸೂಚಿಸುವ ಬಾಣದ ಮೊಬೈಲ್ ಫೋನ್"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"ವೈಬ್ರೇಷನ್ ಮೋಡ್"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"ಮೊಬೈಲ್ ಫೋನ್ ಆಫ್"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"ಮೊಬೈಲ್ ಫೋನ್‌ಗಳಿಲ್ಲ"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"ಬಾರ್‌ಗಳಿರುವ ಆಂಟೆನಾ"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"ಕ್ಯಾಮರಾ"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"ವೀಡಿಯೊ ಕ್ಯಾಮರಾ"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"ದೂರದರ್ಶನ"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"ರೇಡಿಯೋ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"ವೀಡಿಯೊ ಕ್ಯಾಸೆಟ್"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"ಬಲದಿಕ್ಕಿಗೆ ತಿರುಚಿರುವ ಬಾಣಗಳು"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"ಪ್ರದಕ್ಷಿಣಾಕಾರದ ಬಲದಿಕ್ಕು ಮತ್ತು ಎಡದಿಕ್ಕಿನ ಕಡೆಗೆ ತೆರೆದ ವಲಯದ ಬಾಣಗಳು"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"ಒಂದು ಒವರ್‌ಲೇ ಜೊತೆಗೆ ಪ್ರದಕ್ಷಿಣಾಕಾರದ ಬಲದಿಕ್ಕು ಮತ್ತು ಎಡದಿಕ್ಕುಗಳ ಕಡೆಗೆ ತೆರೆದ ವಲಯದ ಬಾಣಗಳು"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"ಪ್ರದಕ್ಷಿಣಾಕಾರವಾಗಿ ಕೆಳಕ್ಕೆ ಮತ್ತು ಮೇಲಕ್ಕೆ ತೆರೆದ ವಲಯದ ಬಾಣಗಳು"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"ಅಪ್ರದಕ್ಷಿಣಾಕಾರವಾಗಿ ಕೆಳಮುಖ ಮತ್ತು ಮೇಲ್ಮುಖವಾಗಿರುವ ತೆರೆದ ವಲಯದ ಬಾಣಗಳು"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"ಕಡಿಮೆ ಹೊಳಪಿನ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"ಹೆಚ್ಚು ಹೊಳಪಿನ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"ರದ್ದು ಸ್ಟ್ರೋಕ್‌ನ ಸ್ಪೀಕರ್"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"ಸ್ಪೀಕರ್‌"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ಏಕ ಧ್ವನಿ ತರಂಗದ ಸ್ಪೀಕರ್"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"ಮೂರು ಧ್ವನಿ ತರಂಗಗಳ ಸ್ಪೀಕರ್"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"ಬ್ಯಾಟರಿ"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"ಎಲೆಕ್ಟ್ರಿಕ್ ಪ್ಲಗ್"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"ಎಡಕ್ಕೆ ತಿರುಗಿದ ಬೂದುಗನ್ನಡಿ"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"ಬಲಕ್ಕೆ ತಿರುಗಿದ ಬೂದುಗನ್ನಡಿ"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ಇಂಕ್ ಪೆನ್‌ನಿಂದ ಲಾಕ್"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"ಕೀಲಿಯಿಂದ ಮುಚ್ಚಿದ ಲಾಕ್"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"ಕೀಲಿ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"ಲಾಕ್"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"ತೆರೆದ ಲಾಕ್"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"ಬೆಲ್"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"ರದ್ದು ಸ್ಟ್ರೋಕ್ ಬೆಲ್"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"ಬುಕ್‌ಮಾರ್ಕ್‌"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"ಲಿಂಕ್ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ರೇಡಿಯೋ ಬಟನ್"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"ಮೇಲೆ ಎಡದಿಕ್ಕಿನ ಕಡೆಗಿನ ಬಾಣವನ್ನು ಹೊಂದಿರುವ ಹಿಂದಕ್ಕೆ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"ಮೇಲೆ ಎಡದಿಕ್ಕಿನ ಕಡೆಗೆ ಬಾಣವಿರುವ ಅಂತ್ಯದ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ಮೇಲೆ ಎಡ ಮತ್ತು ಬಲ ಬಾಣವಿರುವ ಆಶ್ಚರ್ಯಕರ ಚಿಹ್ನೆಯನ್ನು ಹೊಂದಿರುವ ಆನ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"ಮೇಲೆ ಬಲದಿಕ್ಕಿನ ಕಡೆಗಿನ ಬಾಣವಿರುವ ಶೀಘ್ರದಲ್ಲಿಯೇ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"ಮೇಲೆ ಮೇಲ್ಮುಖ ಬಾಣದ ಗುರುತು ಹೊಂದಿರುವ ಮೇಲಕ್ಕೆ ಚಿಹ್ನೆ"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"ಹದಿನೆಂಟು ಚಿಹ್ನೆಯ ಅಡಿಯಲ್ಲಿ ಯಾವುದೂ ಇಲ್ಲ"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"ಕ್ಯೀಕ್ಯಾಪ್ ಟೆನ್"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"ಲ್ಯಾಟಿನ್ ದೊಡ್ಡಕ್ಷರಗಳಿಗಾಗಿ ಇನ್‌ಪುಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"ಲ್ಯಾಟಿನ್ ಸಣ್ಣಕ್ಷರಗಳಿಗಾಗಿ ಇನ್‌ಪುಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"ಸಂಖ್ಯೆಗಳಿಗಾಗಿ ಇನ್‌ಪುಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"ಸಂಕೇತಗಳಿಗಾಗಿ ಇನ್‌ಪುಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"ಲ್ಯಾಟಿನ್ ಅಕ್ಷರಗಳಿಗೆ ಇನ್‌ಪುಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"ಬೆಂಕಿ"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"ಎಲೆಕ್ಟ್ರಿಕ್ ಟಾರ್ಚ್"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"ವ್ರೆಂಚ್"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"ಸುತ್ತಿಗೆ"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"ನಟ್ ಮತ್ತು ಬೋಲ್ಟ್"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"ಚೂರಿ"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"ಪಿಸ್ತೂಲು"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"ಸೂಕ್ಷ್ಮ ದರ್ಶಕ"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"ಟೆಲಿಸ್ಕೋಪ್"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"ಕ್ರಿಸ್ಟಲ್ ಬಾಲ್"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"ಮಧ್ಯ ಬಿಂದು ಸೇರಿದಂತೆ ಆರು ಬಿಂದುಗಳುಳ್ಳ ನಕ್ಷತ್ರ"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"ಹೊಸಬರಿಗೆ ಜಾಪನೀಸ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"ಟ್ರಿಡೆಂಟ್ ಲಾಂಛನ"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"ಕಪ್ಪು ಚೌಕದ ಬಟನ್"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ಬಿಳಿ ಚೌಕದ ಬಟನ್"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"ದೊಡ್ಡ ಕೆಂಪು ಬಣ್ಣದ ವೃತ್ತ"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"ದೊಡ್ಡ ನೀಲಿ ಬಣ್ಣದ ವೃತ್ತ"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"ದೊಡ್ಡ ಕಿತ್ತಳೆ ಬಣ್ಣದ ವಜ್ರ"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"ದೊಡ್ಡ ನೀಲಿ ಬಣ್ಣದ ವಜ್ರ"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"ಸಣ್ಣ ಕಿತ್ತಳೆ ಬಣ್ಣದ ವಜ್ರ"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"ಸಣ್ಣ ನೀಲಿ ಬಣ್ಣದ ವಜ್ರ"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"ಮೇಲಕ್ಕೆ ಸೂಚಿಸುವ ಕೆಂಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"ಕೆಳಕ್ಕೆ ಸೂಚಿಸುವ ಕೆಂಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"ಮೇಲಕ್ಕೆ ಸೂಚಿಸುವ ಕೆಂಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"ಕೆಳಕ್ಕೆ ಸೂಚಿಸುವ ಕೆಂಪು ಬಣ್ಣದ ತ್ರಿಕೋನ"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"ಒಂದು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"ಎರಡು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"ಮೂರು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"ನಾಲ್ಕು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"ಐದು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"ಆರು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"ಏಳು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"ಎಂಟು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"ಒಂಬತ್ತು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"ಹತ್ತು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"ಹನ್ನೊಂದು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"ಹನ್ನೆರಡು ಗಂಟೆಯ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"ಒಂದು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"ಎರಡು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"ಮೂರು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"ನಾಲ್ಕು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"ಐದು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"ಆರು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"ಏಳು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"ಎಂಟು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"ಒಂಬತ್ತು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"ಹತ್ತು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"ಹನ್ನೊಂದು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"ಹನ್ನೆರಡು-ಮೂವತ್ತರ ಗಡಿಯಾರ"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ಮೌಂಟ್ ಫುಜಿ"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"ಟೋಕಿಯೋ ಟವರ್"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"ಲಿಬರ್ಟಿ ಪ್ರತಿಮೆ"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"ಜಪಾನ್‌ನ ಸಿಲೋಟ್"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"ಮೋಯೈ"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"ಮಂದಸ್ಮಿತ ಕಣ್ಣುಗಳುಳ್ಳ ನಗುಮುಖ"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"ಸಂತೋಷದ ಕಣ್ಣೀರಿಡುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"ತೆರೆದ ಬಾಯಿಯ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"ತೆರೆದ ಬಾಯಿ ಮತ್ತು ನಗು ಕಣ್ಣುಗಳ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"ತೆರೆದ ಬಾಯಿ ಮತ್ತು ತಣ್ಣನೆಯ ಬೆವರಿನ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"ತೆರೆದ ಮುಖ ಮತ್ತು ಬಿಗಿಯಾಗಿ ಮುಚ್ಚಿದ ಕಣ್ಣುಗಳ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"ಹಾಲೋ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"ಹಾರ್ನ್ಸ್ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"ಕಣ್ಣು ಮಿಟುಕಿಸುತ್ತಿರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"ನಗು ಕಣ್ಣುಗಳ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"ನಾಲಿಗೆ ಚಪ್ಪರಿಸುತ್ತಿರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"ನೆಮ್ಮದಿ ತೋರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"ಹೃದಯಾಕಾರದ ಕಣ್ಣುಗಳ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"ಕನ್ನಡಕ ಹಾಕಿಕೊಂಡ ಮಂದಸ್ಮಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"ಆಲಸ್ಯ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"ತಟಸ್ಥ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"ಭಾವನೆ ಇಲ್ಲದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"ಹಾಸ್ಯಗ್ರಹಿಸದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"ಬೆವರಿನಿಂದ ಕೂಡಿದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"ಚಿಂತಾಕ್ರಾಂತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"ಗೊಂದಲ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"ತಲೆಕೆಳಗು ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"ಚುಂಬನ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"ಮುತ್ತು ಹೊರಗೆಡುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"ನಗು ಕಣ್ಣುಗಳ ಚುಂಬನ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"ಮುಚ್ಚಿದ ಕಣ್ಣುಗಳ ಚುಂಬನದ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"ಸೊಕ್ಕಿನ ನಾಲಿಗೆ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"ಸೊಕ್ಕಿನ ನಾಲಿಗೆ ಮತ್ತು ಮಿಟುಕಿಸುತ್ತಿರುವ ಕಣ್ಣಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"ಸೊಕ್ಕಿನ ನಾಲಿಗೆ ಮತ್ತು ಬಿಗಿಯಾಗಿ ಮುಚ್ಚಿದ ಕಣ್ಣುಗಳ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"ಬೇಸರ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"ಆತಂಕದ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"ಕೋಪೋದ್ರಿಕ್ತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"ಮೊಂಡುತನದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"ಅಳಲು ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"ನಿಷ್ಠೂರ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"ವಿಜಯೋತ್ಸವದ ನಗೆ ಬೀರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"ಬೇಸರವಿದ್ದರೂ, ನೆಮ್ಮದಿ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"ತೆರೆದ ಬಾಯಿಯ ಹುಬ್ಬು ಗಂಟಿಕ್ಕಿದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"ಅಳು ಮುಖ"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"ನಡತೆ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"ಅಸಹನೆ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"ನಿದ್ರಾವಸ್ಥೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"ಆಯಾಸ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"ಸೊಟ್ಟ ಮೋರೆ"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"ಜೋರಾಗಿ ಅಳುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"ತೆರೆದ ಬಾಯಿಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"ಗೋಪ್ಯತಾ ಭಾವನೆಯ ಮುಖ"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"ತೆರೆದ ಬಾಯಿ ಮತ್ತು ಬೆವರಿನಿಂದ ಕೂಡಿದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"ಭಯದಲ್ಲಿ ಕಿರಿಚುತ್ತಿರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"ಆಶ್ಚರ್ಯಚಕಿತ ಮುಖ"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"ಕೆಂಪೇರಿದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"ಮಲಗಿರುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"ಡಿಜ್ಜಿ ಮುಖ"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"ಬಾಯಿಲ್ಲದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"ವೈದ್ಯಕೀಯ ಮುಖವಾಡದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"ನಗು ಕಣ್ಣುಗಳ ಹಾಸ್ಯದ ನಗೆ ಬೀರುವ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"ಸಂತೋಷದ ಕಣ್ಣೀರಿಡಿರುವ ಮಂದಸ್ಮಿತ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"ತೆರೆದ ಬಾಯಿಯ ಮಂದಸ್ಮಿತ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"ಹೃದಯಾಕಾರದ ಕಣ್ಣುಗಳುಳ್ಳ ಮಂದಸ್ಮಿತ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"ವಕ್ರ ನಗುವಿನ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"ಮುಚ್ಚಿದ ಕಣ್ಣುಗಳ ಚುಂಬನ ಭಾವನೆಯ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"ಮೊಂಡುತನ ಭಾವನೆಯ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"ಅಳು ಭಾವನೆಯ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"ಅಸಹನೆ ಭಾವನೆಯ ಬೆಕ್ಕಿನ ಮುಖ"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"ಉತ್ತಮ ಸನ್ನೆ ಇಲ್ಲದ ಮುಖ"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"ಸರಿ ಸನ್ನೆ ಮಾಡುವ ಮುಖ"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"ದೀರ್ಘವಾಗಿ ತಲೆಬಾಗಿರುವ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"ಕಣ್ಣು ಮುಚ್ಚಿಕೊಂಡಿರುವ ಕೋತಿ"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"ಕಿವಿ ಮುಚ್ಚಿಕೊಂಡಿರುವ ಕೋತಿ"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"ಬಾಯಿ ಮುಚ್ಚಿಕೊಂಡಿರುವ ಕೋತಿ"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"ಸಂತೋಷದಿಂದ ಒಂದು ಕೈ ಎತ್ತಿರುವ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"ಸಂಭ್ರಮಾಚರಣೆಯಲ್ಲಿ ಎರಡೂ ಕೈಗಳನ್ನು ಎತ್ತುವ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"ಹುಬ್ಬು ಗಂಟಿಕ್ಕಿದ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"ಮೊಂಡುತನ ಭಾವನೆಯ ಮುಖದ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"ನಮಸ್ಕಾರ ಸೂಚನೆಯ ವ್ಯಕ್ತಿ"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"ರಾಕೆಟ್"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ಹೆಲಿಕಾಪ್ಟರ್"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"ಉಗಿಬಂಡಿ ಯಂತ್ರ"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"ರೈಲ್ವೆ ಕಾರು"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"ಹೈ-ಸ್ಪೀಡ್ ರೈಲು"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"ಬುಲೆಟ್ ಮೂತಿಯುಳ್ಳ ಹೈ-ಸ್ಪೀಡ್ ರೈಲು"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ರೈಲು"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"ಮೆಟ್ರೋ"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"ಹಗುರ ರೈಲು"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"ನಿಲ್ದಾಣ"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ಟ್ರ್ಯಾಮ್"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ಟ್ರ್ಯಾಮ್ ಕಾರ್"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"ಬಸ್ಸು"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"ಮುಂದು ಬರುತ್ತಿರುವ ಬಸ್ಸು"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ಟ್ರಾಲಿಬಸ್"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"ಬಸ್ ತಂಗುದಾಣ"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"ಮಿನಿಬಸ್"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"ಆಂಬುಲೆನ್ಸ್"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"ಅಗ್ನಿಶಾಮಕ ಯಂತ್ರ"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"ಪೊಲೀಸ್ ಕಾರು"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"ಮುಂದು ಬರುತ್ತಿರುವ ಪೊಲೀಸ್ ಕಾರು"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"ಟ್ಯಾಕ್ಸಿ"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"ಮುಂದು ಬರುತ್ತಿರುವ ಟ್ಯಾಕ್ಸಿ"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"ಆಟೊಮೊಬೈಲ್"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"ಮುಂದು ಬರುತ್ತಿರುವ ಆಟೊಮೊಬೈಲ್"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"ಮನರಂಜನೆ ವಾಹನ"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"ಡೆಲಿವರಿ ಟ್ರಕ್"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ಜಂಟಿ ಲಾರಿ"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ಟ್ರ್ಯಾಕ್ಟರ್"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"ಮೋನೊರೈಲ್"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"ಪರ್ವತ ರೈಲು"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"ತೂಗು ರೈಲ್ವೆ"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"ಪರ್ವತದ ಕೇಬಲ್ ಮಾರ್ಗ"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ಏರಿಯಲ್ ಟ್ರ್ಯಾಮ್ ವೇ"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"ಹಡಗು"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"ಹಾಯಿದೋಣಿ"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"ವೇಗದ ಮೋಟಾರು ದೋಣಿ"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"ಅಡ್ಡ ಸಂಚಾರಿ ದೀಪ"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ಲಂಬ ಸಂಚಾರಿ ದೀಪ"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"ನಿರ್ಮಾಣ ಹಂತದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"ಪೊಲೀಸ್ ಕಾರುಗಳು ಸುತ್ತುತ್ತಿರುವ ಬೆಳಕು"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"ಪೋಸ್ಟ್‌ನಲ್ಲಿ ತ್ರಿಕೋನಾಕಾರದ ಧ್ವಜ"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"ಬಾಗಿಲು"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"ಪ್ರವೇಶವಿಲ್ಲ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"ಧೂಮಪಾನ ನಿಷೇಧದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"ಧೂಮಪಾನ ನಿಷೇಧದ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"ಕಸವನ್ನು ಅದರ ಸ್ಥಳದಲ್ಲಿ ಹಾಕಿ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"ಕಸ ಹಾಕಬಾರದು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"ಕುಡಿಯುವ ನೀರು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"ನೀರು ಕುಡಿಯಲು ಯೋಗ್ಯವಲ್ಲ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"ಸೈಕಲ್"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"ಸೈಕಲ್‌ಗಳಿಗೆ ಪ್ರವೇಶವಿಲ್ಲ"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"ಬೈಸಿಕಲ್ ಪಟು"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"ಪರ್ವತದ ಸೈಕಲ್ ಪಟು"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"ಪಾದಚಾರಿ"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"ಪಾದಚಾರಿಗಳಿಗೆ ಪ್ರವೇಶವಿಲ್ಲ"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"ಮಕ್ಕಳು ದಾಟುವ ಮಾರ್ಗ"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"ಪುರುಷರು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"ಮಹಿಳೆಯರು ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"ಶೌಚಾಲಯ"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"ಮಗುವಿನ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"ಟಾಯ್ಲೆಟ್ ಸಂಕೇತ"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"ವಾಟರ್ ಕ್ಲೋಸೆಟ್"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"ಷವರ್"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"ಸ್ನಾನ"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"ಸ್ನಾನದ ತೊಟ್ಟಿ"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"ಪಾಸ್‌ಪೋರ್ಟ್ ನಿಯಂತ್ರಣ"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"ಕಸ್ಟಮ್ಸ್"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"ಸರಕು ಹಕ್ಕು"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"ಬಿಟ್ಟಿರುವ ಸಾಮಾನು"</string>
+</resources>
diff --git a/java/res/values-kn-rIN/strings-talkback-descriptions.xml b/java/res/values-kn-rIN/strings-talkback-descriptions.xml
index 15cef7c..a2445e2 100644
--- a/java/res/values-kn-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-kn-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"ಯಾವುದೇ ಪಠ್ಯವನ್ನು ನಮೂದಿಸಿಲ್ಲ"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ನಿಂದ <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> ಆಗಿ <xliff:g id="KEY_NAME">%1$s</xliff:g> ಸರಿಪಡಿಸುತ್ತದೆ"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ಸ್ವಯಂ ತಿದ್ದುಪಡಿಯನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"ಯಾವುದೇ ಸಲಹೆ ಇಲ್ಲ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"ಅಪರಿಚಿತ ಅಕ್ಷರ"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"ಇನ್ನಷ್ಟು ಸಂಕೇತಗಳು"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"ಕ್ಯಾಪಿಟಲ್ I, ಮೇಲೆ ಡಾಟ್"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"ಅಪರಿಚಿತ ಚಿಹ್ನೆ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"ಅಪರಿಚಿತ ಎಮೋಜಿ"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"ಬೇಸರದ ಮುಖ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"ಸಂಕೋಚದ ಮುಖ"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"ಸನ್‌ಗ್ಲಾಸ್‌ಗಳನ್ನು ಧರಿಸಿರುವ ಮುಖ"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"ಆಶ್ಚರ್ಯದ ಮುಖ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"ಚುಂಬನದ ಮುಖ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"ತಿರಸ್ಕಾರದ ಮುಖ"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ಪರ್ಯಾಯ ಅಕ್ಷರಗಳು ಲಭ್ಯ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ಪರ್ಯಾಯ ಅಕ್ಷರಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ಪರ್ಯಾಯ ಸಲಹೆಗಳು ಲಭ್ಯ"</string>
diff --git a/java/res/values-kn-rIN/strings.xml b/java/res/values-kn-rIN/strings.xml
index 6cc78ec..b8d61ec 100644
--- a/java/res/values-kn-rIN/strings.xml
+++ b/java/res/values-kn-rIN/strings.xml
@@ -26,24 +26,30 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"ಕೀಲಿಯನ್ನು ಒತ್ತಿದಾಗ ವೈಬ್ರೇಷನ್‌"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"ಕೀಲಿಯನ್ನು ಒತ್ತಿದಾಗ ಶಬ್ದಮಾಡು"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"ಕೀ ಒತ್ತಿದಾಗ ಪಾಪ್ ಅಪ್‌ ಮಾಡು"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ಆದ್ಯತೆಗಳು"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"ಖಾತೆಗಳ ಗೌಪ್ಯತೆ"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"ಗೋಚರತೆಯ ಲೇಔಟ್‌ಗಳ"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ಗೆಸ್ಚರ್ ಟೈಪಿಂಗ್"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"ಪಠ್ಯ ತಿದ್ದುಪಡಿ"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"ಸುಧಾರಿತ"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"ಥೀಮ್"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"ಬೇರ್ಪಡೆ ಕೀಬೋರ್ಡ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google ಕೀಬೋರ್ಡ್‌ ಸಿಂಕ್‌"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"ಸಿಂಕ್‌ ಆನ್‌ ಆಗಿದೆ"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನಿಘಂಟನ್ನು ಸಾಧನಗಳಲ್ಲಿ ಸಿಂಕ್ ಮಾಡಿ"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ಇದೀಗ ಸಿಂಕ್ ಮಾಡಿ"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ಮೇಘ ಡೇಟಾವನ್ನು ಅಳಿಸಿ"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google ನಿಂದ ನಿಮ್ಮ ಸಿಂಕ್ ಮಾಡಲಾದ ಡೇಟಾವನ್ನು ಅಳಿಸುತ್ತದೆ"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ನಿಮ್ಮ ಸಿಂಕ್‌ ಮಾಡಲಾದ ಡೇಟಾವನ್ನು ಮೇಘದಿಂದ ಅಳಿಸಲಾಗುತ್ತದೆ. ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ಅಳಿಸು"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ರದ್ದುಮಾಡು"</string>
+    <!-- unknown quoting pattern: original -1, translation 1 -->
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನಿಘಂಟನ್ನು Google ಸರ್ವರ್‌ಗಳಿಗೆ ಸಿಂಕ್‌ ಮಾಡಲಾಗುತ್ತದೆ &amp;amp; ಬ್ಯಾಕಪ್‌ ಮಾಡಲಾಗುತ್ತದೆ. ನಮ್ಮ ಉತ್ಪನ್ನಗಳನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು ಪದ ಆವರ್ತನೆ ಅಂಕಿಅಂಶವನ್ನು ಸಂಗ್ರಹಿಸಬಹುದು. ಎಲ್ಲಾ ಮಾಹಿತಿಯ ಸಂಗ್ರಹಣೆ ಮತ್ತು ಬಳಕೆಯ "<a href="https://www.google.com/policies/privacy">"Google ನ ಗೌಪ್ಯತೆ ನೀತಿ"</a>" ಯ ಅಡಿಯಲ್ಲಿ ಅನುಸರಣೆ ಮಾಡಲಾಗುತ್ತದೆ."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ಈ ಸಾಧನಕ್ಕೆ ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ದಯವಿಟ್ಟು Google ಖಾತೆಯನ್ನು ಸೇರಿಸಿ"</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">"ಭಾಷಾ ಬದಲಾವಣೆ ಕೀಯು ಇತರೆ ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಕೂಡ ಒಳಗೊಂಡಿರುತ್ತದೆ"</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">"ಸ್ಲೈಡ್ ಸೂಚಕ ತೋರಿಸು"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shift ಅಥವಾ ಚಿಹ್ನೆ ಕೀಗಳಿಂದ ಸ್ಲೈಡ್ ಮಾಡುವಾಗ ದೃಶ್ಯ ಕ್ಯೂ ಪ್ರದರ್ಶಿಸು"</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>
@@ -62,9 +68,6 @@
     <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>
@@ -85,21 +88,32 @@
     <string name="voice_input" msgid="3583258583521397548">"ಧ್ವನಿ ಇನ್‌ಪುಟ್ ಕೀ"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ಯಾವುದೇ ಧ್ವನಿ ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ. ಭಾಷೆ &amp; ಇನ್‌ಪುಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</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="language_selection_title" msgid="3666971864764478269">"ಭಾಷೆಗಳು"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ಸಹಾಯ &amp; ಪ್ರತಿಕ್ರಿಯೆ"</string>
+    <string name="select_language" msgid="5709487854987078367">"ಭಾಷೆಗಳು"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ಉಳಿಸಲು ಮತ್ತೆ ಸ್ಪರ್ಶಿಸಿ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ಉಳಿಸಲು ಇಲ್ಲಿ ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ನಿಘಂಟು ಲಭ್ಯವಿದೆ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ಕೀಬೋರ್ಡ್ ಥೀಮ್"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ಖಾತೆಗಳನ್ನು ಬದಲಿಸು"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ಯಾವುದೇ ಖಾತೆಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿಲ್ಲ"</string>
+    <string name="account_selected" msgid="2846876462199625974">"ಪ್ರಸ್ತತವಾಗಿ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> ಅನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ಸರಿ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"ರದ್ದುಮಾಡು"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ಸೈನ್ ಔಟ್"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"ಬಳಸಲು ಖಾತೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ಇಂಗ್ಲಿಷ್ (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ಇಂಗ್ಲಿಷ್ (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ಸ್ಪ್ಯಾನಿಷ್ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ಹಿಂಗ್ಲಿಷ್"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"ಸರ್ಬಿಯನ್ (ಲ್ಯಾಟಿನ್)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ಇಂಗ್ಲಿಷ್ (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ಇಂಗ್ಲಿಷ್ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ಸ್ಪ್ಯಾನಿಷ್ (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ಹಿಂಗ್ಲಿಷ್ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ಸರ್ಬಿಯನ್ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಸಾಂಪ್ರದಾಯಿಕ)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಸಿರಿಲಿಕ್)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಲ್ಯಾಟಿನ್)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ಕಾಂಪ್ಯಾಕ್ಟ್‌‌)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ಯಾವುದೇ ಭಾಷೆಯಿಲ್ಲ (ವರ್ಣಮಾಲೆ)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ವರ್ಣಮಾಲೆ (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ವರ್ಣಮಾಲೆ (QWERTZ)"</string>
@@ -108,16 +122,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ವರ್ಣಮಾಲೆ (ಕೋಲ್‌ಮ್ಯಾಕ್)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ವರ್ಣಮಾಲೆ (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ಎಮೋಜಿ"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"ಕೀಬೋರ್ಡ್ ಥೀಮ್"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"ಕಸ್ಟಮ್ ಇನ್‌ಪುಟ್ ಶೈಲಿಗಳು"</string>
     <string name="add_style" msgid="6163126614514489951">"ಶೈಲಿ ಸೇರಿಸು"</string>
     <string name="add" msgid="8299699805688017798">"ಸೇರಿಸು"</string>
@@ -129,14 +134,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> ಗಾಗಿ ಈ ಫೈಲ್‌ ಅನ್ನು ನಿಜಕ್ಕೂ ಸ್ಥಾಪಿಸುವುದೇ?"</string>
-    <string name="error" msgid="8940763624668513648">"ದೋಷ ಉಂಟಾಗಿದೆ"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ಕೀಯ ದೀರ್ಘ ಒತ್ತುವ ವಿಳಂಬ"</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>
@@ -154,8 +154,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ಈಗ ನೀವು <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">"ಲಾಂಚರ್‌ನಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಐಕಾನ್ ಪ್ರದರ್ಶಿಸು"</string>
     <string name="app_name" msgid="6320102637491234792">"ನಿಘಂಟು ಪೂರೈಕೆದಾರರು"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ನಿಘಂಟು ಪೂರೈಕೆದಾರರು"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"ನಿಘಂಟು ಸೇವೆ"</string>
diff --git a/java/res/values-ko/strings-emoji-descriptions.xml b/java/res/values-ko/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..c4e16f1
--- /dev/null
+++ b/java/res/values-ko/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"저작권 기호"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"등록 기호"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"느낌표 2개"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"느낌표 물음표"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"상표 기호"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"안내소"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"좌우 양방향 화살표"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"상하 양방향 화살표"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"북서쪽 화살표"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"북동쪽 화살표"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"남동쪽 화살표"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"남서쪽 화살표"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"왼쪽을 가리키는 갈고리 화살표"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"오른쪽을 가리키는 갈고리 화살표"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"손목시계"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"모래시계"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"오른쪽을 가리키는 검은색 이중 삼각형"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"왼쪽을 가리키는 검은색 이중 삼각형"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"위를 가리키는 검은색 이중 삼각형"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"아래를 가리키는 검은색 이중 삼각형"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"알람 시계"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"모래가 떨어지는 모래시계"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"라틴어 M 원문자"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"작은 검은색 정사각형"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"작은 흰색 정사각형"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"오른쪽을 가리키는 검은색 삼각형"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"왼쪽을 가리키는 검은색 삼각형"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"중간 크기의 흰색 정사각형"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"중간 크기의 검은색 정사각형"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"중소형의 흰색 정사각형"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"중소형의 검은색 정사각형"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"햇살이 있는 검은색 태양"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"구름"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"검은색 전화기"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"체크표시가 있는 정사각형"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"우산과 빗방울"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"뜨거운 음료"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"위를 가리키는 흰색 검지"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"웃는 흰색 얼굴"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"양자리"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"황소자리"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"쌍둥이자리"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"게자리"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"사자자리"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"처녀자리"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"천칭자리"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"전갈자리"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"궁수자리"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"염소자리"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"물병자리"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"물고기자리"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"검은색 스페이드"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"검은색 클로버"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"검은색 하트"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"검은색 다이아몬드"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"온천"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"검은색 보편적인 재활용 기호"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"휠체어 기호"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"닻"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"경고 기호"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"고압 전류 기호"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"중간 크기의 흰색 원"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"중간 크기의 검은색 원"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"축구공"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"야구공"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"눈송이 없는 눈사람"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"구름에 가려진 태양"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"뱀주인자리"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"진입 금지"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"교회"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"분수"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"골프 홀에 있는 깃발"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"범선"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"텐트"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"주유기"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"검은색 가위"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"굵은 흰색 체크표시"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"비행기"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"봉투"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"위를 향한 주먹"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"위를 향한 손"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"승리의 V를 한 손"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"연필"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"검은색 펜촉"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"굵은 체크표시"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"굵은 곱셈 표시"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"반짝임"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"8각 별표"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"8각 검은 별"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"눈송이"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"광채"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"곱셈 표시"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"음각 곱셈 표시 블록"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"검은색 물음표"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"흰색 물음표"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"흰색 느낌표"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"굵은 느낌표 기호"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"검은색 하트"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"굵은 덧셈 기호"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"굵은 뺄셈 기호"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"굵은 나눗셈 기호"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"검은색 오른쪽 화살표"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"한 번 꼬인 선"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"두 번 꼬인 선"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"오른쪽을 가리키다가 위로 꺾어지는 화살표"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"오른쪽을 가리키다가 아래로 꺾어지는 화살표"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"검은색 왼쪽 화살표"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"검은색 위 화살표"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"검은색 아래 화살표"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"큰 검은색 정사각형"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"큰 흰색 정사각형"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"중간 크기의 흰색 화살표"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"굵은 선으로 된 흰색 원"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"물결 대시"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"부품 교체 마크"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"한자 표기 축하 원문자"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"한자 표기 비밀 원문자"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"마작패 붉은 용"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"블랙 조커 카드"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"혈액형 A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"혈액형 B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"혈액형 O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"주차장"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"혈액형 AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL 블록"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"COOL 블록"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"FREE 블록"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID 블록"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"NEW 블록"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG 블록"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK 블록"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS 블록"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"UP! 블록"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS 블록"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"카타카나 여기 블록"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"카타카나 서비스 블록"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"한자 표기 무료 블록"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"한자 표기 예약석 블록"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"한자 표기 금지 블록"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"한자 표기 빈자리 블록"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"한자 표기 수락 블록"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"한자 표기 빈자리 없음 블록"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"한자 표기 유료 블록"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"한자 표기 월 블록"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"한자 표기 적용 블록"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"한자 표기 할인 블록"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"한자 표기 영업 중 블록"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"한자 표기 이익 원문자"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"한자 표기 수락 원문자"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"태풍"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"안개"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"접은 우산"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"별 밤"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"산 위의 일출"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"일출"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"황혼녘 도시 전경"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"빌딩 너머로 지는 해"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"무지개"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"교량 야경"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"파도"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"화산"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"은하수"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"지구본 유럽-아프리카"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"지구본 미주"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"지구본 아시아-오세아니아"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"자오선이 있는 지구본"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"삭 기호"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"삭현간 요월 기호"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"상현달 기호"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"현망간 철월 기호"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"보름달 기호"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"망현간 철월 기호"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"하현달 기호"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"현삭간 요월 기호"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"초승달"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"얼굴이 있는 삭"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"얼굴이 있는 상현달"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"얼굴이 있는 하현달"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"얼굴이 있는 보름달"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"얼굴이 있는 태양"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"반짝이는 별"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"별똥별"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"밤"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"묘목"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"상록수"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"낙엽수"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"야자나무"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"선인장"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"튤립"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"벚꽃"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"장미"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"무궁화"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"해바라기"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"꽃"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"옥수수"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"벼 이삭"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"허브"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"네 잎 클로버"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"단풍잎"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"낙엽"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"바람에 흩날리는 잎"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"버섯"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"토마토"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"가지"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"포도"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"멜론"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"수박"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"귤"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"레몬"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"바나나"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"파인애플"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"빨간 사과"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"초록 사과"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"배"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"복숭아"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"체리"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"딸기"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"햄버거"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"피자 조각"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"뼈에 붙은 고기"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"닭다리"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"쌀 과자"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"주먹밥"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"공기밥"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"카레라이스"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"라면"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"스파게티"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"빵"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"프렌치프라이"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"군고구마"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"경단 꼬치"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"어묵 꼬지"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"초밥"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"새우튀김"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"소용돌이무늬가 있는 어묵"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"소프트아이스크림"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"빙수"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"아이스크림"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"도넛"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"쿠키"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"초콜릿 바"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"사탕"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"막대 사탕"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"푸딩"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"꿀단지"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"조각 케이크"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"도시락"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"전골냄비"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"프라이팬"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"포크와 나이프"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"손잡이 없는 찻잔"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"술병과 잔"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"와인잔"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"칵테일잔"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"열대음료"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"맥주잔"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"맥주잔 건배"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"젖병"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"리본"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"포장된 선물"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"생일 케이크"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"호박 초롱"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"크리스마스 트리"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"산타클로스"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"불꽃놀이"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"불꽃놀이 폭죽"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"풍선"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"파티 폭죽"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"박 터트리기"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"일본 칠석제 나무"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"교차하는 깃발"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"소나무 장식"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"일본 인형"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"잉어 모양 깃발"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"풍경"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"달맞이 행사"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"책가방"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"학사모"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"회전목마"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"관람차"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"롤러코스터"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"낚싯대와 물고기"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"마이크"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"영화 카메라"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"극장"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"헤드폰"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"그림 팔레트"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"중절모"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"서커스 천막"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"입장권"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"슬레이트"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"공연"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"비디오 게임"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"명중"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"슬롯머신"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"당구"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"주사위"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"볼링"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"화투"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"음표"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"여러 개의 음표"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"색소폰"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"기타"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"건반"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"트럼펫"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"바이올린"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"악보"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"띠를 두른 셔츠"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"테니스 라켓과 공"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"스키와 스키 부츠"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"농구공과 농구 골대"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"바둑판무늬 깃발"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"스노보드를 타는 사람"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"달리는 사람"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"서핑을 하는 사람"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"트로피"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"경마"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"미식축구"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"럭비"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"수영하는 사람"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"주택"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"뜰이 있는 집"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"사무실 건물"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"일본 우체국"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"유럽 우체국"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"병원"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"은행"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ATM"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"호텔"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"러브호텔"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"편의점"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"학교"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"백화점"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"공장"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"주점 초롱"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"일본 성"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"유럽 성"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"쥐"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"생쥐"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"소"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"물소"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"소"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"표범"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"토끼"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"고양이"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"용"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"악어"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"고래"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"달팽이"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"뱀"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"말"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"숫양"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"염소"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"양"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"원숭이"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"수탉"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"닭"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"개"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"돼지"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"수퇘지"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"코끼리"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"문어"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"소라껍데기"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"벌레"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"개미"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"꿀벌"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"무당벌레"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"물고기"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"열대어"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"복어"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"거북이"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"알 까는 병아리"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"병아리 옆모습"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"병아리 앞모습"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"새"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"펭귄"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"코알라"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"푸들"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"단봉낙타"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"쌍봉낙타"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"돌고래"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"생쥐 얼굴"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"소 얼굴"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"호랑이 얼굴"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"토끼 얼굴"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"고양이 얼굴"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"용 얼굴"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"물 뿜는 고래"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"말 얼굴"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"원숭이 얼굴"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"개 얼굴"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"돼지 얼굴"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"개구리 얼굴"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"햄스터 얼굴"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"늑대 얼굴"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"곰 얼굴"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"판다 얼굴"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"돼지 코"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"동물 발자국"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"눈"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"귀"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"코"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"입"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"혀"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"검지가 위를 가리키는 흰색 손등"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"검지가 아래를 가리키는 흰색 손등"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"검지가 왼쪽을 가리키는 흰색 손등"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"검지가 오른쪽을 가리키는 흰색 손등"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"주먹 기호"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"손을 흔드는 기호"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK 하는 손 기호"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"엄지를 올린 손 기호"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"엄지를 내린 손 기호"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"손뼉 치는 손 기호"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"양손을 벌린 기호"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"왕관"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"여성용 모자"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"안경"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"넥타이"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"티셔츠"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"청바지"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"원피스"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"기모노"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"비키니"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"블라우스"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"지갑"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"핸드백"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"파우치"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"남성 구두"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"운동화"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"하이힐"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"여성 샌들"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"여성 부츠"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"발자국"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"상반신 실루엣"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"여러 명의 상반신 실루엣"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"소년"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"소녀"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"남자"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"여자"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"가족"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"손을 잡고 있는 남자와 여자"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"손을 잡고 있는 두 남자"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"손을 잡고 있는 두 여자"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"경찰관"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"토끼 귀를 한 여자"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"면사포를 쓴 신부"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"머리가 금발인 사람"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"중국 전통 모자를 쓴 남자"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"터번을 두른 남자"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"할아버지"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"할머니"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"아기"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"건설 노동자"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"공주"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"도깨비"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"코가 큰 마귀"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"유령"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"아기 천사"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"외계인"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"우주 괴물"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"꼬마 도깨비"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"해골"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"안내 데스크 직원"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"근위대원"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"무용수"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"립스틱"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"매니큐어"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"얼굴 마사지"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"헤어컷"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"이발소의 간판 기둥"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"주사기"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"알약"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"키스 자국"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"연애편지"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"반지"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"보석"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"키스"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"부케"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"연인과 하트"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"결혼"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"두근거리는 하트"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"깨진 하트"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"두 개의 하트"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"반짝이는 하트"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"점점 커지는 하트"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"화살 맞은 하트"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"파란색 하트"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"녹색 하트"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"노란색 하트"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"보라색 하트"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"리본 달린 하트"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"회전하는 하트"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"하트 장식"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"내부에 점에 있는 마름모 도형"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"전구"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"분노 기호"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"폭탄"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"수면 기호"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"충돌 기호"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"땀방울"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"작은 물방울"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"대시 기호"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"똥 덩어리"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"울퉁불퉁한 이두박근"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"어지러움 기호"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"말풍선"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"생각 풍선"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"흰색 꽃"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"백점 기호"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"돈 가방"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"환전"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"굵은 달러 기호"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"신용카드"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"엔화 지폐"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"달러 지폐"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"유로화 지폐"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"파운드화 지폐"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"날개 달린 돈다발"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"엔화 기호가 있는 상향 추세의 차트"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"좌석"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"개인 컴퓨터"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"서류 가방"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"미니 디스크"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"플로피 디스크"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"광학 디스크"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"파일 폴더"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"열려있는 파일 폴더"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"끝이 둥글게 말린 종이"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"종이 앞면"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"달력"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"일일달력"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"카드 색인 바인더"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"상향 추세의 차트"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"하향 추세의 차트"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"막대그래프"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"클립보드"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"압정"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"둥근 압정"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"클립"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"막대자"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"삼각자"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"즐겨찾기 탭"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"원장"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"공책"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"장식 표지가 있는 공책"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"덮인 책"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"펼친 책"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"녹색 책"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"파란색 책"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"주황색 책"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"여러 권의 책"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"명찰"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"두루마리"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"메모"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"전화 수화기"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"호출기"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"팩스기"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"위성 안테나"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"확성기"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"응원 메가폰"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"보낼 편지함 트레이"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"받은 편지함 트레이"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"소포"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"이메일 기호"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"수신 메시지 봉투"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"아래 화살표가 위에 있는 봉투"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"깃발을 내리고 닫혀 있는 우편함"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"깃발을 올리고 닫혀 있는 우편함"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"깃발을 올리고 열려 있는 우편함"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"깃발을 내리고 열려 있는 우편함"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"우체통"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"나팔"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"신문"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"휴대전화"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"오른쪽 화살표가 왼쪽에 있는 휴대전화"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"진동 모드"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"휴대전화 끄기"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"휴대전화 사용 금지"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"신호가 강한 안테나"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"카메라"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"비디오 카메라"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"텔레비전"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"라디오"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"비디오 카세트"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"서로 교차하는 오른쪽 화살표"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"시계 방향으로 오른쪽과 왼쪽으로 각각 순환하는 열린 화살표"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"시계 방향으로 오른쪽과 왼쪽으로 각각 순환하는 열린 화살표와 그 위에 있는 원문자 1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"시계 방향으로 위아래로 각각 순환하는 열린 화살표"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"시계 반대 방향으로 위아래로 각각 순환하는 열린 화살표"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"낮은 명도 기호"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"높은 명도 기호"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"스피커 사용 중지"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"스피커"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"하나의 음파가 있는 스피커"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"세 개의 음파가 있는 스피커"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"배터리"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"전기 플러그"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"왼쪽을 향한 돋보기"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"오른쪽을 향한 돋보기"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"잉크 펜과 자물쇠"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"열쇠와 자물쇠"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"열쇠"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"자물쇠"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"열려있는 자물쇠"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"종"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"종 사용 중지"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"책갈피"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"사슬 기호"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"라디오 버튼"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"왼쪽 화살표가 위에 있는 BACK"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"왼쪽 화살표가 위에 있는 END"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"좌우 양방향 화살표가 위에 있는 ON!"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"오른쪽 화살표가 위에 있는 SOON"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"위 화살표가 위에 있는 TOP"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18세 이하 금지 기호"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"키 캡 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"라틴어 대문자 입력 기호"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"라틴어 소문자 입력 기호"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"숫자 입력 기호"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"기호 입력 기호"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"라틴어 문자 입력 기호"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"불"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"손전등"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"렌치"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"망치"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"너트와 볼트"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"식칼"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"권총"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"현미경"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"망원경"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"수정구"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"중앙에 점이 있고 6각별"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"일본식 초보자 기호"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"삼지창 엠블럼"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"정사각형 검은색 버튼"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"정사각형 흰색 버튼"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"큰 빨간색 원"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"큰 파란색 원"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"큰 주황색 마름모"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"큰 파란색 마름모"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"작은 주황색 마름모"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"작은 파란색 마름모"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"빨간색 삼각형"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"빨간색 역삼각형"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"작은 빨간색 삼각형"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"작은 빨간색 역삼각형"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"1시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"2시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"3시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"4시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"5시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"6시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"7시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"8시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"9시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"10시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"11시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"12시를 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"1시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"2시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"3시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"4시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"5시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"6시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"7시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"8시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"9시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"10시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"11시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"12시 30분을 가리키는 시계"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"후지 산"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"도쿄 타워"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"자유의 여신상"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"일본의 실루엣"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"모아의 석상"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"이를 드러내고 활짝 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"미소 짓는 눈으로 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"기쁨의 눈물을 흘리는 얼굴"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"입을 벌리고 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"입을 벌리고 미소 짓는 눈으로 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"입을 벌리고 식은땀을 흘리며 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"입을 벌리고 눈을 꼭 감은 채로 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"후광이 있는 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"뿔 달린 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"윙크하는 얼굴"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"미소 짓는 눈으로 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"맛있는 음식을 음미하는 얼굴"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"안심하는 얼굴"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"하트 눈으로 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"선글라스를 쓰고 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"능글맞게 웃는 얼굴"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"감정을 드러내지 않은 얼굴"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"무표정한 얼굴"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"지루해하는 얼굴"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"식은땀 나는 얼굴"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"사색에 잠긴 얼굴"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"혼란에 빠진 얼굴"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"당혹해하는 얼굴"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"키스하는 얼굴"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"키스를 날리는 얼굴"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"미소 짓는 눈으로 키스하는 얼굴"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"눈을 감은 채 키스하는 얼굴"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"메롱 하는 얼굴"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"윙크하며 메롱 하는 얼굴"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"눈을 꼭 감은 채 메롱 하는 얼굴"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"실망한 얼굴"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"걱정하는 얼굴"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"화난 얼굴"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"입을 삐죽 내민 얼굴"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"우는 얼굴"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"인내하는 얼굴"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"의기양양한 얼굴"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"실망하지만 안심하는 얼굴"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"입을 벌리고 찡그리는 얼굴"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"고뇌에 찬 얼굴"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"두려워하는 얼굴"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"지친 얼굴"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"졸린 얼굴"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"피곤해하는 얼굴"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"찡그린 얼굴"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"엉엉 우는 얼굴"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"입을 벌린 얼굴"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"숨죽인 얼굴"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"입을 벌리고 식은땀 흘리는 얼굴"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"공포의 비명을 지르는 얼굴"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"놀라는 얼굴"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"빨개진 얼굴"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"잠자는 얼굴"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"어지러워하는 얼굴"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"입이 없는 얼굴"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"마스크를 한 얼굴"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"미소 짓는 눈으로 웃는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"기쁨의 눈물을 흘리는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"입을 벌리고 웃는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"하트 눈으로 웃는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"쓴웃음을 짓는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"눈을 감은 채 키스하는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"입을 삐죽 내민 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"우는 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"지친 고양이 얼굴"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"안 된다는 신호를 하는 얼굴"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OK 신호를 하는 얼굴"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"절하는 사람"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"눈을 가린 원숭이"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"귀를 막은 원숭이"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"입을 막은 원숭이"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"한 손을 든 행복한 사람"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"두 손을 들고 축하하는 사람"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"눈살을 찌푸린 사람"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"입을 삐죽 내민 사람"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"두 손을 모은 사람"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"로켓"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"헬리콥터"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"증기 기관차"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"철도 차량"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"고속 열차"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"고속 탄환 열차"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"기차"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"지하철"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"경전철"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"역"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"전차"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"전차 차량"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"버스"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"다가오는 버스"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"트롤리버스"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"버스 정류장"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"미니버스"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"구급차"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"소방차"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"경찰차"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"다가오는 경찰차"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"택시"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"다가오는 택시"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"자동차"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"다가오는 자동차"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"SUV"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"배달 트럭"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"트레일러"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"트랙터"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"모노레일"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"산악 기차"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"케이블카"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"산악용 케이블카"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"공중 케이블카"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"배"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"노 젓는 보트"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"모터보트"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"가로 신호등"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"세로 신호등"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"공사 표지"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"경찰차 사이렌"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"깃대에 있는 삼각 깃발"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"문"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"출입 금지 기호"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"흡연 기호"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"금연 기호"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"쓰레기통 사용 권장 기호"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"쓰레기 무단 투기 금지 기호"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"식수 기호"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"식수 금지 기호"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"자전거"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"자전거 금지"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"자전거 타는 사람"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"산악자전거 타는 사람"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"보행자"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"보행 금지"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"길 건너는 어린이"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"남자 기호"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"여자 기호"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"화장실"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"아기 기호"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"변기"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"샤워"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"목욕"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"욕조"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"출입국 관리"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"세관"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"수하물"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"미수취 수하물"</string>
+</resources>
diff --git a/java/res/values-ko/strings-talkback-descriptions.xml b/java/res/values-ko/strings-talkback-descriptions.xml
index 2a3fe88..c42765d 100644
--- a/java/res/values-ko/strings-talkback-descriptions.xml
+++ b/java/res/values-ko/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"입력한 텍스트 없음"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>을(를) 누르면 <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>을(를) <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>(으)로 수정합니다."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g>을(를) 누르면 자동 수정됩니다."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"추천 항목 없음"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"알 수 없는 문자"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift 키"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"기호 더보기"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"대문자 아이, 위 닷"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"알 수 없는 기호"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"알 수 없는 그림 이모티콘"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"지루한 얼굴"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"당황한 얼굴"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"선글라스 쓴 얼굴"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"놀란 얼굴"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"키스하는 얼굴"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"찌푸린 얼굴"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"대체 문자를 사용할 수 있습니다"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"대체 문자를 닫았습니다."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"대체 추천 단어를 사용할 수 있습니다"</string>
diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml
index b6f93e6..d12e36d 100644
--- a/java/res/values-ko/strings.xml
+++ b/java/res/values-ko/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"키를 누를 때 진동 발생"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"키를 누를 때 소리 발생"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"키를 누를 때 팝업"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"환경설정"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"계정 및 개인정보 보호"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"모양 및 레이아웃"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"제스처 타이핑"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"텍스트 수정"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"고급"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"테마"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"분할 키보드 사용"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google 키보드 동기화"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"동기화가 사용 설정됩니다."</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"개인 사전을 기기 간에 동기화합니다."</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"지금 동기화"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"클라우드 데이터 삭제"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google에서 동기화된 데이터 삭제"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"동기화된 데이터가 클라우드에서 삭제됩니다. 계속하시겠습니까?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"삭제"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"취소"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"개인 사전이 Google 서버에 동기화되며 백업됩니다. Google의 제품 개선을 위해 단어 빈도에 관한 통계 정보가 수집될 수 있습니다. 모든 정보는 "<a href="https://www.google.com/policies/privacy">"Google 개인정보취급방침"</a>"에 따라 수집되고 사용됩니다."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"이 기능을 사용하려면 기기에 Google 계정을 추가하세요."</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">"언어 전환 키가 제공하는 기타 입력 방법"</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">"슬라이드 표시기 표시"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shift 또는 기호 키에서 슬라이드하는 동안 시각 효과 표시"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -80,26 +82,37 @@
     <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="gesture_space_aware" msgid="2078291600664682496">"구문 동작"</string>
+    <string name="gesture_space_aware" msgid="2078291600664682496">"구문 제스처"</string>
     <string name="gesture_space_aware_summary" msgid="4371385818348528538">"동작 중에 스페이스바 쪽으로 움직여 공백 입력"</string>
     <string name="voice_input" msgid="3583258583521397548">"음성 입력 키"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"사용 설정된 음성 입력 방법이 없습니다. 언어 및 입력 설정을 확인하세요."</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="language_selection_title" msgid="3666971864764478269">"언어"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"도움말 및 의견"</string>
+    <string name="select_language" msgid="5709487854987078367">"언어"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"저장하려면 다시 터치"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"저장하려면 여기를 터치하세요."</string>
     <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"키보드 테마"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"계정 전환"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"선택한 계정이 없습니다."</string>
+    <string name="account_selected" msgid="2846876462199625974">"현재 <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"확인"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"취소"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"로그아웃"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"사용할 계정 선택"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"영어(영국)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"영어(미국)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"스페인어(미국)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"인도 영어"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"세르비아어(라틴 문자)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"영어(영국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"영어(미국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"스페인어(미국)(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"인도 영어(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"세르비아어(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(번체)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(키릴어)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(라틴어)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(컴팩트)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"언어 없음(알파벳)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"알파벳(QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"알파벳(QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"알파벳(콜맥)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"알파벳(PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"이모티콘"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"키보드 테마"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"맞춤 입력 스타일"</string>
     <string name="add_style" msgid="6163126614514489951">"스타일 추가"</string>
     <string name="add" msgid="8299699805688017798">"추가"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"이 파일을 <xliff:g id="LANGUAGE_NAME">%s</xliff:g>(으)로 설치하시겠습니까?"</string>
-    <string name="error" msgid="8940763624668513648">"오류 발생"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"키 길게 누르기 지연"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"이제 즐겨찾는 앱을 <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">"실행기에 애플리케이션 아이콘 표시"</string>
     <string name="app_name" msgid="6320102637491234792">"사전 제공업체"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"사전 제공업체"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"사전 서비스"</string>
diff --git a/java/res/values-ky-rKG/strings-action-keys.xml b/java/res/values-ky-rKG/strings-action-keys.xml
index 115a392..ffc5d1e 100644
--- a/java/res/values-ky-rKG/strings-action-keys.xml
+++ b/java/res/values-ky-rKG/strings-action-keys.xml
@@ -20,19 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for label_go_key (4033615332628671065) -->
-    <skip />
-    <!-- no translation found for label_next_key (5586407279258592635) -->
-    <skip />
-    <!-- no translation found for label_previous_key (1421141755779895275) -->
-    <skip />
-    <!-- no translation found for label_done_key (7564866296502630852) -->
-    <skip />
-    <!-- no translation found for label_send_key (482252074224462163) -->
-    <skip />
+    <string name="label_go_key" msgid="4033615332628671065">"Өтүү"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"Кийинки"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"Мурунку"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Аткарылды"</string>
+    <string name="label_send_key" msgid="482252074224462163">"Жөнөтүү"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Издөө"</string>
-    <!-- no translation found for label_pause_key (2225922926459730642) -->
-    <skip />
-    <!-- no translation found for label_wait_key (5891247853595466039) -->
-    <skip />
+    <string name="label_pause_key" msgid="2225922926459730642">"Бир аз токт"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"Күтүү"</string>
 </resources>
diff --git a/java/res/values-ky-rKG/strings-appname.xml b/java/res/values-ky-rKG/strings-appname.xml
new file mode 100644
index 0000000..4766fe9
--- /dev/null
+++ b/java/res/values-ky-rKG/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<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">"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-ky-rKG/strings-config-important-notice.xml b/java/res/values-ky-rKG/strings-config-important-notice.xml
new file mode 100644
index 0000000..44b9f9e
--- /dev/null
+++ b/java/res/values-ky-rKG/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"Сунуштарды байланыш каражаттарыңыздын жана терилген дайындардын негизинде жакшыртыңыз"</string>
+</resources>
diff --git a/java/res/values-ky-rKG/strings-emoji-descriptions.xml b/java/res/values-ky-rKG/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..7d836d0
--- /dev/null
+++ b/java/res/values-ky-rKG/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Автордук укук белгиси"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Катталган белги"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Кош илеп белгиси"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Илептүү суроо белгиси"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Соода марка белгиси"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Маалымат булагы"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Солго-оңго багытталган жебе"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Өйдө-төмөн жебе"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Түндүк-батыш жебеси"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Түндүк-чыгыш жебеси"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Түштүк-чыгыш жебеси"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Түштүк-батыш жебеси"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Солго багытталган илмектүү жебе"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Оңго багытталган илмектүү жебе"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Саат"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Кум сааты"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Оң жакты караган кара кош үч бурчтук"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Солду караган кара кош үч бурчтук"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Өйдө караган кара кош үч бурчтук"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Төмөн караган кара кош үч бурчтук"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Ойготкуч саат"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Куму агып жаткан кум сааты"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Тегеректелген чоң латын m тамгасы"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Кичине кара чарчы"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Кичине ак чарчы"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Оң жакты караган кара үч бурчтук"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Солду караган кара үч бурчтук"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Орточо ак чарчы"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Орточо кара чарчы"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Орточо кичине ак чарчы"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Орточо кичине кара чарчы"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Нур чачыраган кара күн"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Булут"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Кара телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Белги коюлган кутуча"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Кол чатыр менен жамгыр тамчылары"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Ысык суусундук"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Жогору караган ак көрсөткүч"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Жылмайган ак жүз"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Кой"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Букачар"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Эгиздер"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Бөйөн"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Арстан"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Бийкеч"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Тараза"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Чаян"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Жаачы"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Текечер"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Суу куйду"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Балык"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Карга белгиси"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Чырым белгиси"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Ача белгиси"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Момун белгиси"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Ысык булак"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Колдонулган нерселерди кайра иштетүү символу"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Майыптар арабасы символу"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Якорь"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Эскертүү белгиси"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Жогорку чыңалгандык белгиси"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Орточо ак тегерек"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Орточо кара тегерек"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Футбол тобу"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бейсбол"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Карсыз кар киши"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Булутка жашынган күн"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Жылан көтөргүч"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Кирүүгө болбойт"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Чиркөө"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтан"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Көзөнөктөгү желек"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Парус кайыгы"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Чатыр"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Күйүүчү май насосу"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Кара кайчы"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Жоон ак белги"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Учак"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Конверт"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Көтөрүлгөн муштум"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Көтөрүлгөн кол"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Жеңиш колу"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Калем"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Кара калем учу"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Жоон белги"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Жоон көбөйтүү белгиси x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Жылтырактар"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Сегиз бурчтуу жылдыз"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Сегиз бурчтуу кара жылдыз"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Кар бүртүгү"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Жылтылдоо"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Крест белгиси"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Чарчыланган крест белгиси"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Кара суроо белгилери менен жасалгалоо"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ак суроо белгилер менен жасалгалоо"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ак илеп белгилер менен жасалгалоо"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Жоон илеп белгисинин символу"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Жоон кара жүрөк"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Жоон кошуу белгиси"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Жоон кемитүү белгиси"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Жоон бөлүү белгиси"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Оңго багытталган кара жебе"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Тармал илмек"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Кош тармал илмек"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Оңго багытталып, андан соң өйдө карай ийилген жебе"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Оңго багытталып, андан соң төмөн карай ийилген жебе"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Солго багытталган кара жебе"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Жогору караган кара жебе"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Төмөн багытталган кара жебе"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Чоң кара чарчы"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Чоң ак чарчы"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Орточо ак жылдыз"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Жоон чоң тегерек"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Толкундуу сызык"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Бөлүк кезектешүү белгиси"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Тегеректелген идеограмма, куттуктоо"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Тегеректелген идеограмма купуясы"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Маджонг сөөкчөсү кызыл ажыдаар"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Оюн картасынын кара джокери"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Экинчи топтогу кан"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Үчүнчү топтогу кан"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Биринчи топтогу кан"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Унаа токтотмосу"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Төртүнчү топтогу кан"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Чарчы CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Чарчыланган салкын"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Чарчыланган бош"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Чарчыланган ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Чарчыланган жаңы"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Чарчыланган N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Чарчыланган OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Чарчыланган SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Илеп белгиси менен чарчыланган"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Чарчыланганга каршы"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Чарчыланган катакана бул жерде"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Чарчыланган катакана кызматы"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Чарчыланган идеограмма, акысыз"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Чарчыланган идеограмма, бош эмес орундук"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Чарчыланган идеограмма, тыюу салуу"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Чарчыланган идеограмма, вакансиясы"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Чарчыланган идеограмма, кабыл алуу"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Чарчыланган идеограмма, жыш отурукташкан"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Чарчыланган идеограмма, төлөндү"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Чарчыланган идеограмма, ай сайын"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Чарчыланган идеограмма, колдонмо"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Чарчыланган идеограмма, арзандатуу"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Бизнестеги чарчыланган идеограмма"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Тегеректелген идеограмма, артыкчылык"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Тегеректелген идеограмма, кабыл алуу"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Тумандуу"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Жабык кол чатыр"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Жылдыздуу түн"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Тоо үстүнөн күндүн чыгышы"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Күндүн чыгышы"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Күүгүмдөгү шаар көрүнүшү"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Имараттардын үстүнөн күндүн батышы"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Асан-үсөн"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Түнкү көпүрө"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Суу толкуну"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Жанар тоо"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Саманчынын жолу"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Жер шары Европа-Африка"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Жер шары жана америка"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Жер шары Азия-Австралия"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Меридиандары көрсөтүлгөн глобус"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Жаңы ай белгиси"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Момдон жасалган жарым ай белгиси"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Биринчи чейректеги ай белгиси"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Момдон жасалган ийилген ай белгиси"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Толгон ай белгиси"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Кемип жаткан ийилген ай белгиси"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Акыркы чейректеги ай белгиси"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Кемип жаткан жарым ай белгиси"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Жарым ай"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Жаңы ай бети менен"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Биринчи чейректеги ай бети менен"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Акыркы чейректеги ай бети менен"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Толгон ай бети менен"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Күн бети менен"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Жаркыраган жылдыз"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Учкан жылдыз"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Каштан"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Көчөт"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Түбөлүктүү жашыл дарак"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Жалбырагы түшүп жаткан дарак"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Пальма дарагы"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Жоогазын"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Алча гүлү"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Роза"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Гибискус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Күнкарама"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Гүлдөө"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Жүгөрү сотосу"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Күрүч машагы"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Чөп"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Төрт жалбырактуу беде"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Клён жалбырагы"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Үзүлгөн жалбырак"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Шамалга дирилдеген жалбырак"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Козу карын"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Помидор"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Баклажан"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Жүзүм"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Коон"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Дарбыз"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарин"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банан"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Кызыл алма"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Көк алма"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Алмурут"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Шабдаалы"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Алча"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Кулпунай"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Гамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Бир кесим пицца"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Сөөктүү эт"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Канаттуунун шыйрагы"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Күрүч печеньеси"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Күрүч тобу"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Бышкан күрүч"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Карри жана күрүч"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Бууланган казан"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Спагетти"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Нан"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Картөшкө-фри"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Куурулган таттуу картөшкө"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Оден"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Куурулган креветка"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Айланма жасалгалуу балык торту"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Жумшак балмуздак"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Жылмаланган муз"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Балмуздак"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Пончик"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Булочка"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Шоколад тилкеси"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Момпосуй"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Чыбыктагы момпосуй"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Крем"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Бал чөйчөк"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Үбөлөнмө торт"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Бенто кутусу"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Бир чөйчөк тамак"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Ашпозчулук"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Вилка жана бычак"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Чыны"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Сакэ шишеси жана чөйчөк"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Вино бокалы"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Коктейль бокалы"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропикалык суусундук"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Сыра кружкасы"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Шыңгыраган сыра кружкалары"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Баланын шишеси"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Тасма"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Оролгон белек"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Туулган күн торту"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Ашкабак чырагы"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Рождество балатысы"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Аяз ата"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Фейерверктер"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Бенгал шамы"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Шар"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Жардыргыч"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Конфетти"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Танабата дарагы"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Кайчылашкан желектер"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Кызыл карагай жасалгасы"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Жапон куурчактары"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Түстүү карптар"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Кытай жылаажындары"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Айды көрүү аземи"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Мектеп сумкасы"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Бүтүрүүчүнүн баш кийими"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Каруселдеги жылкылар"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Шайтандын дөңгөлөгү"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Америка дөбөлөрү"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Кайырмак жана балык"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Тасма камерасы"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кинотеатр"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Гарнитура"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Сүрөтчүнүн боёктору"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Бийик шляпа"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Цирк чатыры"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Билет"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Чык этме нумератору"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Аткаруу чеберчилиги"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Видео оюн"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Таамай тийүү"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Оюн автоматы"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Бильярд"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Оюн сөөгү"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Боулинг"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Гүлдүү оюн картасы"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музыкалык нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Бир нече музыкалык нота"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гитара"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Музыкалык баскычтоп"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Сурнай"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Скрипка"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Музыканын коштоосу"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Арта салынган тасмасы бар майка"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Теннис ракеткасы жана тобу"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Лыжа жана лыжа өтүгү"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскетбол жана себет"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Чакмактуу желек"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордчу"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Жөө күлүк"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Сёрфингчи"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Олжо"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Ат чабыш"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Америка футболу"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Регби"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Сүзүүчү"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Үй имараты"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Короосу бар үй"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Кеңсе имараты"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Жапон почтасы"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Европа почтасы"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Оорукана"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банк"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Мейманкана"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Сүйүү мейманканасы"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Чакан дүкөн"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Мектеп"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Универмаг"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Завод"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Идзакая чырагы"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Жапон сепили"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Европа сепили"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Келемиш"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Чычкан"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Өгүз"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Азия буйволу"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Уй"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Коён"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Мышык"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Ажыдаар"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Үлүл"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Жылан"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Жылкы"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Кочкор"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Эчки"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Кой"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Маймыл"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Короз"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Жөжө"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Ит"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Чочко"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Каман"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Пил"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Осьминог"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Буралма кабык"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Коңуз"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Кумурска"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Бал аары"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Эл кайда көчөт"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Балык"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропикалык балык"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Ит балык"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Ташбака"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Жаңы чыккан жөжө"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Балапан"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Алдыны карап турган балапан"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Куш"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудель"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Бир өркөчтүү төө"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Эки өркөчтүү төө"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Дельфин"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Чычкан"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Уйдун башы"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Жолборс"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Коён"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Мышык"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Ажыдаар"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Суу бүрккөн кит"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Жылкы"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Маймыл"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Ит"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Чочко"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Бака"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Хомяк"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Бөрү"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Аюу"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Панда"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Чочко мурун"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Жаныбарлардын издери"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Көздөр"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Кулак"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Мурун"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ооз"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Тил"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Сөөмөйүн жогору караткан ак кол көрсөткүчү"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Cөөмөйүн төмөн караткан ак кол көрсөткүчү"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Сөөмөйүн солго караткан ак кол көрсөткүчү"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Cөөмөйүн оңго караткан ак кол көрсөткүчү"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Түйүлгөн муштум белгиси"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Кол булгалоо белгиси"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Ok кол белгиси"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Жогору караган бармак белгиси"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Ылдый караган бармак белгиси"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Кол чабуу белгиси"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Алакандар белгиси"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Таажы"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Кыз-келиндердин шляпасы"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Көз айнек"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Галстук"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Футболка"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Джинсы"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Көйнөк"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Кыз-келиндердин кийимдери"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Капчык"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Кол баштык"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Баштык"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Эркектердин бут кийими"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Спорттук бут кийим"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Шиш така"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Кыз-келиндер сандалы"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Кыз-келиндердин өтүгү"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Бут изи"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Бюст карааны"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Бюст карааны"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Эркек бала"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Кыз"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Эркек киши"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Аял"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Үй-бүлө"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Кол кармашкан эркек менен аял"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Кол кармашкан эки эркек"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Кол кармашкан эки аял"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полиция офицери"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Коёндун кейпин кийген аял"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Ак үлбүрчөктүү колукту"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Ак саргыл чачтуу адам"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Гуа пи маочон киши"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Селдечен киши"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Абышка"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Кемпир"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Наристе"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Куруучу"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Ханбийке"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Жапон дөөсү"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Жапон гоблини"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Арбак"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Наристе периште"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Бөтөн планеталык"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Бөтөн планеталык желмогуз"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Шайтан"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Баш сөөк"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Маалымат тактасынын адамы"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Кароолчу"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Бийчи"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Ооз боёк"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Тырмак боёгу"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Жүздү укалоо"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Чач жасалгасы"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Чачтарач мамысы"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Дары"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Өбүү белгиси"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Сүйүү каты"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Шакек"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Акак таш"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Өбүү"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Гүлдесте"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Түгөйлөр жана жүрөк"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Үлпөт"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Соккон жүрөк"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Жараланган жүрөк"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Эки жүрөк"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Жаркылдаган жүрөк"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Өсүп жаткан жүрөк"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Жебе сайылган жүрөк"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Көк жүрөк"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Жашыл жүрөк"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Сары жүрөк"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Кызгылт сыя жүрөк"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Тасма байланган жүрөк"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Айланган жүрөктөр"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Жүрөк жасалгасы"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Ичинде чекити бар алмаз формасы"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Электр лампочкасы"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Ачуулануу символу"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Уйку символу"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Кагылыш символу"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Куюлуп жаткан тер символу"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Тамчы"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Сызыкча белгиси"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Үйүлгөн заң"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Түйүлгөн булчуң"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Баш айлануу символу"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Кеп булутчасы"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Ой булутчасы"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Ак гүл"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Жүз упай символу"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Акча баштыгы"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Валюта алмаштыруу"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Оор доллар белгиси"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Насыя картасы"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Йен банкнотасы"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Доллар банкнотасы"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Евро банкнотасы"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Фунт банкнотасы"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Канаттары бар акча"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Жогору багытталган диаграмма жана йен белгиси"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Орун"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Жеке компьютер"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Портфель"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Минидиск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптикалык диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Файлдар папкасы"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ачык файл папкасы"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Чети бүгүлгөн барак"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Жогору караган барак"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Жылнаама"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Айрыма жылнаама"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Карта индекси"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Жогору карай багытталган диаграмма"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Төмөн карай багытталган диаграмма"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Тилке диаграммасы"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Алмашуу буфери"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Сайгыч"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Тегерек сайгыч"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Кыстыргыч"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Сызгыч"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Үч бурчтук сызгыч"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Кыстарылган кыстырмалар"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Эсеп-кысап китепчеси"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Блокнот"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Кооз мукабалуу блокнот"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Жабык китеп"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Ачык китеп"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Жашыл китеп"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Көк китеп"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Кызгылтым сары китеп"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Китептер"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Ысым төш белгиси"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Сыдырып кароо"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Мемо"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефон трубкасы"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пейжер"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс машинасы"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Спутник антеннасы"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Катуу сүйлөгүч"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Сүрөөчү рупор"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Жөнөтүүчү себет"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Алуучу себет"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Таңгак"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mail символу"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Алынуучу конверт"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Үстүндө төмөн караган жебелүү конверт"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Желеги түшүрүлгөн жабык кат кутусу"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Желеги көтөрүлгөн жабык кат кутусу"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Желеги көтөрүлгөн ачык кат кутусу"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Желеги түшүрүлгөн ачык кат кутусу"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Почта кутусу"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Труба"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Гезит"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобилдик телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Сол жагында оңго багытталган жебелүү уюлдук телефон"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Дирилдөө режими"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Мобилдик телефон өчүк"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Мобилдик телефондор жок"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Тилкелүү антенна"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Видео камера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Сыналгы"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Видеокассета"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Оңду карай айланган жебелер"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Саат жебеси боюнча оңду жана солду карай айланган ачык тегеректүү жебелер"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Оңду карай саат жебеси боюнча жана солду карай айланган ачык тегеректүү жебелер тегеректелген бир катмар менен"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Саат жебеси боюнча төмөн карай жана өйдө карай айланган ачык тегеректүү жебелер"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Төмөн карай саат жебесине каршы айланган жана өйдө караган ачык тегеректүү жебелер"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Төмөн жарык символу"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Жогорку деңгээлдеги жарык символу"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Тыюу салынган катуу сүйлөткүч"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Катуу сүйлөткүч"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Бир толкундуу катуу сүйлөткүч"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Үч толкундуу катуу сүйлөткүч"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батарея"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Электр сайгычы"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Сол жакты караган чоңойтуу айнеги"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Оң жакты караган чоңойтуу айнеги"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Сыя калеми менен кулпулоо"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Ачкычы жанында турган жабык кулпу"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ачкыч"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Кулпу"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Ачык кулпу"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Коңгуроо"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Тыюу салынган коңгуроо"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Кыстарма"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Шилтеме символу"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Радио баскычы"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Үстүндөгү солго багытталган жебе менен артка"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Үстүндөгү солго багытталган жебе менен аягына"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Үстүндөгү солго багытталган жебелүү илеп белгиси менен күйгүзүү"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Үстүндөгү оңго багытталган жебе менен жакында"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Үстүндөгү өйдө багытталган жебе менен башына"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Он сегиз жашка чейинкилерге тыюу салынат символу"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Он деген баскычтын капкакчасы"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Латын чоң тамгаларын киргизүү символу"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Кичине латын тамгаларын киргизүү символу"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Сандарды киргизүү символу"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Символдорду киргизүү символу"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Латын тамгаларын киргизүү символу"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Өрт"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Электр колчырагы"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Үлүк ачкычы"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Балка"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Үлүк менен болт"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Хочо"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Тапанча"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Сыйкырдуу кристалл"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Ортосунда чекити бар алты чекиттүү жылдыз"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Башталгыч үчүн жапон символу"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Үч тиштүү эмблема"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Кара чарчы баскыч"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Ак чарчы баскыч"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Чоң кызыл тегерек"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Чоң көк тегерек"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Чоң кызгылт сары алмаз"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Чоң көк алмаз"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Кичине кызгылт сары алмаз"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Кичине көк алмаз"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Жогору караган кызыл үч бурчтук"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Төмөн караган кызыл үч бурчтук"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Жогору караган кичинекей кызыл үч бурчтук"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Төмөн караган кичинекей кызыл үч бурчтук"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Бирди көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Экини көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Үчтү көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Төрттү көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Бешти көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Алтыны көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Жетини көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Сегизди көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Тогузду көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Онду көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Он бирди көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Он экини көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Бир жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Эки жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Үч жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Төрт жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Беш жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Алты жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Жети жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Сегиз жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Тогуз жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Он жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Он бир жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Он эки жарымды көрсөткөн саат"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Фудзияма тоосу"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токио мунарасы"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Эркиндик статуясы"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Жапон карааны"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Мойай"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Арсаңдаган жүз"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Күлмүңдөгөн көздөр менен арсаңдаган жүз"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Көздөрүнөн жаш чыккыча күлгөн жүз"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Оозун ачып жылмайган бет"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Көздөрүн күлмүңдөтүп оозун ачып алып жылмайган жүз"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Оозун ачып жана муздак тер басып жылмайган жүз"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Көздөрүн чылк жумуп оозун ачып жылмайган жүз"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Кудайга ыраазы болуп жылмайган жүз"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Кытмыр жылмайган шайтан"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Көз кыскан жүз"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Күлмүңдөгөн көздөр менен жылмайган жүз"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Даамдуу тамакка тамшанган жүз"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Жеңилденген жүз"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Жүрөкчө көздөр менен жылмайган жүз"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Көз айнекчен жылмайган жүз"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Мыйыгынан жылмайган жүз"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Кайдыгер жүз"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Сезимсиз жүз"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Кызыксыз жүз"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Муздак тер баскан жүз"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Ойго баткан жүз"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Абдаарыган жүз"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Маң болгон жүз"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Өөп жаткан жүз"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Өбүү ыргыткан жүз"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Күлмүңдөгөн көздөр менен жылмайган жүз"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Көздөрүн чылк жумуп алып өөп жаткан жүз"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Тилин көрсөткөн жүз"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Тилин сунуп көз кыскан жүз"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Көздөрүн чылк жумуп алып тилин сунган жүз"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Көңүлү калган жүз"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Тынчсызданган жүз"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Ачууланган жүз"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Тултуйган жүз"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Ыйлап жаткан жүз"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Көшөргөн жүз"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Жеңишке жеткен жүз"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Көңүлү калган бирок жеңилдеген жүз"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Оозун ачып кабагын чытыган жүз"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Кыйналган жүз"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Үрөйү учкан жүз"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Зериккен жүз"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Уйкусураган жүз"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Чарчаган жүз"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Кебетесин бузган жүз"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Боздогон жүз"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Оозун ачкан жүз"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Унчукпаган бет"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Оозун ачкан муздак тер баскан жүз"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Коркуп кыйкырып жаткан жүз"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Таң калган жүз"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Бети кызарып уялган жүз"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Уктап жаткан жүз"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Башы айланган жүз"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Оозу жок жүз"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Медициналык маскачан жүз"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Күлмүңдөгөн көздөр менен арсаңдаган мышык"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Көздөрүнөн жаш чыккыча күлгөн мышык"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Оозун ачып жылмайган мышык"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Жүрөкчө көздөр менен жылмайган мышык"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Мыйыгынан жылмайган мышык"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Көздөрүн чылк жумуп өөп жаткан мышык"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Тултуйган мышык"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Ыйлап жаткан мышык"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Зериккен мышык"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Болбойт деп жаңсаган жүз"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Жарайт деп жаңсаган жүз"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Жүгүнүп жаткан адам"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Эч нерсе көрбөйм деген маймыл"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Эч нерсе укпайм деген маймыл"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Эч нерсе айтпайм деген маймыл"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Бир колун көтөрүп жыргаган адам"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Эки колун көтөрүп сүйүнгөн адам"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Кабагын бүркөгөн адам"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Тултуйган жүз"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Колдорун бооруна алган адам"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Вертолёт"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Буу локомотиви"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Темир жол вагону"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Жогорку ылдамдыктагы поезд"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Ок тумшуктуу жогорку ылдамдыктагы поезд"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Поезд"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Электропоезд"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Бекет"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвай"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Трамвай вагону"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Келе жаткан автобус"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Троллейбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобус аялдамасы"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Минибус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Тез жардам машинасы"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Өрт өчүргүч унаасы"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полиция машинасы"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Келе жаткан полиция машинасы"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Келе жаткан такси"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автоунаа"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Келе жаткан автоунаа"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Турак-жай унаасы"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Оор жүк ташуучу унаа"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Оор жүк ташыган унаа"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Жалгыз рельстүү"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Тоодогу темир жол"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Асма темир жол"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Тоо аркан жолу"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Асма аркан жолу"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Кеме"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Калактуу кайык"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Ылдам жүргөн кайык"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Жантык жол чырак"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Тик жол чырак"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Курулуш белгиси"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Полиция машинасынын айланма жарыгы"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Кармагычы бар үч бурчтуу желек"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Эшик"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Жол жок белгиси"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Чылым чегүүгө уруксат берген символ"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Чылым чегүүгө тыюу салган символ"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Таштандыны туш келди жерге ыргытпа символу"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Булгаба символу"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Таза суу символу"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ичүүгө жараксыз суу символу"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Велосипед тебүүгө тыюу салынат"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Велосипедчи"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Тоо велосипедчи"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Жөө киши"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Жөө кишилерге жүрүүгө тыюу салынган"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Балдар өтүп жатат"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Эркектер белгиси"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Кыз-келиндердин символу"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Даараткана"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Жаш балдар символу"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Ажаткана"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Даараткана"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Душ"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Ванна"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Ванна таштеги"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Паспорт текшерүү"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Бажы"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Жүктү алуу"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Жүктү калтыруу"</string>
+</resources>
diff --git a/java/res/values-ky-rKG/strings-talkback-descriptions.xml b/java/res/values-ky-rKG/strings-talkback-descriptions.xml
index 70c7792..a19b695 100644
--- a/java/res/values-ky-rKG/strings-talkback-descriptions.xml
+++ b/java/res/values-ky-rKG/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"Катуу айтылган сырсөз ачкычтарын угуу үчүн гарнитураны туташтырыңыз."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"Учурдагы текст %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"Текст киргизилген жок"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> сөзүн <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> сөзүнө оңдойт"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> авто оңдойт"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Сунуш жок"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Белгисиз белги"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Дагы символдор"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shift"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Символдор"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shift"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"Жок кылуу"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Символдор"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Тамгалар"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Сандар"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Жөндөөлөр"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Кыстырма"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Боштук"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Үн менен киргизүү"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Эмодзи"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Кайтуу"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Издөө"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Чекит"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Тилди которуштуруу"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Кийинки"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Мурунку"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Shift иштетилген"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"Caps lock иштетилди"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Символдор режими"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"Дагы символдор режими"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Тамгалар режими"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Телефон режими"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Телефон символдор режими"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Баскытоп жашырылган"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"<xliff:g id="KEYBOARD_MODE">%s</xliff:g> баскычтобу көрсөтүлүүдө"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"күнү"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"күнү жана убакыты"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"email"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"SMS/MMS"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"сан"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"телефон"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"текст"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"убакыт"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Акыркылар"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Адамдар"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Объекттер"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Жаратылыш"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Жерлер"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Символдор"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Жымыңдар"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"Баш тамга <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"Баш тамга I"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Баш тамга I, төбөсүндө чекити бар"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Белгисиз символ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Белгисиз эмодзи"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Зериккен жүз"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Уялган жүз"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Кара көз айнекчен жүз"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Таң калган жүз"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Өөп жаткан жүз"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Кабагын бүркөгөн жүз"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Альтернативалуу белгилер бар"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Альтернативалуу белгилер этибарга алынбайт"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Альтернативалуу сунуштар бар"</string>
diff --git a/java/res/values-ky-rKG/strings.xml b/java/res/values-ky-rKG/strings.xml
index cf60508..e00364f 100644
--- a/java/res/values-ky-rKG/strings.xml
+++ b/java/res/values-ky-rKG/strings.xml
@@ -20,355 +20,188 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for english_ime_input_options (3909945612939668554) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
-    <skip />
-    <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
-    <skip />
-    <!-- no translation found for sound_on_keypress (6093592297198243644) -->
-    <skip />
-    <!-- no translation found for popup_on_keypress (123894815723512944) -->
-    <skip />
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key (5915478828318774384) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
-    <skip />
-    <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
-    <skip />
-    <!-- no translation found for settings_system_default (6268225104743331821) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict (4435317977804180815) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
-    <skip />
-    <!-- no translation found for use_personalized_dicts (5167396352105467626) -->
-    <skip />
+    <string name="english_ime_input_options" msgid="3909945612939668554">"Дайндрд киргзүү парамтрлр"</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="settings_screen_preferences" msgid="2696713156722014624">"Мүмкүнчүлүктөрдү тандоо"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Каттоо эсептери жана купуялык"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Көрүнүш жана жайгашуулар"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Жаңсап терүү"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Текстти оңдоо"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Өркүндөтүлгөн"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Баскычтопту бөлүүнү иштетүү"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google тергичин шайкештирүү"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Шайкештирүү өчүрүлгөн"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Жеке сөздүгүңүздү бардык түзмөктөрүңүздө шайкештириңиз"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Азыр шайкштр"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Булут дайындарын жок кылуу"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Шайкештештирилген дайындарыңыз Google\'дан жок кылынат"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Шайкештирилген дайындарыңыз булуттан жок кылынат. Макулсузбу?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Жок кылуу"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Жокко чыгаруу"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Жеке сөздүгүңүз шайкештирилет жана Google серверлерине сакталат. Өндүрүмдөрүбүздү жакшыртууга жардамдашуу максатында сөз жыштыгынын статистикалык маалыматы топтолушу мүмкүн. Бардык маалыматты топтоо жана колдонуу "<a href="https://www.google.com/policies/privacy">"Google\'дун Купуялык Саясатына"</a>" ылайык болот."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Бул өзгөчөлүктү иштт ү-н ушул түзмөккө Google каттоо эсбн кошңз"</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">"Тил которуштуруу баскычында башка киргизүү ыкмалары дагы камтылган"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"Тил которуштуруу баскычы"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Бир нече киргизүү тили иштетилгенде көрсөтүлсүн"</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>
+    <string name="settings_system_default" msgid="6268225104743331821">"Демейки тутум"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Байланш ысымдарн сунуштоо"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Сунуштар жана оңдоолор үчүн Байланыштардагы ысымдарды пайдалануу"</string>
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"Жекечелештирилгн сунуштр"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"Жакшыртуу <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <!-- no translation found for use_double_space_period (8781529969425082860) -->
-    <skip />
-    <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
-    <skip />
-    <!-- no translation found for auto_cap (1719746674854628252) -->
-    <skip />
-    <!-- no translation found for auto_cap_summary (7934452761022946874) -->
-    <skip />
-    <!-- no translation found for edit_personal_dictionary (3996910038952940420) -->
-    <skip />
-    <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
-    <skip />
-    <!-- no translation found for main_dictionary (4798763781818361168) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
-    <skip />
-    <!-- no translation found for auto_correction (7630720885194996950) -->
-    <skip />
-    <!-- no translation found for auto_correction_summary (5625751551134658006) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) -->
-    <skip />
-    <!-- no translation found for bigram_prediction (1084449187723948550) -->
-    <skip />
-    <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
-    <skip />
-    <!-- no translation found for gesture_input (826951152254563827) -->
-    <skip />
-    <!-- no translation found for gesture_input_summary (9180350639305731231) -->
-    <skip />
-    <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware (2078291600664682496) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware_summary (4371385818348528538) -->
-    <skip />
-    <!-- no translation found for voice_input (3583258583521397548) -->
-    <skip />
-    <!-- no translation found for voice_input_disabled_summary (8141750303464726129) -->
-    <skip />
-    <!-- no translation found for configure_input_method (373356270290742459) -->
-    <skip />
-    <!-- no translation found for language_selection_title (1651299598555326750) -->
-    <skip />
-    <!-- no translation found for send_feedback (1780431884109392046) -->
-    <skip />
-    <!-- no translation found for select_language (3693815588777926848) -->
-    <skip />
-    <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
-    <skip />
-    <!-- no translation found for has_dictionary (6071847973466625007) -->
-    <skip />
-    <!-- no translation found for keyboard_layout (8451164783510487501) -->
-    <skip />
-    <!-- no translation found for subtype_en_GB (88170601942311355) -->
-    <skip />
-    <!-- no translation found for subtype_en_US (6160452336634534239) -->
-    <skip />
-    <!-- no translation found for subtype_es_US (5583145191430180200) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_GB (1931018968641592304) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_US (8809311287529805422) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_es_US (510930471167541338) -->
-    <skip />
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <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 />
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
-    <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
-    <skip />
-    <!-- no translation found for add_style (6163126614514489951) -->
-    <skip />
-    <!-- no translation found for add (8299699805688017798) -->
-    <skip />
-    <!-- no translation found for remove (4486081658752944606) -->
-    <skip />
-    <!-- no translation found for save (7646738597196767214) -->
-    <skip />
-    <!-- no translation found for subtype_locale (8576443440738143764) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
-    <skip />
-    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
-    <skip />
-    <!-- no translation found for enable (5031294444630523247) -->
-    <skip />
-    <!-- no translation found for not_now (6172462888202790482) -->
-    <skip />
-    <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
-    <skip />
-    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
-    <skip />
-    <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_confirm_install_message (4782116251651288054) -->
-    <skip />
-    <!-- no translation found for error (8940763624668513648) -->
-    <skip />
-    <!-- no translation found for button_default (3988017840431881491) -->
-    <skip />
-    <!-- no translation found for setup_welcome_title (6112821709832031715) -->
-    <skip />
-    <!-- no translation found for setup_welcome_additional_description (8150252008545768953) -->
-    <skip />
-    <!-- no translation found for setup_start_action (8936036460897347708) -->
-    <skip />
-    <!-- no translation found for setup_next_action (371821437915144603) -->
-    <skip />
-    <!-- no translation found for setup_steps_title (6400373034871816182) -->
-    <skip />
-    <!-- no translation found for setup_step1_title (3147967630253462315) -->
-    <skip />
-    <!-- no translation found for setup_step1_instruction (2578631936624637241) -->
-    <skip />
-    <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
-    <skip />
-    <!-- no translation found for setup_step1_action (4366513534999901728) -->
-    <skip />
-    <!-- no translation found for setup_step2_title (6860725447906690594) -->
-    <skip />
-    <!-- no translation found for setup_step2_instruction (9141481964870023336) -->
-    <skip />
-    <!-- no translation found for setup_step2_action (1660330307159824337) -->
-    <skip />
-    <!-- no translation found for setup_step3_title (3154757183631490281) -->
-    <skip />
-    <!-- no translation found for setup_step3_instruction (8025981829605426000) -->
-    <skip />
-    <!-- no translation found for setup_step3_action (600879797256942259) -->
-    <skip />
-    <!-- no translation found for setup_finish_action (276559243409465389) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon (5008028590593710830) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) -->
-    <skip />
-    <!-- no translation found for app_name (6320102637491234792) -->
-    <skip />
-    <!-- no translation found for dictionary_provider_name (3027315045397363079) -->
-    <skip />
-    <!-- no translation found for dictionary_service_name (6237472350693511448) -->
-    <skip />
-    <!-- no translation found for download_description (6014835283119198591) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_title (8091417676045693313) -->
-    <skip />
-    <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_summary (5305694987799824349) -->
-    <skip />
-    <!-- no translation found for user_dictionaries (3582332055892252845) -->
-    <skip />
-    <!-- no translation found for default_user_dict_pref_name (1625055720489280530) -->
-    <skip />
-    <!-- no translation found for dictionary_available (4728975345815214218) -->
-    <skip />
-    <!-- no translation found for dictionary_downloading (2982650524622620983) -->
-    <skip />
-    <!-- no translation found for dictionary_installed (8081558343559342962) -->
-    <skip />
-    <!-- no translation found for dictionary_disabled (8950383219564621762) -->
-    <skip />
-    <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) -->
-    <skip />
-    <!-- no translation found for no_dictionaries_available (8039920716566132611) -->
-    <skip />
-    <!-- no translation found for check_for_updates_now (8087688440916388581) -->
-    <skip />
-    <!-- no translation found for last_update (730467549913588780) -->
-    <skip />
-    <!-- no translation found for message_updating (4457761393932375219) -->
-    <skip />
-    <!-- no translation found for message_loading (5638680861387748936) -->
-    <skip />
-    <!-- no translation found for main_dict_description (3072821352793492143) -->
-    <skip />
-    <!-- no translation found for cancel (6830980399865683324) -->
-    <skip />
-    <!-- no translation found for go_to_settings (3876892339342569259) -->
-    <skip />
-    <!-- no translation found for install_dict (180852772562189365) -->
-    <skip />
-    <!-- no translation found for cancel_download_dict (7843340278507019303) -->
-    <skip />
-    <!-- no translation found for delete_dict (756853268088330054) -->
-    <skip />
-    <!-- no translation found for should_download_over_metered_prompt (1583881200688185508) -->
-    <skip />
-    <!-- no translation found for download_over_metered (1643065851159409546) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (2176209579313941583) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_title (4583842811218581658) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_description (1075194169443163487) -->
-    <skip />
-    <!-- no translation found for toast_downloading_suggestions (6128155879830851739) -->
-    <skip />
-    <!-- no translation found for version_text (2715354215568469385) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
-    <skip />
-    <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
-    <skip />
+    <string name="use_double_space_period" msgid="8781529969425082860">"Эки жолу боштук чекити"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Боштук баскычы эки жолу таптлгнда аркаснда боштгу бар чекит коюлт"</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_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>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Күжүрмөн"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Аябай күжүрмөн"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"Кийинки сөздү сунуштоо"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"Сунуштоодо мурунку сөздү пайдалануу"</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="gesture_space_aware" msgid="2078291600664682496">"Сөз айкашын жаңсоо"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Боштук баскычын сылоо менен боштуктарды жаңсап киргизиңиз"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Үн менен киргизүү баскычы"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Үн менен киргизүү ыкмаларынын бири да иштетилген эмес. Тил &amp; киргизүү жөндөөлөрүн текшериңиз."</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Дайндрд киргзүү ыкмалрн конфигрцлоо"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Тилдер"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Жардам &amp; жооп пикир"</string>
+    <string name="select_language" msgid="5709487854987078367">"Тилдер"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Сактоо үчүн кайра тийип коюңуз"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Сактоо үчүн бул жерди басыңыз"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"Сөздүк бар"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"Баскычтоп темасы"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Каттоо эсептерин которуштуруу"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Бир дагы каттоо эсеби тандалган жок"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Учурда <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> колдонулууда"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Жокко чыгаруу"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Чыгуу"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Колдонуу үчүн каттоо эсебин тандаңыз"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"Англисче (UK)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"Англисче (US)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"Испанча (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Сербче (Латын)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англисче (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англисче (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испанча (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сербче (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Салттык)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Чакан)"</string>
+    <string name="subtype_no_language" msgid="7137390094240139495">"Тил жок (Алфавит)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Алфавит (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Алфавит (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Алфавит (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Алфавит (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Алфавит (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Алфавит (PC)"</string>
+    <string name="subtype_emoji" msgid="7483586578074549196">"Эмодзи"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"Баскычтоп темасы"</string>
+    <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_keypress_vibration_duration_settings" msgid="7918341459947439226">"Басылган баскычтын дирлдөө узактгы"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Басылган баскычтын үнүнүн катуулугу"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Баскычты көпкө басууну кечиктирүү"</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">"Тил &amp; Киргизүү жөндөөлөрүңүздөн \"<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> буга чейин эле Тил &amp; Киргизүү жөндөөлөрүндө иштетилгендиктен бул кадам аткарылды деск болт. Кийинкисине өтө бериңз!"</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">"Эми бардык сүйүктүү колдонмолоруңузда <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="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="5638680861387748936">"Жүктөлүүдө…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Негизги сөздүк"</string>
+    <string name="cancel" msgid="6830980399865683324">"Жокко чыгаруу"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"Жөндөөлөр"</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="1583881200688185508">"Мобилдик түзмөгүңүздөгү тандалган тилде сөздүк бар.&lt;br/&gt; Терүү аракетиңизди жакшыртуу &lt;b&gt;үчүн&lt;/b&gt; <xliff:g id="LANGUAGE_NAME">%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; менюсундагы уюлдук түзмөгүңүздүн менюсундагы <b>Тил &amp; киргизүү</b> бөлүмүнө өтүп, сөздүктөрдү жүктөп алсаңыз же алып салсаңыз болот."</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="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> тилинде сөздүк бар"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Карап көрүү жана жүктөп алуу үчүн басыңыз"</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Жүктөлүп алынууда: <xliff:g id="LANGUAGE_NAME">%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">"OK"</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">"Кошумча кыска жол"</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/values-lo-rLA/strings-emoji-descriptions.xml b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
index 0747fa6..335fc19 100644
--- a/java/res/values-lo-rLA/strings-emoji-descriptions.xml
+++ b/java/res/values-lo-rLA/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"​ຄຸ​ກ​ກີ້"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"​ຊັອກ​ໂກ​ແລັດບາ"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"ແຄນດີ້"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"​ໂລ​ລິ​ປັອບ"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"ເຂົ້າໜົມອົມຍິ້ມ"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"​ຄັ​ສ​ຕາດ"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ໝໍ້​ນ້ຳ​ເຜິ້ງ"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ຊັອດ​ເຄັກ"</string>
diff --git a/java/res/values-lo-rLA/strings-talkback-descriptions.xml b/java/res/values-lo-rLA/strings-talkback-descriptions.xml
index 187b63a..e421dcc 100644
--- a/java/res/values-lo-rLA/strings-talkback-descriptions.xml
+++ b/java/res/values-lo-rLA/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"ບໍ່ມີ​ການໃສ່​ຂໍ້ຄວາມ"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ແກ້​ໄຂ​ <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ເປັນ <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ດຳ​ເນີນ​ການ​ແກ້​ໄຂ​ອັດ​ຕະ​ໂນ​ມັດ"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"ບໍ່​ມີ​ຄຳ​ແນະ​ນຳ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"​ໂຕ​ອັກ​ສອນ​ທີ່ບໍ່​ຮູ້​ຈັກ"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"​ສັນ​ຍາ​ລັກ​ເພີ່ມ​ເຕີມ"</string>
@@ -65,7 +66,7 @@
     <string name="keyboard_mode_time" msgid="8558297845514402675">"ເວລາ"</string>
     <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
     <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"ຫາ​ກໍ​ໃຊ້"</string>
-    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"​ຄົນ"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"ຜູ່​ຄົນ"</string>
     <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"​ວັດ​ຖຸ"</string>
     <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"ທຳມະຊາດ"</string>
     <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"ສະຖານທີ່"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"​ໂຕພິມ​ໃຫຍ່ I ມີ​ຈ້ຳ​ເມັດ​ຢູ່​ເທິງ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"ສັນ​ຍາ​ລັກ​ທີ່ບໍ່​ຮູ້​ຈັກ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"ອີ​ໂມ​ຈິ​ທີ່ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"ໜ້າ​ຮູ້​ສຶກເບື່ອ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"​ໜ້າ​ຮູ້​ສຶກ​ອາຍ"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"​ໜ້າ​ໃສ່​ແວ່ນ​ຕາ​ດຳ"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"​ໜ້າ​ຕົກ​ໃຈ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"​ໜ້າ​ຈູບ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"​ໜ້າ​ບູດ"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"​ມີ​ໂຕ​ອັກ​ສອນ​ສຳ​ຮອງ​ໃຫ້​ເລືອກ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"​ປິດ​ໂຕ​ອັກ​ສອນ​ສຳ​ຮອງ​ແລ້ວ"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"​ມີ​ຄຳ​ແນະ​ນຳ​ສຳ​ຮອງ​ໃຫ້​ເລືອກ"</string>
diff --git a/java/res/values-lo-rLA/strings.xml b/java/res/values-lo-rLA/strings.xml
index b0e090a..521ff5d 100644
--- a/java/res/values-lo-rLA/strings.xml
+++ b/java/res/values-lo-rLA/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"​ການ​ຕັ້ງ​ຄ່າ​ການ​ປ້ອນ​ຂໍ້​ມູນ"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"​ຮູບ​ແບບ​ໜ້າ​ຕາ"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"​ໂຕ​ເລືອກ​ລະ​ບົບຫຼາຍ​ພາ​ສາ"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"​ການ​ຕັ້ງ​ຄ່າ​ການ​ພິມ​ດ້ວຍ​ທ່າ​ທາງ"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"​​ການ​ຕັ້ງ​ຄ່າ"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"ບັນຊີ &amp; ​ຄວາມ​ເປັນ​ສ່ວນ​ຕົວ"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"​ລັກ​ສະ​ນະ &amp; ໂຄງ​ຮ່າງ"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"​ກາ​ນ​ພິມ​ແບບ​ລາກ​ນິ້ວ"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"​ການ​ແປງ​ຄຳ​ໃຫ້​ຖືກ​ຕ້ອງ"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"​ຂັ້ນ​ສູງ"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"ຮູບແບບສີສັນ"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"ເປີດ​ນຳ​ໃຊ້​ແປ້ນ​ພິມ​ແຍກ​ຕົວ"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"ການ​ຊິງ​ຄ໌​ແປ້ນ​ພິມ Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"ຊິງ​ຄ໌​ເປ​ີດ​ແລ້ວ"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ຊິງ​ຄ໌​ພົດ​ຈະ​ນາ​ນຸ​ກົມ​ສ່ວນ​ຕົວ​ຂອງ​ທ່ານ​ໃນ​ທຸກ​ອຸ​ປະ​ກອນ"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ຊິງ​ຄ໌ດຽວນີ້"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ລຶບ​ຂໍ້​ມູນ​ຄ​ລາວ"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"ລຶບ​ຂໍ້​ມູນ​ທີ່​ຊິງ​ຄ໌​ແລ້ວ​ຂອງ​ທ່ານ​ຈາກ Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ຂໍ້​ມູນ​ທີ່​ຊິງ​ຄ໌​ແລ້ວ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ລຶບ​ໄປ​ຈາກ​ຄ​ລາວ. ທ່ານ​ແນ່​ໃຈ​ບໍ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ລຶບ"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ຍົກເລີກ"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"ພົດ​ຈະ​ນາ​ນຸ​ກົມ​ສ່ວນ​ຕົວ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ຊິງ​ຄ໌ ແລະ​ສຳ​ຮອງ​ໄປ​ໃສ່​ເຊີບ​ເວີ Google. ຂໍ້​ມູນ​ສະ​ຖິ​ຕິ​ຂອງ​ຄວາມ​ຖີ່​ຄຳ​ເວົ້າ​ອາດ​ຈະ​ຖືກ​ເກັບ​ກຳ ເພື່ອ​ຊ່ວຍ​ປັບ​ປຸງ​ຜະ​ລິດ​ຕະ​ພັນ​ຂອງ​ທ່ານ. ການ​ເກັບ​ກຳ ແລະ​ການ​ນຳ​ໃຊ້​ທຸກ​ຂໍ້​ມູນ​ຈະ​ເປັນ​ໄປ​ຕາມ "<a href="https://www.google.com/policies/privacy">"ນະ​ໂຍ​ບາຍ​ຄວາມ​ເປັນ​ສ່ວນ​ຕົວ​ຂອງ Googl"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ກະ​ລຸ​ນາ​ເພີ່ມ​ບັນ​ຊີ Google ໃສ່​ອຸ​ປະ​ກອນ​ນີ້ ເພື່ອ​ເປີດ​ໃຊ້​ງານ​ຄຸນ​ສົມ​ບັດ​ນີ້"</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">"ໂຕປ່ຽນພາສາເປັນທັງໂຕປ່ຽນຮູບແບບການປ້ອນຂໍ້ມູນເຊັ່ນກັນ"</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">"ສະແດງໂຕບົ່ງບອກການສະໄລ້"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"ສະແດງແນວທາງໃນຂະນະທີ່ສະໄລ້ຈາກ Shift ຫຼື ປຸ່ມເຄື່ອງໝາຍ"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"ປຸ່ມປ້ອນຂໍ້ມູນດ້ວຍສຽງ"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ບໍ່ມີວິທີການປ້ອນສຽງເປີດນໍາໃຊ້. ໃຫ້ກວດເບິ່ງການຕັ້ງຄ່າໃນເມນູ ພາສາ &amp; ການປ້ອນຂໍ້ມູນ."</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="language_selection_title" msgid="3666971864764478269">"ພາ​ສາ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ຊ່ວຍ​ເຫຼືອ &amp; ຄຳ​ຕິ​ຊົມ"</string>
+    <string name="select_language" msgid="5709487854987078367">"ພາ​ສາ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"ກົດອີກຄັ້ງເພື່ອບັນທຶກ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"ແຕະ​ບ່ອນ​ນີ້​ເພື່ອ​ບັນ​ທຶກ"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ມີວັດຈະນານຸກົມ"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ສີສັນແປ້ນພິມ"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ສະລັບບັນຊີ"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"​ບໍ່​ໄດ້​ເລືອກ​ບັນ​ຊີ​ເທື່ອ"</string>
+    <string name="account_selected" msgid="2846876462199625974">"ຕອນ​ນີ້​ກຳ​ລັງ​ໃຊ້ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ຕົກລົງ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"​ຍົກ​ເລີກ"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ອອກຈາກລະບົບ"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"​ເລືອກ​ບັນ​ຊີ​ທີ່​ຈະ​ໃຊ້"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ອັງກິດ (ສະຫະລາດຊະອານາຈັກ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ອັງກິດ (ສະຫະລັດຯ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ສະເປນ (ອາເມລິກາ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ຮິງ​ລິສ"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"ເຊີ​ບຽນ (​ລາ​ຕິນ)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ອັງ​ກິດ (ສະ​ຫະ​ລາດ​ຊະ​ອາ​ນາ​ຈັກ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ອັງ​ກິດ (ສະ​ຫະ​ລັດຯ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ສະ​ແປນ​ນິດ (ສະ​ຫະ​ລັດຯ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ຮິງ​ລິສ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ເຊີ​ບຽນ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ດັ້ງ​ເດີມ)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ຊິ​ຣິວ​ລິກ)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ລາ​ຕິນ)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ກະ​ທັດ​ຮັດ)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ບໍ່ມີພາສາ (ໂຕອັກສອນ)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ໂຕອັກສອນ (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ໂຕອັກສອນ (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ໂຕອັກສອນ (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ອີໂມຈິ"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"ຮູບ​ແບບ​ສີ​ສັນ​ແປ້ນ​ພິມ"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"​ຂາວ​ແຈ້ງ"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"ຟ້າ​ແຈ​້ງ"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"​ສະ​ສານ​ມືດ"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"​ສະ​ສານ​ແຈ້ງ"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"ຮູບແບບການປ້ອນຂໍ້ມູນສ່ວນຕົວ"</string>
     <string name="add_style" msgid="6163126614514489951">"ເພີ່ມຮູບແບບ"</string>
     <string name="add" msgid="8299699805688017798">"ເພີ່ມ"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"ຕິດ​ຕັ້ງ​ໄຟ​ລ໌​ນີ້​ສຳ​ລັບ <xliff:g id="LANGUAGE_NAME">%s</xliff:g> ແທ້ບໍ່??"</string>
-    <string name="error" msgid="8940763624668513648">"ມີຂໍ້ຜິດພາດເກີດຂຶ້ນ"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ໄລຍະເວລາຂອງການກົດປຸ່ມ"</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">"ດ້ວຍການພິມແບບ Gesture"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ຕອນນີ້ທ່ານສາມາດພິມໃນແອັບຯທີ່ທ່ານມັກໄດ້ທຸກແອັບຯດ້ວຍ <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">"ສະແດງໄອຄອນຂອງແອັບຯໃນ Launcher"</string>
     <string name="app_name" msgid="6320102637491234792">"ຜູ່​ສະ​ຫນອງ​ວັດຈະ​ນາ​ນຸ​ກົມ"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ຜູ່​ສະ​ຫນອງ​ວັດຈະ​ນາ​ນຸ​ກົມ"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"ບໍລິການວັດຈະນານຸກົມ"</string>
diff --git a/java/res/values-lt/strings-emoji-descriptions.xml b/java/res/values-lt/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..afe9ac0
--- /dev/null
+++ b/java/res/values-lt/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Autorių teisių simbolis"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Registruoto prekės ženklo simbolis"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Du šauktukai"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Šauktukas ir klaustukas"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Prekės ženklo simbolis"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informacijos šaltinis"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Rodyklė į kairę ir dešinę"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Rodyklė į viršų ir apačią"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Rodyklė į viršų ir kairę"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Rodyklė į viršų ir dešinę"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Rodyklė į apačią ir dešinę"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Rodyklė į apačią ir kairę"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Lenkta rodyklė į kairę"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Lenkta rodyklė į dešinę"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Laikrodis"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Smėlio laikrodis"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Du juodi trikampiai į dešinę"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Du juodi trikampiai į kairę"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Du juodi trikampiai į viršų"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Du juodi trikampiai į apačią"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Žadintuvas"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Smėlio laikrodis su byrančiu smėliu"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Lotyniška didžioji raidė M apskritime"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Juodas mažas kvadratas"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Baltas mažas kvadratas"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Juodas trikampis į dešinę"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Juodas trikampis į kairę"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Baltas vidutinio storio kvadratas"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Juodas vidutinio storio kvadratas"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Baltas vidutinio storio mažas kvadratas"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Juodas vidutinio storio mažas kvadratas"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Juoda saulė su spinduliais"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Debesis"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Juodas telefonas"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Apklausos langelis su varnele"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Skėtis su lietaus lašais"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Karštas gėrimas"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Baltas į viršų rodantis pirštas"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Baltas besišypsantis veidas"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Avinas"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tauras"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Dvyniai"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Vėžys"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Liūtas"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Mergelė"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Svarstyklės"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpionas"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Šaulys"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Ožiaragis"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vandenis"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Žuvys"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Juodų pikų korta"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Juodų kryžių korta"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Juodų širdžių korta"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Juodų būgnų korta"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Karštieji šaltiniai"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Universalus juodas perdirbimo simbolis"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Invalido vežimėlio simbolis"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Inkaras"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Įspėjimo ženklas"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Aukštos įtampos ženklas"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Vidutinio dydžio baltas apskritimas"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Vidutinio dydžio juodas apskritimas"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futbolo kamuolys"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beisbolo kamuoliukas"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Senis besmegenis be sniego"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Saulė už debesies"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Gyvatnešis"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Įeiti / įvažiuoti draudžiama"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Bažnyčia"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontanas"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Vėliavėlė skylutėje"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Burlaivis"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Palapinė"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Kuro siurblys"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Juodos žirklės"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Balta stora žymėjimo varnelė"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Lėktuvas"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Vokas"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Pakeltas kumštis"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Pakelta ranka"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Pergalės ženklą rodanti ranka"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Pieštukas"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Juoda plunksna"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Stora žymėjimo varnelė"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Storas daugybos ženklas x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Žėrėjimas"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Aštuoniakampė žvaigždutė"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Aštuoniakampė juoda žvaigždė"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snaigė"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Kibirkštėlė"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kryžiuko ženklas"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Neigiamas kryžiuko ženklas kvadrate"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Juodas klaustuko ornamentas"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Baltas klaustuko ornamentas"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Baltas šauktuko ornamentas"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Storas šauktukas"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Stora juoda širdelė"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Storas pliuso ženklas"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Storas minuso ženklas"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Storas dalybos ženklas"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Juoda rodyklė į dešinę"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Kilpelė"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dviguba kilpelė"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Rodyklė, nukreipta į kairę ir užlenkta į viršų"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Rodyklė, nukreipta į dešinę ir nulenkta žemyn"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Juoda rodyklė į kairę"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Juoda rodyklė aukštyn"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Juoda rodyklė žemyn"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Juodas didelis kvadratas"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Baltas didelis kvadratas"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Balta vidutinė žvaigždė"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Storas didelis apskritimas"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Vingiuotas brūkšnys"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Dalių apkeitimo ženklas"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Pasveikinimo hieroglifas apskritime"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Paslapties hieroglifas apskritime"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Madžongo kaladėlė su raudonu drakonu"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Žaidimo korta su juodu juokdariu"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A kraujo grupė"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B kraujo grupė"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"O kraujo grupė"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Stovėjimo aikštelė"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB kraujo grupė"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL kvadrate"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"COOL kvadrate"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"FREE kvadrate"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID kvadrate"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"NEW kvadrate"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG kvadrate"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK kvadrate"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS kvadrate"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"UP ir šauktukas kvadrate"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS kvadrate"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"KATAKANA KOKO kvadrate"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"KATAKANA SA kvadrate"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Nemokamas paslaugas reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Rezervuotą vietą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Draudimą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Laisvą vietą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Sutikimą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Visiškai užimtą vietą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Mokamas paslaugas reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Mėnesio laikotarpį reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Prašymą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Nuolaidą reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Darbo valandas reiškiantis hieroglifas kvadrate"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Pranašumą reiškiantis hieroglifas apskritime"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Sutikimą reiškiantis hieroglifas apskritime"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciklonas"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Tirštas rūkas"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Suskleistas skėtis"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Žvaigždėta naktis"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Saulėtekis virš kalnų"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Saulėtekis"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Sutemos virš miesto"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Saulėlydis virš pastatų"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Vaivorykštė"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Tiltas naktį"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vandens banga"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Ugnikalnis"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Paukščių Takas"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Žemės rutulys su Europos ir Afrikos žemynais"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Žemės rutulys su Šiaurės ir Pietų Amerikos žemynais"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Žemės rutulys su Azijos ir Australijos žemynais"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Žemės rutulys su dienovidiniais"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Jaunaties simbolis"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Priešpilnio (pradžios) simbolis"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Priešpilnio (pirmo fazės ketvirčio) simbolis"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Priešpilnio (pabaigos) simbolis"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Pilnaties simbolis"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Delčios (pradžios) simbolis"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Delčios (paskutinio fazės ketvirčio) simbolis"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Delčios (pabaigos) simbolis"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Pusmėnulis"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Jaunas mėnulis su veidu"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Priešpilnio mėnulis su veidu"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Delčios mėnulis su veidu"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Pilnaties mėnulis su veidu"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Saulė su veidu"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Žėrinti žvaigždė"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Krintanti žvaigždė"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kaštainis"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Daigas"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Amžinai žaliuojantis medis"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Lapuotis"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmė"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktusas"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulpė"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Vyšnių žiedai"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rožė"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Kinrožė"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Saulėgrąža"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Žiedai"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kukurūzo burbuolė"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Ryžių varpa"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Žolelė"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Keturlapis dobilas"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Klevo lapas"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Nukritęs lapas"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Lapas vėjyje"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Grybas"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Pomidoras"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Baklažanas"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Vynuogės"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melionas"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Arbūzas"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarinas"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citrina"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Bananas"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananasas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Raudonas obuolys"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Žalias obuolys"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Kriaušė"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Persikas"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Vyšnios"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Braškė"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Mėsainis"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Picos gabalėlis"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Mėsa ant kaulo"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Paukščio šlaunelė"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Ryžių paplotėlis"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Ryžių rutuliukas"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Išvirti ryžiai"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Ryžiai su kariu"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Makaronų sriubos dubenėlis"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagečiai"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Duona"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Gruzdintos bulvytės"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Kepta saldžioji bulvė"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sušis"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Kepta krevetė"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Žuvies pyragėlis su išpieštu sūkurio simboliu"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Minkšti ledai"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Susmulkintas šaldytas vanduo"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Ledai"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Spurga"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Sausainis"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Šokolado plytelė"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Saldainis"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Saldus kremas"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Medaus puodynė"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Trapus pyragas"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento dėžutė"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Puodas su maistu"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Valgio gaminimas"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Šakutė ir peilis"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Puodelis be ąselės"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakės butelis ir puodelis"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vyno taurė"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kokteilio taurė"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropinis gėrimas"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Alaus bokalas"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Susidaužiantys alaus bokalai"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Kūdikio buteliukas"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Kaspinas"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Supakuota dovana"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Gimtadienio tortas"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Helovino moliūgas"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Kalėdų eglutė"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Kalėdų Senis"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fejerverkai"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Šaltoji ugnelė"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balionas"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfeti šaudyklė"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfeti kamuolys"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata medis"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Sukryžiuotos vėliavos"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Dekoracija iš pušies"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japoniškos lėlės"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Karpio vėtrungė"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vėjo varpeliai"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Mėnesienos stebėjimo ceremonija"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Mokyklinė kuprinė"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Mokyklos baigimo kepurėlė"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karuselės arkliukas"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Apžvalgos ratas"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Linksmieji kalneliai"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Meškerė ir žuvis"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofonas"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmavimo kamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kinas"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Ausinė"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Dailininko paletė"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Skrybėlė cilindras"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirko palapinė"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Bilietas"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Kino kadro pranešimo lenta"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Scenos menas"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Vaizdo žaidimas"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Smūgis tiesiai į taikinį"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Žaidimų automatas"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliardas"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Žaidimų kauliukas"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Kėgliai"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Kortos su gėlėmis"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Muzikos nata"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Kelios muzikos natos"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofonas"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Instrumento klaviatūra"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trimitas"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Smuikas"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitūra"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Bėgimo marškinėliai su juosta"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Teniso raketė ir kamuoliukas"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Slidės ir slidžių batai"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Krepšinio kamuolys ir lankas"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Vėliava langeliais"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snieglentininkas"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Bėgikas"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Banglentininkas"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Prizas"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Žirgų lenktynės"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikietiškas futbolas"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Regbis"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Plaukikas"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Namas"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Namas su sodu"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Biurų pastatas"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japoniškas paštas"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europietiškas paštas"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Ligoninė"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bankas"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomatas"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Viešbutis"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Meilės viešbutis"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Visą parą dirbanti parduotuvė"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Mokykla"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Prekybos centras"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Gamykla"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Popierinis žibintas"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japoniška pilis"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europietiška pilis"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Žiurkė"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Pelė"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Jautis"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Naminis buivolas"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Karvė"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardas"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Triušis"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Katė"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drakonas"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodilas"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Banginis"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Sraigė"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Gyvatė"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Arklys"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Avinas"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Ožys"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Avis"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Beždžionė"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gaidys"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Višta"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Šuo"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Kiaulė"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Šernas"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Dramblys"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Aštuonkojis"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Susisukusi kriauklė"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Vabalas"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Skruzdėlė"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Bitė"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Boružė"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Žuvis"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropinė žuvis"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Fugu"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Vėžlys"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Išsiritęs viščiukas"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Viščiukas"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Atsisukęs snapu viščiukas"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Paukštis"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvinas"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudelis"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Vienakupris kupranugaris"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Dvikupris kupranugaris"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfinas"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Pelės snukutis"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Karvės snukis"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigro snukis"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Triušio snukutis"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Katės snukutis"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Drakono snukis"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Purškiantis banginis"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Arklio snukis"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Beždžionės snukutis"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Šuns snukutis"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Kiaulės snukis"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Varlės snukutis"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Žiurkėno snukutis"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Vilko snukis"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Meškos snukis"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandos snukutis"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Šnipas"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pėdutės"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Akys"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ausis"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nosis"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Burna"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Liežuvis"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Balta aukštyn pirštu rodanti ranka"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Balta žemyn pirštu rodanti ranka"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Balta į kairę pirštu rodanti ranka"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Balta į dešinę pirštu rodanti ranka"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Kumščio ženklas"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Mojančios rankos ženklas"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"GERAI ženklas rankomis"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Aukštyn pakelto nykščio ženklas"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Žemyn nuleisto nykščio ženklas"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Plojančių rankų ženklas"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Atvirų rankų ženklas"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Karūna"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Moteriška skrybėlė"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Akiniai"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kaklaraištis"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Marškinėliai"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Džinsai"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Suknelė"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikinis"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Moteriški drabužiai"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Piniginė"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Rankinė"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Krepšelis"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Vyriškas batas"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportinis batelis"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Aukštakulnis batelis"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Moteriška basutė"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Moteriški batai"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Pėdos"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Biusto siluetas"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Biustų siluetai"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Berniukas"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Mergaitė"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Vyras"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Moteris"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Šeima"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Vyras ir moteris, susikibę rankomis"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Du vyrai, susikibę rankomis"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dvi moterys, susikibusios rankomis"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policininkas"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Moteris su kiškio ausytėmis"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Nuotaka su nuometu"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Šviesių plaukų žmogus"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Vyras su gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Vyras su turbanu"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Senukas"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Senutė"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Kūdikis"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Statybininkas"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesė"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japoniška pabaisa"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japoniškas demonas"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Vaiduoklis"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Angeliukas"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Ateivis iš kitos planetos"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstras ateivis"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Velniūkštis"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Kaukolė"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Informacinio skyriaus darbuotojas"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Apsaugininkas"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Šokėjas"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lūpų dažai"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nagų lakas"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Veido masažas"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Plaukų kirpimas"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Kirpėjo suktukas"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Švirkštas"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Tabletė"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Bučinio žymė"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Meilės laiškas"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Žiedas"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Brangakmenis"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bučinys"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Puokštė"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Porelė su širdele"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Vestuvės"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Plakanti širdelė"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Sudaužyta širdelė"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dvi širdelės"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Žėrinti širdelė"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Didėjanti širdelė"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Širdelė su strėle"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Mėlyna širdelė"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Žalia širdelė"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Geltona širdelė"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Rožinė širdelė"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Širdelė su kaspinu"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Besisukančios širdelės"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Širdelės dekoracija"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Deimanto forma su tašku viduje"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektros lemputė"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Pykčio simbolis"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Miego simbolis"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Susidūrimo simbolis"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Srūvančio prakaito simbolis"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Lašelis"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Sukeltų dulkių simbolis"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Išmatų krūvelė"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Paryškinti bicepsai"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Apsvaigimo simbolis"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Kalbos debesėlis"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Minčių debesėlis"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Balta gėlė"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Šimto balų simbolis"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Pinigų maišas"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valiutos kursas"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Storas dolerio ženklas"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredito kortelė"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknotas su jenos ženklu"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknotas su dolerio ženklu"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknotas su euro ženklu"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknotas su svaro ženklu"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Pinigai su sparnais"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Didėjimo tendencijos diagrama ir jenos ženklas"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sėdynė"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Asmeninis kompiuteris"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Portfelis"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Mini diskas"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskelis"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optinis diskas"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Failų aplankas"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Atviras failų aplankas"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Užsirietęs puslapis"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Puslapis viršutine puse"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendorius"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Nuplėšiamas kalendorius"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kortelių laikiklis"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Didėjimo tendencijos diagrama"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Mažėjimo tendencijos diagrama"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Juostinė diagrama"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Segtuvas"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Smeigtukas"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Apvalus smeigtukas"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Sąvaržėlė"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Tiesi liniuotė"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trikampė liniuotė"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Žymių skirtukai"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Sąskaitų knyga"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Užrašų knygelė"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Užrašų knygelė su dekoratyviniu viršeliu"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Užversta knyga"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Atverta knyga"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Žalia knyga"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Mėlyna knyga"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranžinė knyga"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Knygos"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Vardo ir pavardės ženklelis"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Ritinys"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Atmintinė"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefono ragelis"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pranešimų gaviklis"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fakso aparatas"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Palydovinė antena"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Viešasis garsiakalbis"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ruporas"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Siunčiamų laiškų dėklas"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Gautų laiškų dėklas"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakuotė"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"El. pašto simbolis"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Įeinantis vokas"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Vokas su žemyn nukreipta rodykle virš jo"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Uždaryta pašto dėžutė su nuleista vėliava"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Uždaryta pašto dėžutė su pakelta vėliava"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Atidaryta pašto dėžutė su pakelta vėliava"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Atidaryta pašto dėžutė su nuleista vėliava"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Pašto dėžutė"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Pašto ragas"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Laikraštis"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobilusis telefonas"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobilusis telefonas su į dešinę nukreipta rodykle kairėje"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibravimo režimas"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Išjungtas mobilusis telefonas"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Jokių mobiliųjų telefonų"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Signalo stiprumo juostos"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoaparatas"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Vaizdo kamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizorius"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radijas"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Vaizdajuostė"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Susipynusios į dešinę nukreiptos rodyklės"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Laikrodžio rodyklės kryptimis nukreiptos rodyklės į dešinę ir kairę, sudarančios apskritimą"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Laikrodžio rodyklės kryptimis nukreiptos rodyklės į dešinę ir kairę, sudarančios apskritimą, bei apskritimu apvestas vienetas viršuje"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Laikrodžio rodyklės kryptimis nukreiptos rodyklės į viršų ir apačią, sudarančios apskritimą"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Prieš laikrodžio rodyklę nukreiptos rodyklės į apačią ir viršų, sudarančios apskritimą"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Mažo šviesumo simbolis"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Didelio šviesumo simbolis"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Brūkšniu perbrauktas garsiakalbis"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Garsiakalbis"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Garsiakalbis su viena garso banga"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Garsiakalbis su trimis garso bangomis"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Akumuliatorius"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektros kištukas"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Didinimo stiklas į kairę"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Didinimo stiklas į dešinę"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Spyna su rašaliniu rašikliu"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Užrakinta spyna su raktu"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Raktas"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Spyna"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Atrakinta spyna"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Skambutis"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Brūkšniu perbrauktas skambutis"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Žymė"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Nuorodos simbolis"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Akutė"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Užrašas BACK ir į kairę nukreipta rodyklė virš jo"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Užrašas END ir į kairę nukreipta rodyklė virš jo"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Užrašas ON su šauktuku ir rodyklė į kairę ir dešinę virš jo"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Užrašas SOON ir į dešinę nukreipta rodyklė virš jo"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Užrašas TOP ir į viršų nukreipta rodyklė virš jo"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Draudimą nepilnamečiams reiškiantis simbolis"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Dešimtas klavišas"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Didžiųjų lotyniškų raidžių įvedimo simbolis"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Mažųjų lotyniškų raidžių įvedimo simbolis"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Skaičių įvedimo simbolis"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbolių įvedimo simbolis"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Lotyniškų raidžių įvedimo simbolis"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Gaisras"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Žibintuvėlis"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Veržliaraktis"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Plaktukas"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Veržlė ir varžtas"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho peilis"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistoletas"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskopas"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskopas"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Krištolinis kamuolys"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Šešiakampė žvaigždė su tašku viduryje"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japoniškas simbolis pradedančiajam"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trišakio simbolis"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Juodas kvadratinis mygtukas"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Baltas kvadratinis mygtukas"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Didelis raudonas rutulys"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Didelis mėlynas rutulys"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Didelis oranžinis deimantas"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Didelis mėlynas deimantas"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Mažas oranžinis deimantas"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Mažas mėlynas deimantas"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Aukštyn nukreiptas raudonas trikampis"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Žemyn nukreiptas raudonas trikampis"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Aukštyn nukreiptas mažas raudonas trikampis"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Žemyn nukreiptas mažas raudonas trikampis"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Pirmą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Antrą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Trečią valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Ketvirtą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Penktą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Šeštą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Septintą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Aštuntą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Devintą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Dešimtą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Vienuoliktą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Dvyliktą valandą rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Pusę dviejų rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Pusę trijų rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Pusę keturių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Pusę penkių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Pusę šešių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Pusę septynių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Pusę aštuonių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Pusę devynių rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Pusę dešimt rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Pusę vienuolikos rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Pusę dvylikos rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Pusę pirmos rodantis laikrodis"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fudži kalnas"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokijo bokštas"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Laisvės statula"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Japonijos siluetas"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai akmeninė statula"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Išsišiepęs veidas"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Išsišiepęs veidas su besišypsančiomis akimis"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Veidas su džiaugsmo ašaromis"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Besišypsantis išsižiojęs veidas"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Besišypsantis išsižiojęs veidas su besišypsančiomis akimis"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Besišypsantis išsižiojęs veidas, išpiltas šalto prakaito"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Besišypsantis išsižiojęs veidas su smarkiai užmerktomis akimis"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Besišypsantis veidas su aureole"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Besišypsantis veidas su ragais"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Mirksintis veidas"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Besišypsantis veidas su besišypsančiomis akimis"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Skaniu maistu besimėgaujantis veidas"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Veidas su palengvėjimu"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Besišypsantis veidas su širdelės formos akimis"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Besišypsantis veidas su saulės akiniais"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Iš pasitenkinimo besišypsantis veidas"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutralus veidas"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Veidas be jokios išraiškos"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Nelinksmas veidas"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Veidas, išpiltas šalto prakaito"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Susimąstęs veidas"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Sutrikęs veidas"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Suglumintas veidas"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Bučiuojantis veidas"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Bučinį siunčiantis veidas"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Bučiuojantis veidas su besišypsančiomis akimis"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Bučiuojantis veidas su užmerktomis akimis"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Veidas su iškištu liežuviu"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Veidas su iškištu liežuviu ir viena primerkta akim"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Veidas su iškištu liežuviu ir stipriai užmerktomis akimis"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Nusivylęs veidas"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Susirūpinęs veidas"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Piktas veidas"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Susiraukęs veidas"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Verkiantis veidas"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Atkaklus veidas"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Triumfuojantis veidas"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Nusivylęs veidas, tačiau su palengvėjimu"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Paniuręs išsižiojęs veidas"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Kančios kupinas veidas"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Baimės pilnas veidas"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Nuvargęs veidas"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Mieguistas veidas"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Pavargęs veidas"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Besivaipantis veidas"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Garsiai verkiantis veidas"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Išsižiojęs veidas"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Nuščiuvęs veidas"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Išsižiojęs veidas, išpiltas šalto prakaito"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Išsigandęs veidas"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Apstulbęs veidas"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Nuraudęs veidas"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Miegantis veidas"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Apsvaigęs veidas"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Veidas be burnos"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Veidas su medicinine kauke"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Išsišiepusios katės snukutis su besišypsančiomis akimis"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Katės snukutis su džiaugsmo ašaromis"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Besišypsančios išsižiojusios katės snukutis"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Besišypsančios katės snukutis su širdelės formos akimis"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Katės snukutis su kreiva šypsena"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Bučiuojančios katės snukutis su užmerktomis akimis"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Susiraukusios katės snukutis"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Verkiančios katės snukutis"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Nuvargusios katės snukutis"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Nepritariantis veidas"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Pritariantis veidas"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Žemai nusilenkęs žmogus"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Užsidengusi akis beždžionė"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Užsidengusi ausis beždžionė"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Užsidengusi burną beždžionė"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Laimingas žmogus, pakėlęs vieną ranką"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Džiaugsmingai rankas keliantis žmogus"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Susiraukęs žmogus"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Žmogus susiraukusiu veidu"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Žmogus su suglaustais delnais"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Sraigtasparnis"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Garvežys"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Geležinkelio vežimėlis"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Greitasis traukinys"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Greitasis traukinys su smailiu priekiu"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Traukinys"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Miesto tramvajus"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stotis"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvajus"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tramvajaus vagonas"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobusas"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Artėjantis autobusas"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Troleibusas"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobusų stotelė"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Mikroautobusas"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Greitosios pagalbos automobilis"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Ugniagesių automobilis"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policijos automobilis"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Artėjantis policijos automobilis"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Artėjantis taksi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobilis"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Artėjantis automobilis"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Rekreacijos automobilis"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Krovininis sunkvežimis"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Sunkvežimis su priekaba"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktorius"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Vienbėgis geležinkelis"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Kalnų geležinkelis"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Kabanti geležinkelio linija"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Kalnų kabelinis kranas"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Orinis tramvajus"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Laivas"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Irklinė valtis"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motorinis kateris"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontalus šviesoforas"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikalus šviesoforas"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Statybų ženklas"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Besisukanti policijos automobilio lempa"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trikampė vėliavėlė ant kotelio"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Durys"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Ženklas, kad įeiti / įvažiuoti draudžiama"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Rūkymo simbolis"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Nerūkymo simbolis"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Šiukšlių metimo į tam skirtas vietas simbolis"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Draudimo šiukšlinti simbolis"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Geriamojo vandens simbolis"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Negeriamojo vandens simbolis"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Dviratis"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Dviračiais važiuoti draudžiama"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Dviratininkas"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Dviratininkas, važiuojantis kalnų dviračiu"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pėsčiasis"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Pėstiesiems eiti draudžiama"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Vaikų perėja"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Vyrų simbolis"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Moterų simbolis"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Tualeto kambarys"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Kūdikio simbolis"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Tualetas"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Tualetas"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dušas"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Vonia"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Vonia"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasų kontrolė"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Muitinė"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagažo atsiėmimo punktas"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Palikto bagažo punktas"</string>
+</resources>
diff --git a/java/res/values-lt/strings-talkback-descriptions.xml b/java/res/values-lt/strings-talkback-descriptions.xml
index 18b09dd..d2a97dd 100644
--- a/java/res/values-lt/strings-talkback-descriptions.xml
+++ b/java/res/values-lt/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nėra įvesto teksto"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> pataiso <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> į <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> atlieka automatinį taisymą"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nėra pasiūlymų"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Nežinomas simbolis"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Klavišas „Shift“"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Daugiau simbolių"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Didžioji I su tašku viršuje"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nežinomas simbolis"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nežinomas jaustukas"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Nuobodžiaujantis veidas"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Susigėdęs veidas"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Veidas su akiniais nuo saulės"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Nustebęs veidas"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bučiuojantis veidas"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Paniuręs veidas"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatyvūs ženklai pasiekiami"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatyvūs simboliai atmetami"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatyvūs pasiūlymai pasiekiami"</string>
diff --git a/java/res/values-lt/strings.xml b/java/res/values-lt/strings.xml
index cac1287..00d20d6 100644
--- a/java/res/values-lt/strings.xml
+++ b/java/res/values-lt/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibruoti, kai paspaudžiami klavišai"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Klavišo paspaudimo garsas"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Iššoka paspaudus klavišą"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Nuostatos"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Paskyros ir privatumas"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Išvaizda ir išdėstymai"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Įvestis gestais"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Teksto taisymas"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Išplėstiniai"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Įgalinti suskaidytą klaviatūrą"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"„Google“ klaviatūros sinchroniz."</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinchronizavimas įjungtas"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sinchronizuokite asmeninį žodyną visuose įrenginiuose"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinchronizuoti dabar"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Duomenų debesyje ištrynimas"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Ištrinami sinchronizuoti duomenys iš „Google“"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Sinchron. duomenys bus ištrinti iš debesies. Norite tai atlikti?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Ištrinti"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Atšaukti"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Asmeninis žodynas bus sinchronizuotas ir atsarginė kopija sukurta „Google“ serveriuose. Gali būti renkama statistinė žodžių dažnumo informacija, kad būtų galima patobulinti produktus. Visa informacija renkama ir naudojama laikantis "<a href="https://www.google.com/policies/privacy">"„Google“ privatumo politikos"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Pridėkite „Google“ paskyrą prie įreng., kad įgalint. šią funkciją"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Perj. į kt. įvesties būd."</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kalbos perjungimo klavišu taip pat perjungiami įvesties būdai"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Kalbos keitimo klavišas"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Rodyti, kai įgalintos kelios įvesties kalbos"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Rodyti šliaužiklio indikatorių"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Rodyti vaizd. užuominą slenkant nuo „Shift“ ar simb. klavišų"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pagr. išš. l. atsis. d."</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Be delsos"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Numatytasis"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Pagrindinis žodynas"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Rodyti taisymo pasiūlymus"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Įvedant tekstą pateikti siūlomų žodžių"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visada rodyti"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Rodyti portreto režimu"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Visada slėpti"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokuoti įžeidžiančius žodžius"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Nesiūlyti galimai įžeidžiančių žodžių"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatinis taisymas"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Įvesties balsu klavišas"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nėra jokių įgalintų įvesties balsu metodų. Patikrinkite kalbos ir įvesties nustatymus."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Siųsti atsiliepimą"</string>
-    <string name="select_language" msgid="3693815588777926848">"Įvesties kalbos"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Kalbos"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pagalba ir atsiliepimai"</string>
+    <string name="select_language" msgid="5709487854987078367">"Kalbos"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Jei norite išsaugoti, palieskite dar kartą"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Palieskite čia, kad išsaugotumėte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatūros tema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Perjungti paskyras"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nepasirinkta jokia paskyra"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Šiuo metu naudojama <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Gerai"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Atšaukti"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Atsijungti"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Pasirinkite norimą naudoti paskyrą"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglų k. (JK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglų k. (JAV)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Ispanų k. (JAV)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi ir anglų k. derinys"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbų k. (lot. rašmenys)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Anglų (JK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Anglų (JAV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ispanų (JAV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi ir anglų derinys (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbų k. (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicinė)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirilica)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (lotynų)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktiška)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Kalbos nėra (abėcėlė)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abėcėlė (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abėcėlė (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Abėcėlė („Colemak“)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Abėcėlė (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Jaustukai"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Klaviatūros tema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Pasirinkti įvesties stilių"</string>
     <string name="add_style" msgid="6163126614514489951">"Prid. stilių"</string>
     <string name="add" msgid="8299699805688017798">"Pridėti"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Įgalinti"</string>
     <string name="not_now" msgid="6172462888202790482">"Ne dabar"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Toks pat įvesties stilius jau yra: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Klavišo ilgo paspaudimo delsa"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrav. paspaudus mygt. trukmė"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Garso paspaudus mygt. garsumas"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Skaityti išorinį žodyno failą"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Atsisiuntimų aplanke nėra žodyno failų"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pasirinkite diegiamą žodyno failą"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Ar tikrai įdiegti šį failą <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Įvyko klaida"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Klavišo ilgo paspaudimo delsa"</string>
     <string name="button_default" msgid="3988017840431881491">"Numatytieji"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Sveiki! Tai „<xliff:g id="APPLICATION_NAME">%s</xliff:g>“"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"naudojant įvestį gestais"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Dabar galite įvesti visas mėgstamas programas naudodami „<xliff:g id="APPLICATION_NAME">%s</xliff:g>“."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigūruokite papildomas kalbas"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Baigta"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Rodyti programos piktogramą"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Pateikti programos piktogramą paleidimo priemonėje"</string>
     <string name="app_name" msgid="6320102637491234792">"Žodyno teikėjas"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Žodyno teikėjas"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Žodyno paslauga"</string>
diff --git a/java/res/values-lv/strings-emoji-descriptions.xml b/java/res/values-lv/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..525a1a0
--- /dev/null
+++ b/java/res/values-lv/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Autortiesību zīme"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Reģistrētas prečzīmes simbols"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Divas izsaukuma zīmes"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Izsaukuma un jautājuma zīme"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Prečzīme"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informācijas avots"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Pa labi un pa kreisi vērstā bultiņa"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Augšupvērstā un lejupvērstā bultiņa"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Bultiņa no Ziemeļiem uz Rietumiem"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Bultiņa no Ziemeļiem uz Austrumiem"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Bultiņa no Dienvidiem uz Austrumiem"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Bultiņa no Dienvidiem uz Rietumiem"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Pa kreisi vērstā bultiņa ar āķi"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Pa labi vērstā bultiņa ar āķi"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Pulkstenis"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Smilšu pulkstenis"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Divi pa labi vērsti melni trīsstūri"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Divi pa kreisi vērsti melni trīsstūri"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Divi augšupvērsti melni trīsstūri"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Divi lejupvērsti melni trīsstūri"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Modinātājs"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Smilšu pulkstenis ar plūstošām smiltīm"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Apvilkts latīņu alfabēta lielais burts “M”"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Mazs, melns kvadrāts"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Mazs, balts kvadrāts"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Melns pa labi vērsts trīsstūris"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Melns pa kreisi vērsts trīsstūris"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Balts vidēja lieluma kvadrāts"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Melns vidēja lieluma kvadrāts"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Balts vidēji mazs kvadrāts"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Melns vidēji mazs kvadrāts"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Melna saule ar stariem"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Mākonis"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Melns tālrunis"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Atzīmēta izvēles rūtiņa"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Lietussargs ar ūdens lāsēm"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Karsts dzēriens"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Augšupvērsts rādītājpirksts baltā krāsā"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Smaidiņš baltā krāsā"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Auns"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Vērsis"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Dvīņi"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Vēzis"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lauva"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Jaunava"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Svari"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpions"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Strēlnieks"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Mežāzis"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Ūdensvīrs"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Zivis"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Melns pīķa masts"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Melns kreica masts"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Melns ercena masts"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Melns kārava masts"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Karstie avoti"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Melns universāls otrreizējās pārstrādes simbols"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Invalīdu ratiņu simbols"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Enkurs"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Brīdinājuma zīme"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Augstsprieguma zīme"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Vidēji liels balts aplis"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Vidēji liels melns aplis"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futbola bumba"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beisbola bumba"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Sniegavīrs bez sniega"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Saule aiz mākoņa"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Čūsknesis"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Iebraukt aizliegts"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Baznīca"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Strūklaka"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Karodziņš bedrītē"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Burulaiva"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Telts"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Degvielas sūknis"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Melnas šķēres"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Balta izcelta atzīme"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Lidmašīna"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Aploksne"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Pacelta dūre"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Pacelta roka"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Rokas žests “Uzvara!”"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Zīmulis"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Melna rakstāmspalva"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Izcelta atzīme"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Izcelta reizinājuma zīme"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Spīguļošana"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Astoņu staru zvaigznīte"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Melna astoņu smaiļu zvaigznīte"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Sniegpārsliņa"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Dzirksts"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Reizinājuma zīme"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Reizinājuma zīme negatīvās krāsās ietverta kvadrātā"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Dekoratīva melna jautājuma zīme"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Dekoratīva balta jautājuma zīme"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Dekoratīva balta izsaukuma zīme"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Izcelts izsaukuma zīmes simbols"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Aizpildīta melna sirds"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Izcelta pluszīme"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Izcelta mīnus zīme"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Izcelta dalīšanas zīme"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Melna pa labi vērsta bultiņa"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Izliekta cilpa"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Divas izliektas cilpas"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pa labi vērsta bultiņa, kas pagriežas uz augšu"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pa labi vērsta bultiņa, kas pagriežas uz leju"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Pa kreisi vērsta melna bultiņa"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Augšupvērsta melna bultiņa"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Lejupvērsta melna bultiņa"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Liels melns kvadrāts"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Liels balts kvadrāts"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Balta vidēja lieluma zvaigzne"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Izcelts liels aplis"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Viļņota līkne"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Dziedātāja partijas maiņas zīme"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Apvilkta ideogramma “Apsveicu!”"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Apvilkta ideogramma “Noslēpums”"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong kauliņš: sarkanais pūķis"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Spēļu kārts: melnais džokers"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A asins grupa"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B asins grupa"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"0. asins grupa"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Autostāvvieta"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB asins grupa"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Abreviatūra “CL” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Vārds “cool” ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Vārds “free” ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Abreviatūra “ID” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Vārds “new” ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Abreviatūra “N G” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Abreviatūra “OK” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Abreviatūra “SOS” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Vārds “up” ar izsaukuma zīmi ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Abreviatūra “vs” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Vārds “šeit” (katakanas rakstībā) ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Vārds “apkalpošana” (katakanas rakstībā) ietverts kvadrātā"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogramma “bez maksas” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogramma “rezervēta vieta” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogramma “aizliegums” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogramma “vakance” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogramma “pieņemšana” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogramma “brīvu vietu nav” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogramma “maksas” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogramma “mēnesī” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogramma “pieteikums” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogramma “atlaide” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogramma “atvērts” ietverta kvadrātā"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideogramma “priekšrocības” ietverta aplī"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideogramma “piekrist” ietverta aplī"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciklons"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Migla"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Aizvērts lietussargs"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Zvaigžņota nakts"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Saullēkts pār kalniem"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Saullēkts"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Pilsēta krēslā"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Saulriets pār ēkām"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Varavīksne"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Tilts naktī"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Ūdens vilnis"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkāns"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Piena ceļš"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globuss ar Eiropu un Āfriku"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globuss ar Ziemeļameriku un Dienvidameriku"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globuss ar Āziju un Austrāliju"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globuss ar meridiāniem"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Jauna mēness simbols"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Augoša mēness sirpja simbols"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Pirmā ceturkšņa mēness simbols"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Augoša izliekta mēness simbols"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Pilnmēness simbols"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Dilstoša izliekta mēness simbols"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Pēdējā ceturkšņa mēness simbols"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Dilstoša mēness sirpja simbols"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Mēness sirpis"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Jauns mēness ar seju"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Pirmā ceturkšņa mēness ar seju"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Pēdējā ceturkšņa mēness ar seju"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Pilnmēness ar seju"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Saule ar seju"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Mirgojoša zvaigzne"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Krītoša zvaigzne"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanis"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Asns"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Mūžzaļš koks"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Lapu koks"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktuss"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulpe"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Ķirša zieds"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Roze"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisks"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Saulespuķe"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Zieds"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kukurūzas vālīte"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Rīsu vārpas"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Ārstniecības augs"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Četrlapu āboliņš"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Kļavas lapa"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Nokritušas lapas"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Vējā lidojoša lapa"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Sēne"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomāts"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Baklažāns"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Vīnogas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melone"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Arbūzs"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarīns"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citrons"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banāns"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananāss"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Sarkans ābols"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zaļš ābols"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Bumbieris"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Persiks"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Ķirši"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Zemene"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburgers"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Picas šķēle"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Gaļa ar kaulu"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Putna gaļas stilbiņi"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rīsu cepumi"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rīsu bumbiņa"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Vārīti rīsi"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Rīsi ar karija mērci"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Kūpoša bļoda"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spageti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Maize"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Kartupeļi Frī"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Cepts saldais kartupelis"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Suši"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Fritēta garnele"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Zivju kūciņa ar spirālveida rotājumu"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Mīkstais saldējums"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Sasmalcināta ledus deserts"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Saldējums"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Virtulis"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cepums"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Šokolādes tāfelīte"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Konfekte"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Olu krēms"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Medus pods"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Smilšu torte ar augļu pildījumu"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento pusdienu kastīte"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Ēdiens podiņā"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Ēdiena gatavošana"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Nazis un dakšiņa"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tējas krūze bez osas"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakē pudele un glāzīte"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vīna glāze"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kokteiļglāze"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropu augļu kokteilis"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Alus kauss"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Alus kausu saskandināšana"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Barošanas pudelīte"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Lente"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Iesaiņota dāvana"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Dzimšanas dienas kūka"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Helovīna laterna"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Egle"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Santaklauss"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Salūts"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Brīnumusvecīte"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balons"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Plaukšķene"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfeti bumba"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata koks"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Sakrustoti karogi"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Priedes dekorācija"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japāņu lelles"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Karpu karodziņi"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vēja zvani"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Mēness skatīšanās ceremonija"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Skolas soma"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Izlaiduma cepure"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karuseļa zirdziņš"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Panorāmas rats"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Amerikāņu kalniņi"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Makšķere un zivs"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofons"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Kinokamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kinoteātris"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Austiņas"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Gleznošanas palete"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cilindrs"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirka telts"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Biļete"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Kino klapīte"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Tēlotāja māksla"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videospēle"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Tieši mērķī"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Spēļu automāts"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljards"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Metamie kauliņi"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Boulings"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Ziedu kāršu spēle"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Mūzikas nots"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Vairākas mūzikas notis"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofons"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Ģitāra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klavieru taustiņi"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompete"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Vijole"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Nošu līnijas"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Skriešanas krekls ar lenti"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tenisa rakete un bumbiņa"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Slēpes un slēpju zābaki"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbola bumba un grozs"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Rūtains karogs"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snovbordists"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Skrējējs"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Sērfotājs"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Balva"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Zirgu sacīkstes"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikāņu futbola bumba"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Regbija bumba"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Peldētājs"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Dzīvojamā māja"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Māja ar dārzu"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Biroju ēka"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Pasta ēka Japānā"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Pasta ēka Eiropā"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Slimnīca"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomāts"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Viesnīca"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Mīlnieku viesnīca"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Diennakts veikals"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Skola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Lielveikals"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Rūpnīca"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Papīra laterna"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japāņu pils"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Pils Eiropā"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Žurka"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Pele"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Vērsis"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Ūdens bifelis"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Govs"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopards"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Trusis"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kaķis"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Pūķis"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodils"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Valis"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Gliemezis"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Čūska"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Zirgs"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Auns"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Kaza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Aita"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Pērtiķis"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gailis"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Vista"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Suns"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cūka"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Vepris"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Zilonis"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Astoņkājis"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spirālveida gliemežvāks"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Kukainis"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Skudra"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Medusbite"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Mārīte"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Zivs"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropu zivs"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Adatzivs"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Bruņurupucis"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Izšķīlies cālēns"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Cālēns"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Cālēna pretskats"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Putns"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvīns"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala lācis"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pūdelis"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Vienkupra kamielis"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Divkupru kamielis"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfīns"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Peles galva"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Govs galva"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tīģera galva"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Truša galva"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kaķa galva"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Pūķa galva"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Valis izšļāc ūdeni"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Zirga galva"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Pērtiķa galva"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Suņa galva"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cūkas galva"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Vardes galva"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Kāmis"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Vilka galva"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Lāča galva"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandas galva"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Cūkas šņukurs"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Ķepu nospiedumi"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Acis"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Auss"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Deguns"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mute"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Mēle"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Balta delnas virspuse ar augšupvērstu rādītājpirkstu"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Balta delnas virspuse ar lejupvērstu rādītājpirkstu"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Balta delnas virspuse ar pa kreisi vērstu rādītājpirkstu"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Balta delnas virspuse ar pa labi vērstu rādītājpirkstu"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Plauksta dūrē"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Mājoša roka"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Žests “Viss kārtībā!”"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Pacelts īkšķis"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Nolaists īkšķis"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Plaukstas plaukšķina"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Atvērtu plaukstu žests"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Kronis"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Sieviešu cepure"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Brilles"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kaklasaite"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T krekls"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Džinsa bikses"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Kleita"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Sieviešu apģērbs"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Naudasmaks"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Rokassomiņa"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Maciņš"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Vīriešu kurpe"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sporta kurpe"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Augstpapēžu kurpe"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sieviešu sandale"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Sieviešu zābaks"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Pēdu nospiedumi"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Krūšutēla siluets"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Krūšutēlu siluets"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Zēns"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Meitene"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Vīrietis"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Sieviete"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Ģimene"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Vīrietis un sieviete sadevušies rokās"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Divi vīrieši sadevušies rokās"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Divas sievietes sadevušās rokās"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policists"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Sieviete ar zaķa ausīm"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Līgava ar plīvuru"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persona ar blondiem matiem"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Vīrietis ar ķīniešu tradicionālo cepuri"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Vīrietis ar turbānu"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Gados vecāks vīrietis"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Gados vecāka sieviete"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Zīdainis"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Celtnieks"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princese"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japāņu velns"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japāņu gnoms"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spoks"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Ķerubs"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Citplanētietis"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Citplanētiešu briesmonis"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Velnēns"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Galvaskauss"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Darbinieks recepcijā"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Apsargs"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dejotājs"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lūpukrāsa"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nagu laka"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Sejas masāža"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Matu griezums"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Bārddziņa izkārtne"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Šļirce"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Tablete"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Lūpu nospiedums"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Mīlestības vēstule"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Gredzens"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Dārgakmens"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Skūpsts"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Ziedu pušķis"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pāris ar sirdi"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Kāzas"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Pukstoša sirds"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Lauzta sirds"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Divas sirdis"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Vizuļojoša sirds"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Pieaugoša sirds"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Sirds ar bultu"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Zila sirds"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zaļa sirds"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Dzeltena sirds"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Violeta sirds"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Sirds ar lenti"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Rotējošas sirdis"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Sirds rotājums"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Briljanta forma ar punktu iekšpusē"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektriskā spuldze"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Dusmu simbols"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Spridzeklis"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Gulēšanas simbols"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Sadursmes simbols"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Līstoši sviedri"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Piliens"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Steigšanās simbols"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Izkārnījumu kaudze"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Sasprindzināts bicepss"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Galvas reiboņu simbols"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Runas burbulis"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Domu burbulis"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Balts zieds"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simts punktu simbols"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Naudas maiss"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valūtas maiņa"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Izcelta dolārzīme"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredītkarte"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknote ar jēnas zīmi"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknote ar dolāra zīmi"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknote ar eiro zīmi"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknote ar mārciņas zīmi"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Banknote ar spārniem"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Diagramma ar pozitīvām tendencēm un jēnas zīmi"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sēdeklis"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personālais dators"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Portfelis"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisks"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskete"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optiskais disks"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Failu mape"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Atvērta failu mape"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Uzlocījusies lapa"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Lapa ar tekstu uz augšu"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendārs"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Noplēšamais kalendārs"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kartotēka"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Diagramma ar pozitīvām tendencēm"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Diagramma ar negatīvām tendencēm"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Stabiņu diagramma"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Mape planšete"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Piespraude"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Adata"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Saspraude"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Taisns lineāls"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trīsstūrveida lineāls"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Marķēšanas indeksi"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Virsgrāmata"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Klade"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Klade ar dekoratīviem vākiem"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Aizvērta grāmata"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Atvērta grāmata"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zaļa grāmata"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Zila grāmata"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranža grāmata"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Grāmatas"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Vārda kartīte"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Pergamenta rullis"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Zīmīte"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Tālruņa klausule"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Peidžeris"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fakss"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelītantena"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Rupors"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Uzmundrinošs megafons"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Izejošo dokumentu plaukts"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Ienākošo dokumentu plaukts"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Sūtījums"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-pasta simbols"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Ienākošā pasta aploksne"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Aploksne ar lejupvērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Aizvērta pastkastīte ar nolaistu karodziņu"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Aizvērta pastkastīte ar paceltu karodziņu"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Atvērta pastkastīte ar paceltu karodziņu"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Atvērta pastkastīte ar nolaistu karodziņu"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Pasta kaste"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Pasta taure"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Laikraksts"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobilais tālrunis"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobilais tālrunis ar pa labi vērstu bultiņu kreisajā pusē"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrorežīms"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobilais tālrunis izslēgts"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobilie tālruņi nav atļauti"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena ar stabiņiem"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotokamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizors"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokasete"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Pa labi vērstas savītas bultiņas"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Pulksteņrādītāja virzienā pa labi un pa kreisi vērstas atvērtas bultiņas, kas veido apli"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Pulksteņrādītāja virzienā pa labi un pa kreisi vērstas atvērtas bultiņas, kas veido apli, kur pārklājas apvilkts cipars “viens”"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Pulksteņrādītāja virzienā lejupvērstas un augšupvērstas atvērtas bultiņas, kas veido apli"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Pretēji pulksteņrādītāja virzienam lejupvērstas un augšupvērstas atvērtas bultiņas, kas veido apli"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Zems spilgtuma līmenis"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Augsts spilgtuma līmenis"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Pārsvītrots skaļrunis"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Skaļrunis"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Skaļrunis ar vienu skaņas vilni"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Skaļrunis ar trīs skaņas viļņiem"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Akumulators"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Kontaktspraudnis"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Pa kreisi vērsta lupa"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Pa labi vērsta lupa"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Slēdzene ar tintes pildspalvu"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Slēgta slēdzene ar atslēgu"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Atslēga"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Slēdzene"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Atvērta slēdzene"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zvans"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Pārsvītrots zvans"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Grāmatzīme"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Saites simbols"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radiopoga"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Vārds “Back” ar pa kreisi vērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Vārds “End” ar pa kreisi vērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Vārds “On” ar izsaukuma zīmi un pa kreisi un pa labi vērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Vārds “Soon” ar pa labi vērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Vārds “Top” ar augšupvērstu bultiņu augšpusē"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Aizlieguma zīme personām, kas jaunākas par 18 gadiem"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Taustiņš “10”"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Latīņu alfabēta lielo burtu ievades simbols"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Latīņu alfabēta mazo burtu ievades simbols"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Ciparu ievades simbols"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbols simbolu ievadei"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Latīņu alfabēta burtu ievades simbols"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Ugunsgrēks"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Kabatas lukturītis"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Uzgriežņu atslēga"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Āmurs"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Skrūve un uzgrieznis"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Virtuves nazis"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistole"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskops"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskops"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristāla lode"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sešstaru zvaigzne ar punktu vidū"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japāņu simbols, kas nozīmē “Iesācējs”"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trijžubura simbols"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Melna, kvadrātveida poga"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Balta, kvadrātveida poga"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Liels, sarkans aplis"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Liels, zils aplis"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Liels, oranžs briljants"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Liels, zils briljants"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Mazs, oranžs briljants"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Mazs, zils briljants"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Augšupvērsts sarkans trīsstūris"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Lejupvērsts sarkans trīsstūris"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Augšupvērsts mazs, sarkans trīsstūris"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Lejupvērsts mazs, sarkans trīsstūris"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Ciparnīca: plkst. viens"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Ciparnīca: plkst. divi"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Ciparnīca: plkst. trīs"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Ciparnīca: plkst. četri"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Ciparnīca: plkst. pieci"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Ciparnīca: plkst. seši"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Ciparnīca: plkst. septiņi"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Ciparnīca: plkst. astoņi"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Ciparnīca: plkst. deviņi"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Ciparnīca: plkst. desmit"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Ciparnīca: plkst. vienpadsmit"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Ciparnīca: plkst. divpadsmit"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Ciparnīca: plkst. pus divi"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Ciparnīca: plkst. pus trīs"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Ciparnīca: plkst. pus četri"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Ciparnīca: plkst. pus pieci"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Ciparnīca: plkst. pus seši"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Ciparnīca: plkst. pus septiņi"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Ciparnīca: plkst. pus astoņi"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Ciparnīca: plkst. pus deviņi"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Ciparnīca: plkst. pus desmit"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Ciparnīca: plkst. pus vienpadsmit"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Ciparnīca: plkst. pus divpadsmit"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Ciparnīca: plkst. pus viens"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fudzi kalns"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokijas tornis"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Brīvības statuja"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Japānas kontūra"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Zobgalīgs smaids"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Zobgalīga seja ar smaidošām acīm"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Seja ar prieka asarām"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Plats smaids"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Plats smaids un smaidošas acis"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Plats smaids un auksti sviedri"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Plats smaids un cieši aizvērtas acis"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Smaidiņš ar nimbu"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Smaidiņš ar ragiem"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Smaidiņš ar piemiegtu aci"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Smaidiņš ar smaidošām acīm"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Smaidiņš, kas izbauda gardu ēdienu"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Atvieglota sejas izteiksme"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Smaidiņš ar acīm sirds formā"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Smaidiņš ar saulesbrillēm"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Vīpsnājošs smaidiņš"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neitrāla sejas izteiksme"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Seja bez izteiksmes"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Neiepriecināta sejas izteiksme"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Seja ar aukstiem sviedriem"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Domīgs"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Samulsis"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Apmulsināts"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Skūpstu sniedzošs"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Skūpstu sūtošs"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Skūpstu sniedzošs smaidiņš ar smaidošām acīm"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Skūpstu sniedzošs smaidiņš ar aizvērtām acīm"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Smaidiņš ar izbāztu mēli"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Smaidiņš ar izbāztu mēli un piemiedzošu aci"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Smaidiņš ar izbāztu mēli un cieši aizvērtām acīm"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Vīlies"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Noraizējies"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Dusmīgs"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Sabozies"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Raudošs"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Neatlaidīgs"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Smaidiņš ar triumfējošu skatienu"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Vīlies, bet atvieglots"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Saviebies ar atvērtu muti"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Mokpilna seja"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Pārbijies"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Garlaikots"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Miegains"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Noguris"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Vaibstās"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Skaļi raudošs"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Ar atvērtu muti"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Apklusināts"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Ar atvērtu muti un aukstiem sviedriem"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Bailēs kliedzoša seja"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Izbrīnīts"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Nosarcis"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Guļošs"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Sareibis"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Seja bez mutes"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Seja ar medicīnisko masku"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Zobgalīgs kaķis ar smaidošām acīm"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Kaķis ar prieka asarām"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Smaidīgs kaķis ar atvērtu muti"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Smaidīgs kaķis ar acīm sirds formā"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Kaķis ar ironisku smaidu"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Skūpstu sniedzošs kaķis ar aizvērtām acīm"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Sabozies kaķis"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Raudošs kaķis"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Garlaikots kaķis"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Persona ar žestu “Nav labi!”"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Persona ar žestu “Viss kārtībā!”"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persona, kas zemu paklanās"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Pērtiķis, kas neredz ļaunu"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Pērtiķis, kas nedzird ļaunu"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Pērtiķis, kas nesaka ļaunu"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Laimīga persona pacēlusi vienu roku"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Cilvēks ar sajūsmā paceltām rokām"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Nīgra persona"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Sabozusies persona"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persona ar kopā saliktām plaukstām"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raķete"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopters"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Tvaika lokomotīve"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vilciena vagons"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Ātrvilciens"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Ātrvilciens ar lodesveida priekšgalu"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vilciens"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Pasažieru vilciens"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stacija"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvajs"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tramvaja vagons"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobuss"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Pienākošs autobuss"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbuss"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobusu pietura"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Mikroautobuss"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ātrā palīdzība"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Ugunsdzēsēju mašīna"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policijas automašīna"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Policijas automašīna tuvojas"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksis"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taksis tuvojas"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automašīna"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automašīna tuvojas"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Apvidus auto"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Vieglais preču automobilis"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Kravas auto"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktors"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Viensliežu dzelzceļš"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Funikulieris"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Trošu vilciens"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Kalna trošu ceļš"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Gaisa tramvajs"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Kuģis"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Airu laiva"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Ātrlaiva"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontālais luksofors"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikāls luksofors"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Ceļa remontdarbu zīme"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Policijas automašīnas ar ieslēgtām bākugunīm"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trīsstūra formas karogs mastā"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Durvis"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Zīme “Aizliegts ienākt!”"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Zīme “Smēķēt atļauts”"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Smēķēšanas aizlieguma zīme"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Zīmē “Ievietojiet atkritumus tam paredzētajās tvertnēs!”"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Zīme “Nepiesārņot!”"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Zīme “Dzeramais ūdens”"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Zīme “Ūdens nav dzerams”"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Velosipēds"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Ar velosipēdiem pārvietoties aizliegts"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Velosipēdists"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Kalnu velosipēdists"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Kājāmgājējs"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Kājāmgājējiem pārvietoties aizliegts"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Pāreja bērniem"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Zīme “Vīriešiem”"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Zīme “Sievietēm”"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Atpūtas telpa"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Zīme “Piemērota zīdaiņiem”"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Tualete"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Ūdens klozets"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Duša"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Vanna"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Burbuļvanna"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasu kontrole"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Muita"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagāžas nodošanas/saņemšanas vieta"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Aizmirstā bagāža"</string>
+</resources>
diff --git a/java/res/values-lv/strings-talkback-descriptions.xml b/java/res/values-lv/strings-talkback-descriptions.xml
index 2fe7f91..d23d4fa 100644
--- a/java/res/values-lv/strings-talkback-descriptions.xml
+++ b/java/res/values-lv/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Teksts nav ievadīts"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Nospiežot taustiņu <xliff:g id="KEY_NAME">%1$s</xliff:g>, “<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>” tiek labots uz “<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>”."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Taustiņam <xliff:g id="KEY_NAME">%1$s</xliff:g> ir automātiskas labošanas funkcija."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nav ieteikuma"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Nezināma rakstzīme"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Pārslēgšanas taustiņš"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Citi simboli"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Lielais burts “I” ar punktu virs tā"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nezināms simbols"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nezināma emocijzīme"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Garlaikots"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Apmulsis"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ar saulesbrillēm"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Pārsteigts"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Skūpstu sniedzošs"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Drūms"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Ir pieejamas alternatīvas rakstzīmes."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatīvās rakstzīmes netiek rādītas."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Ir pieejami alternatīvi ieteikumi."</string>
diff --git a/java/res/values-lv/strings.xml b/java/res/values-lv/strings.xml
index 798d517..aefa323 100644
--- a/java/res/values-lv/strings.xml
+++ b/java/res/values-lv/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrēt, nospiežot taustiņu"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Skaņa, nospiežot taustiņu"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Nospiežot taustiņu, parādīt uznirstošo izvēlni"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferences"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Konti un konfidencialitāte"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Izskats un izkārtojumi"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Ievade ar žestiem"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Teksta korekcija"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Papildu"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Motīvs"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Iespējot dalīto tastatūru"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google tastatūras sinhronizācija"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinhronizācija ir ieslēgta."</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sinhronizējiet savu personisko vārdnīcu vairākās ierīcēs."</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinhronizēt tūlīt"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Dzēst mākoņa datus"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Dzēš sinhronizētos datus no Google serveriem"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Sinhronizētie dati tiks dzēsti no mākoņa. Vai tiešām to vēlaties?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Dzēst"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Atcelt"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Jūsu personiskā vārdnīca tiks sinhronizēta un dublēta Google serveros. Mūsu produktu uzlabošanas nolūkos var tikt apkopota statistiskā informācija par vārdu biežumu. Visa informācija tiks apkopota un izmantota saskaņā ar "<a href="https://www.google.com/policies/privacy">"Google konfidencialitātes politiku"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Lai iespējotu šo funkciju, pievienojiet Google kontu šai ierīcei."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Pārsl. uz citām iev. met."</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Valodas pārslēgš. taustiņu var lietot arī citām ievades metodēm."</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Valodas pārslēgšanas taustiņš"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Parādīt, ja ir iespējotas vairākas ievades valodas"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Rādīt vilkšanas indikatoru"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Attēlot vizuālu norādījumu, velkot no Shift vai simbolu taustiņa"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Taust. uzn. loga noraid. aizk."</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez aizkaves"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Noklusējums"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Galvenā vārdnīca"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Rādīt labojumu ieteikumus"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Ievades laikā attēlot ieteiktos vārdus"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vienmēr rādīt"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Rādīt portreta režīmā"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vienmēr slēpt"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloķēt aizvainojošus vārdus"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Neiesakiet vārdus, kas varētu būt aizvainojoši."</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automātiska labošana"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Balss ievades atslēga"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nav iespējota neviena balss ievades metode. Pārbaudiet valodas un ievades iestatījumus."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Sūtīt atsauksmes"</string>
-    <string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Valodas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Palīdzība un atsauksmes"</string>
+    <string name="select_language" msgid="5709487854987078367">"Valodas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Lai saglabātu, pieskarieties šeit"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastatūras motīvs"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Pārslēgt kontus"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nav atlasīts neviens konts."</string>
+    <string name="account_selected" msgid="2846876462199625974">"Pašlaik tiek izmantots konts <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>."</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Labi"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Atcelt"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Izrakstīties"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Izmantojamā konta atlasīšana"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Angļu valoda (Lielbritānija)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Angļu valoda (ASV)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spāņu (ASV)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi–angļu valoda"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbu (latīņu)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Angļu (Lielbritānija) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Angļu (ASV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spāņu (ASV) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi–angļu valoda (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbu (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionālā)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kirilica)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latīņu)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktā)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nav valodas (alfabēts)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabēts (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabēts (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabēts (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabēts (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Japāņu emocijzīmes"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tastatūras motīvs"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Pielāg. ievades stili"</string>
     <string name="add_style" msgid="6163126614514489951">"Piev. stilu"</string>
     <string name="add" msgid="8299699805688017798">"Pievienot"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Iespējot"</string>
     <string name="not_now" msgid="6172462888202790482">"Vēlāk"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Šāds ievades stils jau pastāv: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Taustiņa ilgās nosp. noildze"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Taust. nosp. vibrācijas ilgums"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Taustiņu nosp. skaņas skaļums"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ārējās vārdnīcas faila nolasīšana"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Mapē Lejupielādes nav neviena vārdnīcas faila."</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Instalējamā vārdnīcas faila atlasīšana"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vai tiešām instalēt šo failu šādai valodai: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Radās kļūda"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Taustiņa ilgās nosp. noildze"</string>
     <string name="button_default" msgid="3988017840431881491">"Noklusējums"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Laipni lūdzam pakalpojumā <xliff:g id="APPLICATION_NAME">%s</xliff:g>,"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"kurā varat izmantot ievadi ar žestiem"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Izmantojot lietojumprogrammu <xliff:g id="APPLICATION_NAME">%s</xliff:g>, varat rakstīt visās iecienītākajās lietotnēs."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurēt papildu valodas"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Pabeigts"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Rādīt lietotnes ikonu"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Rādīt palaidēja ekrānā lietojumprogrammas ikonu"</string>
     <string name="app_name" msgid="6320102637491234792">"Vārdnīcas nodrošinātājs"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Vārdnīcas nodrošinātājs"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Vārdnīcas pakalpojums"</string>
diff --git a/java/res/values-mk-rMK/strings-action-keys.xml b/java/res/values-mk-rMK/strings-action-keys.xml
index f4fc9ce..f7b0277 100644
--- a/java/res/values-mk-rMK/strings-action-keys.xml
+++ b/java/res/values-mk-rMK/strings-action-keys.xml
@@ -20,19 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for label_go_key (4033615332628671065) -->
-    <skip />
-    <!-- no translation found for label_next_key (5586407279258592635) -->
-    <skip />
-    <!-- no translation found for label_previous_key (1421141755779895275) -->
-    <skip />
-    <!-- no translation found for label_done_key (7564866296502630852) -->
-    <skip />
-    <!-- no translation found for label_send_key (482252074224462163) -->
-    <skip />
+    <string name="label_go_key" msgid="4033615332628671065">"Оди"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"Следно"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"Прет."</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Готово"</string>
+    <string name="label_send_key" msgid="482252074224462163">"Прати"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Барај"</string>
-    <!-- no translation found for label_pause_key (2225922926459730642) -->
-    <skip />
-    <!-- no translation found for label_wait_key (5891247853595466039) -->
-    <skip />
+    <string name="label_pause_key" msgid="2225922926459730642">"Пауза"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"Чекај"</string>
 </resources>
diff --git a/java/res/values-mk-rMK/strings-appname.xml b/java/res/values-mk-rMK/strings-appname.xml
new file mode 100644
index 0000000..da3d84e
--- /dev/null
+++ b/java/res/values-mk-rMK/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<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">"Проверувач на правопис на 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-mk-rMK/strings-config-important-notice.xml b/java/res/values-mk-rMK/strings-config-important-notice.xml
new file mode 100644
index 0000000..d2ae5fa
--- /dev/null
+++ b/java/res/values-mk-rMK/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"Учете од комуникациите и напишаните податоци за подобри предлози"</string>
+</resources>
diff --git a/java/res/values-mk-rMK/strings-emoji-descriptions.xml b/java/res/values-mk-rMK/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..7f9fbd7
--- /dev/null
+++ b/java/res/values-mk-rMK/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Знак за авторски права"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Регистриран знак"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Два извичника"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Извичник и прашалник"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Знак за заштитен знак"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Извор на информации"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Стрелка налево и надесно"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Стрелка нагоре и надолу"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Стрелка северозапад"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Стрелка североисток"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Стрелка југоисток"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Стрелка југозапад"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Стрелка налево со кука"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Стрелка надесно со кука"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Часовник"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Песочен часовник"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Два црни триаголника свртени надесно"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Два црни триаголника свртени налево"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Два црни триаголника свртени нагоре"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Два црни триаголника свртени надолу"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Будилник"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Песочен часовник со песок што паѓа"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Голема латинична буква М во крукче"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Црно квадратче"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Бело квадратче"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Црн триаголник свртен надесно"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Црн триаголник свртен налево"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Квадрат во бела средина"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Квадрат во црна средина"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Квадратче во бела средина"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Квадратче во црна средина"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Црно сонце со зраци"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Облак"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Црн телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Рамка за гласање, означена"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Чадор со капки дожд"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Топол напиток"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Бел показалец што покажува нагоре"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Бело насмеано лице"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Овен"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Бик"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Близнаци"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Рак"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Лав"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Девица"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Вага"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Скорпија"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Стрелец"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Јарец"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Водолија"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Риби"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Боја на карти црн пик"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Боја на карти црн треф"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Боја на карти црн херц"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Боја на карти црно каро"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Топли извори"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Црн универзален симбол за рециклирање"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Симбол инвалидска количка"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Сидро"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Знак за предупредување"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Знак висок напон"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Среден бел круг"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Среден црн круг"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Фудбалска топка"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бејзбол"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Снешко без снег"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Сонце зад облак"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Змијоносец"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Забранет влез"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Црква"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтана"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Знаме во дупка"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Едрилица"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Шатор"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Пумпа за гориво"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Црни ножици"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Бел голем знак за означување"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Авион"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Коверт"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Крената тупаница"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Крената рака"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Победничка рака"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Молив"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Црн врв од перо"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Задебелен знак за означување"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Задебелен х за множење"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Искри"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Ѕвездичка со осум страни"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Осумстрана црна ѕвезда"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Снегулка"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Искра"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Знак крст"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Крст со значење „негативно“ во квадрат"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Украсен црн прашалник"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Украсен бел прашалник"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Украсен бел извичник"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Симбол задебелен прашалник"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Задебелено црно срце"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Знак задебелен плус"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Знак задебелен минус"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Задебелен знак за делење"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Црна стрелка надесно"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Свртена јамка"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Јамка двапати свртена"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Стрелка насочена надесно, па свртена нагоре"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Стрелка насочена надесно, па свртена надолу"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Црна стрелка налево"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Црна стрелка нагоре"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Црна стрелка надолу"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Голем црн квадрат"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Голем бел квадрат"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Бела средна ѕвезда"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Голем задебелен круг"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Разбранувана црта"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Знак за промена на улога"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Идеограм „честитки“ во круг"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Идеограм „тајна“ во крукче"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Плочка за маџонг, црвен змеј"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Карта за играње, црн џокер"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Крвна група А"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Крвна група Б"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Крвна група О"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Паркинг"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Крвна група АБ"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL во квадрат"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"„Фино“ во квадрат"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Бесплатно во квадрат"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"„ИД“ во квадрат"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Ново во квадрат"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"„НГ“ во квадрат"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Во ред во квадрат"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"„СОС“ во квадрат"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Горе со извичник во квадрат"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"vs во квадрат"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"„Овде“ на катакана во квадрат"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"„Услуга“ на катакана во квадрат"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Идеограм „без трошоци“ во квадрат"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Идеограм „резервирано место“ во квадрат"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Идеограм „прохибиција“ во квадрат"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Идеограм „слободно“ во квадрат"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Идеограм „прифаќање“ во квадрат"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Идеограм „целосна исполнетост“ во квадрат"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Идеограм „платено“ во квадрат"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Идеограм „месечно“ во квадрат"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Идеограм „апликација“ во квадрат"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Идеограм „попуст“ во квадар"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Идеограм „работи“ во квадрат"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Заокружен идеограм „предност“"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Заокружен идеограм „прифати“"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Магловито"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Затворен чадор"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Ноќ со ѕвезди"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Изгрејсонце над планини"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Изгрејсонце"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Градски пејзаж на самрак"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Зајдисонце над градби"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Виножито"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Мост ноќе"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Бран на вода"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Млечниот Пат"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Европа и Африка на глобус"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Континентот Америка прикажан на глобус"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Азија и Австралија на глобус"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Глобус со меридијани"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Симбол млада месечина"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Симбол на месечина во наголемување"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Симбол на месечина во прва четвртина"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Симбол на испапчена месечина во наголемување"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Симбол на полна месечина"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Симбол на испапчена месечина во намалување"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Симбол на месечина во последна четвртина"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Симбол на месечина во намалување"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Месечина во наголемување"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Млада месечина со лице"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Месечина во прва четвртина со лице"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Месечина во последна четвртина со лице"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Полна месечина со лице"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Сонце со лице"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Блескава ѕвезда"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Ѕвезда што паѓа"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Костен"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Никулец"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Зимзеленo дрвo"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Листопадно дрво"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Палмово дрво"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Лале"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Цвет од цреша"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Роза"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Хибискус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Сончоглед"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Цвет"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Кочан пченка"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Оризов клас"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Билка"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Детелина со четири листа"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Лист од јавор"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Паднат лист"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Лист што трепери на ветар"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Печурка"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Домат"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Модар домат"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Грозје"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Диња"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Лубеница"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарина"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банана"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Црвено јаболко"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Зелено јаболко"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Круша"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Праска"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Цреши"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Јагода"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Хамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Парче пица"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Месо на коска"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Копан"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Оризов крекер"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Топче од ориз"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Варен ориз"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Кари и ориз"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Чинија што испарува"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Шпагети"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Леб"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Помфрит"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Печен сладок компир"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Оден"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Пржени ракчиња"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Рибин вртен колач"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Мек сладолед"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Струган мраз"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Сладолед"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Крофна"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Колаче"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Чоколада"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Бонбони"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Лижавче"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Крем од жолчки"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Грне со мед"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Шорткејк"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Кутија бенто"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Грне со храна"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Готвење"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Вилушка и нож"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Шолја за чај без рачка"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Шише и чаша со саќе"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Винска чаша"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Коктел-чаша"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропски пијалак"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Кригла за пиво"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Чукање со кригли пиво"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Шише за бебе"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Панделка"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Завиткан подарок"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Роденденска торта"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Фенер од тиква"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Новогодишна елка"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Дедо Мраз"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Огномет"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Жижица"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Балон"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Петарда за забави"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Топка со конфети"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Дрво танабата"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Вкрстени знамиња"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Украс со бор"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Јапонски кукли"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Коинобори"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Ѕвончиња за ветар"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Церемонија за гледање месечина"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Училишна торба"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Дипломска капа"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Коњ на рингишпил"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Панорамско тркало"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Тобоган"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Трска за риболов и риба"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Филмска камера"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кино"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Слушалки"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Уметничка палета"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Цилиндар"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Циркуски шатор"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Билет"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Клапа"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Изведувачки уметности"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Видеоигра"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Полн погодок"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Слот-машина"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Билијард"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Коцка"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Куглање"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Цвет со боја на карти"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Повеќе ноти"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гитара"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Музичка тастатура"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Труба"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Виолина"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Партитура"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Тркачка маица со лента"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Рекет и топче за тенис"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Скија и чизма за скијање"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскет и обрач"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Шаховско знаме"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордер"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Тркач"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Сурфер"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Трофеј"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Тркачки коњ"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Американски фудбал"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Топка за рагби"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Пливач"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Станбена зграда"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Куќа со градина"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Деловна зграда"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Јапонска пошта"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Европска пошта"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Болница"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банка"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Хотел"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Хотел на љубовта"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Продавница"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Училиште"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Стоковна куќа"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Фабрика"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Фенер изакаја"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Јапонски дворец"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Европски замок"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Стаорец"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Глушец"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Вол"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Воден бивол"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Крава"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Зајак"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Мачка"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Змеј"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Полжав"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Змија"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Коњ"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Овен"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Коза"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Овца"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Мајмун"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Петел"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Кокошка"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Куче"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Свиња"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Крмнак"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Слон"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Октопод"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Спирална школка"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Бубачка"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Мравка"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Медоносна пчела"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Бубамара"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Риба"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропска риба"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Риба пуфер"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Желка"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Пиле што се испилува"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Пиле"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Пиле свртено нанапред"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Птица"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудлица"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Едногрба камила"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Двогрба камила"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Делфин"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Лице на глушец"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Лице на крава"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Лице на тигар"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Лице на зајак"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Лице на мачка"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Лице на змеј"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Кит што исфрла вода"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Лице на коњ"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Лице на мајмун"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Лице на куче"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Лице на свиња"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Лице на жаба"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Лице на хрчак"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Лице на волк"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Лице на мечка"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Лице на панда"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Рилка"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Отпечатоци од шепа"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Очи"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Уво"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Нос"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Уста"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Јазик"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Бела рака со показалец што покажува нагоре"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Бела рака со показалец што покажува надолу"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Бела рака со показалец што покажува налево"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Бела рака со показалец што покажува надесно"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Знак рака во тупаница"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Знак рака што мавта"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Знак рака „Одлично“"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Знак за одобрување"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Знак за неодобрување"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Знак со раце што ракоплескаат"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Знак отворена рака"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Круна"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Женска капа"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Очила"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Вратоврска"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Маица со куси ракави"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Фармерки"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Фустан"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Женска облека"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Чанта"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Ташна"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Торбичка"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Машки чевел"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Спортски чевел"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Штикла"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Женска сандала"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Женска чизма"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Стапалки"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Силуета на биста"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Силуета на биста"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Момче"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Девојче"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Маж"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Жена"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Семејство"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Маж и жена се држат за раце"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Двајца мажи се држат за раце"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Две жени се држат за раце"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полицаец"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Жена со зајачки уши"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Невеста со превез"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Лице со руса коса"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Маж со гуа пи мао"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Маж со турбан"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Постар маж"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Постара жена"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Бебе"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Градежен работник"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцеза"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Јапонски џин"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Јапонски гоблин"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Дух"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Бебе ангел"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Вонземјанин"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Вонземско чудовиште"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Детиште"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Череп"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Работник на информации"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Гардист"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Танчер"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Кармин"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Лак за нокти"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Масажа на лице"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Фризура"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Берберски столб"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Пилула"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Отпечаток од бакнеж"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Љубовно писмо"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Прстен"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Скапоцен камен"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Бакнеж"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Двојка со срце"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Свадба"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Срце што чука"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Скршено срце"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Две срца"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Блескаво срце"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Срце што расте"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Срце со стрела"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Сино срце"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Зелено срце"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Жолто срце"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Пурпурно срце"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Срце со панделка"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Срца што се вртат"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Украс со срце"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Облик на дијамант со точка внатре"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Крушка за електрична светилка"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Симбол гнев"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Симбол за спиење"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Симбол судар"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Симбол капки пот"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Капка"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Симбол тире"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Куп каки"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Стегнат бицепс"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Симбол за вртоглавица"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Балон за говор"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Балон за мисла"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Бел цвет"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Симбол сто поени"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Торба за пари"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Размена на валути"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Знак за долар"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Кредитна картичка"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Банкнота со знак за јен"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Банкнота со знак за долар"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Банкнота со знак за евро"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Банкнота со знак за фунта"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Пари со крилја"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Графикон со нагорна тенденција и знак за јен"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Седиште"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Персонален компјутер"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Актовка"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Минидиск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Флопи диск"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптички диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Двд"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Папка за датотеки"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Отворена папка за датотеки"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Страница со свиткан дел"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Страница свртена нагоре"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Календар"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Календар од кој се кинат страници"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Регистар за картички"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Графикон со нагорна тенденција"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"График со надолна тенденција"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"График со ленти"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Табла со штипка"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Игличка"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Игличка со кружна глава"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Спојувалка"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Прав линијар"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Триаголен линијар"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Јазичиња за обележување"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Бележник"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Тетратка"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Тетратка со украсна корица"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Затворена книга"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Отворена книга"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Зелена книга"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Сина книга"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Портокалова книга"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Книги"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Значка за име"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Свиток"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Меморандум"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефонска слушалка"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пејџер"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс-апарат"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Сателитска антена"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Разглас за јавно обраќање"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Мегафон за навивање"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Сад за излезна пошта"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Сад за дојдовна пошта"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Пакет"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Симбол за е-пошта"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Дојдовно писмо"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Коверт над кој има стрелка нагоре"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Затворено сандаче со спуштено знаменце"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Затворено сандаче со кренато знаменце"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Отворено сандаче со кренато знаменце"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Отворено сандаче со спуштено знаменце"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Поштенска кутија"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Поштенска труба"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Весник"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобилен телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Мобилен телефон со стрелка надесно одлево"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Режим на вибрирање"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Знак за исклучување на мобилниот телефон"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Забрана за мобилни телефони"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Антена со цртички"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Видеокамера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Телевизор"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Видеокасета"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Извртени стрелки надесно"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Десна и лева стрелка свртени во круг надесно"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Десна и лева стрелка свртени во круг надесно, со крукче и бројот еден над нив"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Десна и лева стрелка свртени надесно во отворено крукче"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Десна и лева стрелка свртени налево во отворено крукче"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Симбол за ниска светлост"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Симбол за висока светлост"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Звучник со знак за исклучување"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Звучник"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Звучник со еден звучен бран"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Звучник со три звучни брана"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батерија"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Електричен приклучок"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Лупа свртена налево"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Лупа свртена надесно"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Катанец со пенкало за мастило"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Затворен катанец со клуч"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Клуч"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Катанец"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Отворен катанец"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Ѕвонче"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Ѕвонче со знак за исклучување"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Обележувач"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Симбол за врска"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Радиокопче"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Квадратче со стрелка налево"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Зборот „крај“ со стрелка налево над него"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Зборот „Вклучено“ со извичник со стрелка лево-десно над него"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Зборот „набрзо“ со стрелка надесно над него"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Зборот „Врв“ со стрелка нагоре над него"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Симбол „Не е за под 18-годишна возраст“"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Копче од тастатура „10“"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Симбол за внесување латинични големи букви"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Симбол за внесување латинични мали букви"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Симбол за внесување броеви"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Симбол за внесување симболи"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Симбол за внесување латинични букви"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Оган"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Електрична лампа"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Клуч"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Чекан"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Завртка и навртка"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Нож"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пиштол"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Кристална топка"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Шестстрана ѕвезда со точка во средина"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Јапонски симбол за почетник"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Трозабец амблем"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Копче со црн квадрат"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Копче со бел квадрат"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Голем црвен круг"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Голем син круг"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Голема портокалова баклава"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Голема сина баклава"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Мала портокалова баклава"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Мала сина баклава"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Црвен триаголник свртен нагоре"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Црвен триаголник свртен надолу"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Мал црвен триаголник свртен нагоре"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Мал црвен триаголник свртен надолу"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Часовник со лице, еден часот"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Часовник со лице, два часот"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Часовник со лице, три часот"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Часовник со лице, покажува четири часот"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Часовник со лице, пет часот"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Часовник со лице, шест часот"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Часовник со лице, седум часот"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Часовник со лице, осум часот"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Часовник со лице, девет часот"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Часовник со лице, десет часот"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Часовник со лице, единаесет часот"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Часовник со лице, дванаесет часот"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Часовник со лице, еден и триесет"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Часовник со лице, два и триесет часот"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Часовник со лице, три и триесет часот"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Часовник со лице, четири и триесет часот"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Часовник со лице, пет и триесет часот"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Часовник со лице, шест и триесет часот"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Часовник со лице, седум и триесет часот"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Часовник со лице, осум и триесет"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Часовник со лице, девет и триесет"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Часовник со лице, десет и триесет"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Часовник со лице, осум и триесет часот"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Часовник со лице, дванаесет и триесет"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Планината Фуџи"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токиска кула"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Статуата на слободата"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Силуета на Јапонија"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Мојаи"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Лице што се смее"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Насмеано лице со очи што се смеат"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Лице со солзи радосници"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Лице што се смее со отворена уста"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Лице што се потсмева со отворена уста и очи што се смеат"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Лице што се смее со отворена уста и студена пот"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Лице што се смее со отворена уста и затворени и стегнати очи"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Лице што се смее со ореол"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Лице што се смее со рогови"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Лице што намигнува"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Лице што се смее со очи што се смеат"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Лице што пробува вкусна храна"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Лице на кое му олеснало"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Насмеано лице со очи во форма на срциња"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Лице што се смее со очила за сонце"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Лице што се потсмева"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Неутрално лице"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Безизразно лице"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Лице на кое не му е интересно"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Лице со студена пот"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Замислено лице"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Збунето лице"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Збунето лице"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Лице што бакнува"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Лице што праќа бакнеж"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Лице што бакнува со насмеани очи"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Лице што бакнува со затворени очи"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Лице со исплазен јазик"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Лице со исплазен јазик и намигнато око"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Лице со исплазен јазик и затворени и стегнати очи"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Разочарано лице"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Загрижено лице"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Луто лице"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Лице со напрчени усни"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Расплакано лице"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Лице што истрајува"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Лице со изглед на триумф"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Разочарано лице, но на кое му олеснало"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Намуртено лице со отворена уста"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Очајно лице"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Страшливо лице"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Уморно лице"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Поспано лице"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Уморно лице"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Лице што прави гримаси"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Лице што плаче гласно"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Лице со отворена уста"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Стишено лице"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Лице со отворена уста и студена пот"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Лице што вреска од страв"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Восхитено лице"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Вцрвено лице"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Лице што спие"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Лице со вртоглавица"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Лице без уста"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Лице со медицинска маска"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Насмеано лице со очи што се смеат"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Лице на мачка со солзи радосници"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Лице што се смее со отворена уста"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Лице на мачка со очи во облик на срциња"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Лице на мачка со иронична насмевка"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Лице на мачка што бакнува со затворени очи"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Лице на мачка со напрчени усни"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Лице на мачка што плаче"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Уморно лице на мачка"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Лице со гест „не може“"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Лице со гест „одлично“"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Човек што се поклонува длабоко"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Мајмун „ништо не гледам“"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Мајмун „ништо не слушам“"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Мајмун „ништо не зборувам“"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Среќно лице со една крената рака"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Човек со две кренати раце во прослава"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Намуртен човек"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Човек со напрчено лице"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Човек со прекрстени раце"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Хеликоптер"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Парна локомотива"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Железнички вагон"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Брз воз"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Брз воз со звук од куршум"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Воз"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Лесна железница"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станица"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвај"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Трамвајски вагон"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Автобус што доаѓа"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Тролејбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобуска постојка"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Минибус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Брза помош"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Пожарна кола"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полициска кола"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Полициски автомобил што доаѓа"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Такси што доаѓа"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автомобил"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Автомобил што доаѓа"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Рекреативно возило"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Камион за испораки"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Шлепер"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Едношинска железница"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Планинска железница"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Висечка железница"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Планинска жичница"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Воздушен трамвај"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Брод"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Чун"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Глисер"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Хоризонтален семафор"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Вертикални семафори"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Знак „Градежни работи“"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Полициска кола со ротационо светло"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Триаголно знаме на столб"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Врата"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Знак за забранет влез"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Симбол за пушење"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Симбол за забрането пушење"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Симбол „Отпадоците фрлајте ги во канта“"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Симбол „Не правете смет“"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Симбол „Вода за пиење“"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Симбол за забрането пиење на водата"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Забрана за велосипеди"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Велосипедист"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Планински велосипедист"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Пешак"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Забрана за пешаци"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Деца преминуваат улица"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Симбол за машки тоалет"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Женски симбол"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Тоалет"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Симбол за бебе"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Тоалет"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"ВЦ-школка"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Туш"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Бања"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Када"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Пасошка контрола"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Царина"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Подигнување багаж"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Оставен багаж"</string>
+</resources>
diff --git a/java/res/values-mk-rMK/strings-talkback-descriptions.xml b/java/res/values-mk-rMK/strings-talkback-descriptions.xml
index 12a6413..0ca80fd 100644
--- a/java/res/values-mk-rMK/strings-talkback-descriptions.xml
+++ b/java/res/values-mk-rMK/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"Вклучете слушалки за да ги слушнете копчињата за лозинката гласно изговорени."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"Тековниот текст е %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"Не е внесен текст"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> го поправи <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> со <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> врши автоматска корекција"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Нема предлог"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Непознат знак"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"копче Shift"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Повеќе симболи"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"копче Shift"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Симболи"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"копче Shift"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"Бришење"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Симболи"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Букви"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Броеви"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Поставки"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Таб"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Празно место"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Гласовен запис"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Емотикони"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Враќање"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Пребарување"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Точка"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Смени јазик"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Следно"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Претходно"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Овозможено префрлање"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"овозможено Caps lock"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Режим на симболи"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"Режим на повеќе симболи"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Режим на букви"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Телефонски режим"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Режим на телефонски симболи"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Тастатурата е сокриена"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"Се прикажува тастатура <xliff:g id="KEYBOARD_MODE">%s</xliff:g>"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"датум"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"датум и време"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"е-пошта"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"размена на пораки"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"број"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"телефон"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"текст"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"време"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"УРЛ"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Неодамнешни"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Луѓе"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Предмети"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Природа"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Места"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Симболи"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Емотикони"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"Голема буква <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"Голема буква I"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Голема буква I, со точка одозгора"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Непознат симбол"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Непозната емотикона"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Досадно лице"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Засрамено лице"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Лице со очила за сонце"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Изненадено лице"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Лице што бакнува"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Намуртено лице"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Достапни се алтернативни знаци"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Алтернативните знаци се отфрлени"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Достапни се алтернативни предлози"</string>
diff --git a/java/res/values-mk-rMK/strings.xml b/java/res/values-mk-rMK/strings.xml
index d7945e3..6d2846c 100644
--- a/java/res/values-mk-rMK/strings.xml
+++ b/java/res/values-mk-rMK/strings.xml
@@ -20,355 +20,188 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for english_ime_input_options (3909945612939668554) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
-    <skip />
-    <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
-    <skip />
-    <!-- no translation found for sound_on_keypress (6093592297198243644) -->
-    <skip />
-    <!-- no translation found for popup_on_keypress (123894815723512944) -->
-    <skip />
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key (5915478828318774384) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
-    <skip />
-    <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
-    <skip />
-    <!-- no translation found for settings_system_default (6268225104743331821) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict (4435317977804180815) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
-    <skip />
-    <!-- no translation found for use_personalized_dicts (5167396352105467626) -->
-    <skip />
+    <string name="english_ime_input_options" msgid="3909945612939668554">"Опции за внесување"</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="settings_screen_preferences" msgid="2696713156722014624">"Претпочитани поставки"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Сметки и приватност"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Изглед и распоред"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Пишување со движење"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Корекција на текст"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Напредни"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Овозможи поделена тастатура"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Синхронизирање на таст. на Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхронизирањето е вклучено"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Синхронизирајте го личниот речник низ уредите"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Синхронизирај сега"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Избриши податоци од облакот"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Ги брише синхронизираните податоци од Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Синхронизираните податоци ќе се избр. од облак. Дали сте сигурни?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Избриши"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Откажи"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Вашиот личен речник ќе се синхронизира и ќе се создаде резервна копија на серверите на Google. Може да се собираат статистички информации за честотата на зборовите за помош при подобрување на нашите производи. Собирањето и користењето на сите информации ќе биде во согласност со "<a href="https://www.google.com/policies/privacy">"Политиката за приватност на Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Додајте сметка на Google на уредов за овозможување на функцијава"</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">"Копчето за менување јазици покрива и други методи на внес"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"Копче за промена на јазик"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Покажи кога се овозможени повеќе влезни јазици"</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> ms"</string>
+    <string name="settings_system_default" msgid="6268225104743331821">"Стандардно за системот"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Предложи имиња на контакт"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Употреби имиња од Контакти за предлози и корекции"</string>
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"Персонализирани предлози"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"Подобри <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <!-- no translation found for use_double_space_period (8781529969425082860) -->
-    <skip />
-    <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
-    <skip />
-    <!-- no translation found for auto_cap (1719746674854628252) -->
-    <skip />
-    <!-- no translation found for auto_cap_summary (7934452761022946874) -->
-    <skip />
-    <!-- no translation found for edit_personal_dictionary (3996910038952940420) -->
-    <skip />
-    <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
-    <skip />
-    <!-- no translation found for main_dictionary (4798763781818361168) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
-    <skip />
-    <!-- no translation found for auto_correction (7630720885194996950) -->
-    <skip />
-    <!-- no translation found for auto_correction_summary (5625751551134658006) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) -->
-    <skip />
-    <!-- no translation found for bigram_prediction (1084449187723948550) -->
-    <skip />
-    <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
-    <skip />
-    <!-- no translation found for gesture_input (826951152254563827) -->
-    <skip />
-    <!-- no translation found for gesture_input_summary (9180350639305731231) -->
-    <skip />
-    <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware (2078291600664682496) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware_summary (4371385818348528538) -->
-    <skip />
-    <!-- no translation found for voice_input (3583258583521397548) -->
-    <skip />
-    <!-- no translation found for voice_input_disabled_summary (8141750303464726129) -->
-    <skip />
-    <!-- no translation found for configure_input_method (373356270290742459) -->
-    <skip />
-    <!-- no translation found for language_selection_title (1651299598555326750) -->
-    <skip />
-    <!-- no translation found for send_feedback (1780431884109392046) -->
-    <skip />
-    <!-- no translation found for select_language (3693815588777926848) -->
-    <skip />
-    <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
-    <skip />
-    <!-- no translation found for has_dictionary (6071847973466625007) -->
-    <skip />
-    <!-- no translation found for keyboard_layout (8451164783510487501) -->
-    <skip />
-    <!-- no translation found for subtype_en_GB (88170601942311355) -->
-    <skip />
-    <!-- no translation found for subtype_en_US (6160452336634534239) -->
-    <skip />
-    <!-- no translation found for subtype_es_US (5583145191430180200) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_GB (1931018968641592304) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_US (8809311287529805422) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_es_US (510930471167541338) -->
-    <skip />
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <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 />
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
-    <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
-    <skip />
-    <!-- no translation found for add_style (6163126614514489951) -->
-    <skip />
-    <!-- no translation found for add (8299699805688017798) -->
-    <skip />
-    <!-- no translation found for remove (4486081658752944606) -->
-    <skip />
-    <!-- no translation found for save (7646738597196767214) -->
-    <skip />
-    <!-- no translation found for subtype_locale (8576443440738143764) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
-    <skip />
-    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
-    <skip />
-    <!-- no translation found for enable (5031294444630523247) -->
-    <skip />
-    <!-- no translation found for not_now (6172462888202790482) -->
-    <skip />
-    <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
-    <skip />
-    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
-    <skip />
-    <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_confirm_install_message (4782116251651288054) -->
-    <skip />
-    <!-- no translation found for error (8940763624668513648) -->
-    <skip />
-    <!-- no translation found for button_default (3988017840431881491) -->
-    <skip />
-    <!-- no translation found for setup_welcome_title (6112821709832031715) -->
-    <skip />
-    <!-- no translation found for setup_welcome_additional_description (8150252008545768953) -->
-    <skip />
-    <!-- no translation found for setup_start_action (8936036460897347708) -->
-    <skip />
-    <!-- no translation found for setup_next_action (371821437915144603) -->
-    <skip />
-    <!-- no translation found for setup_steps_title (6400373034871816182) -->
-    <skip />
-    <!-- no translation found for setup_step1_title (3147967630253462315) -->
-    <skip />
-    <!-- no translation found for setup_step1_instruction (2578631936624637241) -->
-    <skip />
-    <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
-    <skip />
-    <!-- no translation found for setup_step1_action (4366513534999901728) -->
-    <skip />
-    <!-- no translation found for setup_step2_title (6860725447906690594) -->
-    <skip />
-    <!-- no translation found for setup_step2_instruction (9141481964870023336) -->
-    <skip />
-    <!-- no translation found for setup_step2_action (1660330307159824337) -->
-    <skip />
-    <!-- no translation found for setup_step3_title (3154757183631490281) -->
-    <skip />
-    <!-- no translation found for setup_step3_instruction (8025981829605426000) -->
-    <skip />
-    <!-- no translation found for setup_step3_action (600879797256942259) -->
-    <skip />
-    <!-- no translation found for setup_finish_action (276559243409465389) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon (5008028590593710830) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) -->
-    <skip />
-    <!-- no translation found for app_name (6320102637491234792) -->
-    <skip />
-    <!-- no translation found for dictionary_provider_name (3027315045397363079) -->
-    <skip />
-    <!-- no translation found for dictionary_service_name (6237472350693511448) -->
-    <skip />
-    <!-- no translation found for download_description (6014835283119198591) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_title (8091417676045693313) -->
-    <skip />
-    <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_summary (5305694987799824349) -->
-    <skip />
-    <!-- no translation found for user_dictionaries (3582332055892252845) -->
-    <skip />
-    <!-- no translation found for default_user_dict_pref_name (1625055720489280530) -->
-    <skip />
-    <!-- no translation found for dictionary_available (4728975345815214218) -->
-    <skip />
-    <!-- no translation found for dictionary_downloading (2982650524622620983) -->
-    <skip />
-    <!-- no translation found for dictionary_installed (8081558343559342962) -->
-    <skip />
-    <!-- no translation found for dictionary_disabled (8950383219564621762) -->
-    <skip />
-    <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) -->
-    <skip />
-    <!-- no translation found for no_dictionaries_available (8039920716566132611) -->
-    <skip />
-    <!-- no translation found for check_for_updates_now (8087688440916388581) -->
-    <skip />
-    <!-- no translation found for last_update (730467549913588780) -->
-    <skip />
-    <!-- no translation found for message_updating (4457761393932375219) -->
-    <skip />
-    <!-- no translation found for message_loading (5638680861387748936) -->
-    <skip />
-    <!-- no translation found for main_dict_description (3072821352793492143) -->
-    <skip />
-    <!-- no translation found for cancel (6830980399865683324) -->
-    <skip />
-    <!-- no translation found for go_to_settings (3876892339342569259) -->
-    <skip />
-    <!-- no translation found for install_dict (180852772562189365) -->
-    <skip />
-    <!-- no translation found for cancel_download_dict (7843340278507019303) -->
-    <skip />
-    <!-- no translation found for delete_dict (756853268088330054) -->
-    <skip />
-    <!-- no translation found for should_download_over_metered_prompt (1583881200688185508) -->
-    <skip />
-    <!-- no translation found for download_over_metered (1643065851159409546) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (2176209579313941583) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_title (4583842811218581658) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_description (1075194169443163487) -->
-    <skip />
-    <!-- no translation found for toast_downloading_suggestions (6128155879830851739) -->
-    <skip />
-    <!-- no translation found for version_text (2715354215568469385) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
-    <skip />
-    <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
-    <skip />
+    <string name="use_double_space_period" msgid="8781529969425082860">"Точка со два простора"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Со двоен допир на празно место се вметнува точка и празно место"</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_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>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Агресивна"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Многу агресивно"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"Предлози за следен збор"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"Употребете го претходниот збор за предлози"</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="gesture_space_aware" msgid="2078291600664682496">"Движење за фрази"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Внеси празни места при движења со лизгање до тоа копче"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Копче за влез на глас"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Не се овозможени методи за гласовно внесување. Проверете ги поставките за Јазик и внесување."</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Конфигурирај методи на влез"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Јазици"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Помош и повратни информации"</string>
+    <string name="select_language" msgid="5709487854987078367">"Јазици"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Допрете повторно за да се зачува"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Допри тука да се зачува"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"Речникот е достапен"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"Тема на тастатурата"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Префрли сметки"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Не се избрани сметки"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Во моментов ја користите <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Во ред"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Откажи"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Одјави се"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Изберете ја сметката што ќе ја користите"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"англиски (ОК)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"англиски (САД)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"шпански (САД)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Српски (латиница)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"англиски (ОК) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"англиски (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"шпански (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Српски (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционален)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Компактна)"</string>
+    <string name="subtype_no_language" msgid="7137390094240139495">"Нема јазик (азбука)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Азбука (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Азбука (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Азбука (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Азбука (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Азбука (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Азбука (PC)"</string>
+    <string name="subtype_emoji" msgid="7483586578074549196">"Емотикони"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"Тема на тастатурата"</string>
+    <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_keypress_vibration_duration_settings" msgid="7918341459947439226">"Траење на вибрација од копче"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Копче за јачина на звук"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Доцнење на долго притискање копче"</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">"Сега може да ги впишете сите омилени апликации со <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="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="5638680861387748936">"Се вчитува..."</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Главен речник"</string>
+    <string name="cancel" msgid="6830980399865683324">"Откажи"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"Поставки"</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="1583881200688185508">"За избраниот јазик на мобилниот уред има достапен речник.&lt;br/&gt; Препорачуваме да го &lt;b&gt;преземете&lt;/b&gt; речникот за <xliff:g id="LANGUAGE_NAME">%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="4583842811218581658">"Достапен е речник за <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Притиснете за да прегледате и преземете"</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Се презема: предлозите за <xliff:g id="LANGUAGE_NAME">%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">"Во ред"</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">"Изборна кратенка"</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/values-ml-rIN/strings-emoji-descriptions.xml b/java/res/values-ml-rIN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..2fad192
--- /dev/null
+++ b/java/res/values-ml-rIN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"പകർപ്പവകാശത്തിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"രജിസ്‌ട്രേഡ് ചിഹ്നം"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"ഇരട്ട ആശ്ചര്യ ചിഹ്നം"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"ആശ്ചര്യചിഹ്നവും ചോദ്യ അടയാളവും"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"ട്രേഡ് മാർക്ക് അടയാളം"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"വിവരങ്ങൾക്കുള്ള ഉറവിടം"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"ഇടത് വശത്തേക്കും വലത് വശത്തേക്കുമുള്ള അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"മുകളിലേക്കും താഴേക്കുമുള്ള അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"വടക്ക്പടിഞ്ഞാറ് അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"വടക്കുകിഴക്ക് അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"തെക്കുക്കിഴക്ക് അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"തെക്കുപടിഞ്ഞാറ് അമ്പടയാളം"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"കൊളുത്തോടുകൂടിയ ഇടതുവശത്തേക്ക് പോകുന്ന അമ്പടയാളം"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"കൊളുത്തോടുകൂടിയ വലതുവശത്തേക്ക് പോകുന്ന അമ്പടയാളം"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"കാ‍ണുക"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"മണൽ ഘടികാരം"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"വലതുവശത്തേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ഇരട്ട ത്രികോണം"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"ഇടതുവശത്തേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ഇരട്ട ത്രികോണം"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"മുകളിലേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ഇരട്ട ത്രികോണം"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"താഴേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ഇരട്ട ത്രികോണം"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"അലാറം ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"ഒഴുകുന്ന മണലുള്ള മണൽഘടികാരം"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"വൃത്തത്തിനുള്ളിൽ ലാറ്റിൻ വലിയക്ഷരത്തിൽ \'m\'"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"കറുത്ത ചെറിയ ചതുരം"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"വെളുത്ത ചെറിയ ചതുരം"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"വലതുവശത്തേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ത്രികോണം"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"ഇടതുവശത്തേക്ക് പോയിന്റുചെയ്‌തിരിക്കുന്ന കറുത്ത ത്രികോണം"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"വെളുത്ത ഇടത്തരം ചതുരം"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"കറുത്ത ഇടത്തരം ചതുരം"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"വെളുത്ത ഇടത്തരം ചെറിയ ചതുരം"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"കറുത്ത ഇടത്തരം ചെറിയ ചതുരം"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"രശ്‌മികളുള്ള കറുത്ത സൂര്യൻ"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"മേഘം"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"കറുത്ത ടെലിഫോൺ"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"ശരി അടയാളത്തോടുകൂടിയ ബാലറ്റ് ബോക്‌സ്"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"കുടയും മഴത്തുള്ളികളും"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"ചൂട് പാനീയം"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"മുകളിലേക്ക് ചൂണ്ടുന്ന മുൻ ചൂണ്ടുവിരൽ"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"വെളുത്ത പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"മേടരാശി"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"ഇടവരാശി"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"മിഥുന രാശി"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"കർക്കിടകരാശി"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"ചിങ്ങരാശി"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"കാന്നിരാശി"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"തുലാം രാശി"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"വൃശ്ചികരാശി"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"ധനുരാശി"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"മകരരാശി"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"കുഭരാശി"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"മീനരാശി"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"കറുത്ത സ്‌പേഡ് സ്യൂട്ട്"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"കറുത്ത ക്ല്ബ് സ്യൂട്ട്"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"കറുത്ത ഹാർട്ട് സ്യൂട്ട്"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"കറുത്ത ഡയമണ്ട് സ്യൂട്ട്"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"നീരാവി"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"കറുത്ത യൂണിവേഴ്‌സൽ റീസൈക്കിൾ ചിഹ്നം"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"വീൽചെയർ ചിഹ്നം"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"നങ്കൂരം"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"മുന്നറിയിപ്പ് ചിഹ്നം"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"ഉയർന്ന വോൾട്ടേജ് ചിഹ്നം"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"ഇടത്തരം വെളുത്ത വൃത്തം"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"ഇടത്തരം കറുത്ത വൃത്തം"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"സോക്കർ ബോൾ"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"ബേസ്ബോൾ"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"മഞ്ഞില്ലാത്ത മഞ്ഞുമനുഷ്യൻ"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"മേഘത്തിൻ പുറകിലുള്ള സൂര്യൻ"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ഒഫിയൂക്കസ്"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"പ്രവേശനമില്ല"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"ക്രിസ്തീയ ദേവാലയം"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"ജലധാര"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"കുഴിക്കുള്ളിൽ സ്ഥാപിച്ചിരിക്കുന്ന പതാക"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"പായ്‌‌വഞ്ചി"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"കൂടാരം"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"പെട്രോൾ പമ്പ്"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"കറുത്ത കത്രിക"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"കറുത്ത വലുപ്പമുള്ള ശരിയടയാളം"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"വിമാനം"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"എൻവലപ്പ്"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"ഉയർത്തിയ മുഷ്‌ടി"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"ഉയർത്തിയ കൈ"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"വിജയം എന്നത് കൈകൊണ്ട് കാണിക്കൽ"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"പെൻസിൽ"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"കറുത്ത മുന"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"വലുപ്പമുള്ള ശരിയടയാളം"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"കറുത്ത ഗുണനചിഹ്നം \'x\'"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"തിളങ്ങുന്നവ"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"എട്ട് മുനകളുള്ള നക്ഷത്ര ചിഹ്നം"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"എട്ട് പോയിന്റുള്ള കറുത്ത നക്ഷത്രം"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"മഞ്ഞുകട്ട"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"തിളക്കമുള്ളത്"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"ഗുണന ചിഹ്നം"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"നെഗറ്റീവ് ചതുരത്തിലുള്ള ഗുണന ചിഹ്നം"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"കടുത്ത ചോദ്യചിഹ്ന ഓർണമെന്റ്"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"വെളുത്ത ചോദ്യ ചിഹ്ന ഓർണമെന്റ്"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"വെളുത്ത ആശ്ചര്യചിഹ്ന ഓർണമെന്റ്"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"വലുപ്പമുള്ള വെളുത്ത ആശ്ചര്യചിഹ്നം"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"വലിയ കറുത്ത ഹൃദയചിഹ്നം"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"വലുപ്പമുള്ള സങ്കലന ചിഹ്നം"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"വലുപ്പമുള്ള ന്യൂന ചിഹ്നം"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"വലുപ്പമുള്ള ഹരണ ചിഹ്നം"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"വലതുവശത്തേക്കുള്ള കറുത്ത അമ്പടയാളം"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"ചുരുണ്ട കുരുക്ക്"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"ഇരട്ട ചുരുണ്ട കുരുക്ക്"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"വലതുവശത്തേക്ക് വന്ന് മുകളിലേക്ക് വളയുന്ന അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"വലതുവശത്തേക്ക് വന്ന് താഴേക്ക് വളയുന്ന അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"വലതുവശത്തേക്ക് പോകുന്ന കറുത്ത അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"മുകളിലേക്ക് പോകുന്ന കറുത്ത അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"താഴേക്ക് പോകുന്ന കറുത്ത അമ്പടയാളം"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"കറുത്ത വലിയ ചതുരം"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"വെളുത്ത വലിയ ചതുരം"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"വെളുത്ത ഇടത്തരം നക്ഷത്രം"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"വലുപ്പമുള്ള വൃത്തം"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"വേവി ഡാഷ്"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"പാർട്ട് ആൾട്ടർനേഷൻ അടയാളം"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"വൃത്താകൃതിയിലുള്ള അഭിനന്ദന ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"വൃത്താകൃതിയിലുള്ള രഹസ്യ ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"മജോംഗ് ടൈൽ റെഡ് ഡ്രാഗൺ"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"പ്ലേയിംഗ് കാർഡ് ബ്ലാക്ക് ജോക്കർ"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"രക്ത തരം A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"രക്ത തരം B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"രക്ത തരം O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"പാർക്കുചെയ്യാനുള്ള സ്ഥലം"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"രക്ത തരം AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"ചതുരാകൃതിയിലുള്ള CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"ചതുരാകൃതിയിലുള്ള കൂൾ"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"ചതുരാകൃതിയിലുള്ള ഫ്രീ"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ചതുരാകൃതിയിലുള്ള ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"ചതുരാകൃതിയിലുള്ള ന്യൂ"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"ചതുരാകൃതിയിലുള്ള N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"ചതുരാകൃതിയിലുള്ള OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"ചതുരാകൃതിയിലുള്ള SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"ചതുരാകൃതിയിലുള്ള ആശ്ചര്യ ചിഹ്നത്തോടുകൂടിയുള്ള അപ്പ്"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"ചതുരാകൃതിയിലുള്ള vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"ചതുരാകൃതിയിലുള്ള കാറ്റക്കാനാ ഹിയർ"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"ചതുരാകൃതിയിലുള്ള കാറ്റക്കാനാ സർവ്വീസ്"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"ചതുരാകൃതിയിലുള്ള ചാർജ്ജ് ഫ്രീ ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"ചതുരാകൃതിയിലുള്ള റിസർവ്‌ഡ് സീറ്റ് ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"ചതുരാകൃതിയിലുള്ള പ്രൊഹിബിഷൻ ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"ചതുരാകൃതിയിലുള്ള വേക്കൻസി ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"ചതുരാകൃതിയിലുള്ള കൈക്കൊള്ളൽ ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"ചതുരാകൃതിയിലുള്ള പൂർണ്ണ ഒക്യുപ്പെൻസി ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"ചതുരാകൃതിയിലുള്ള പെയ്‌ഡ് ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"ചതുരാകൃതിയിലുള്ള മാസം തോറും എന്ന ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"ചതുരാകൃതിയിലുള്ള അപ്ലിക്കേഷൻ ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"ചതുരാകൃതിയിലുള്ള ഡിസ്‌കൗണ്ട് ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"ബിസിനസ്സിലെ ചതുരാകൃതിയിലുള്ള ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"വൃത്താകൃതിയിലുള്ള അഡ്‌വാന്റേജ് ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"വൃത്താകൃതിയിലുള്ള അക്‌സപ്‌റ്റ് ഐഡിയോഗ്രാഫ്"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"കൊടുങ്കാറ്റ്"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"മങ്ങിയത്"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"അടച്ച കുട"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"നക്ഷത്രങ്ങൾ നിറഞ്ഞ രാത്രി"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"മലമുകളിലെ സൂര്യോദയം"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"സൂര്യോദയം"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"നഗരത്തിലെ സന്ധ്യാസമയം"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"കെട്ടിടങ്ങൾക്ക് മുകളിലെ സൂര്യാസ്‌തമയം"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"മഴവില്ല്"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"പാലത്തിന്റെ രാത്രിക്കാഴ്‌ച"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"ജലതരംഗം"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"അഗ്‌നിപർവ്വതം"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"ക്ഷീരപഥം"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"യൂറോപ്പ്-ആഫ്രിക്ക ഭൗമ ഗ്ലോബ്"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"അമേരിക്കാസ് ഭൗമ ഗ്ലോബ്"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"ഏഷ്യാ ആസ്‌ട്രേലിയ ഭൗമ ഗ്ലോബ്"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"ധ്രുവരേഖകൾ ഉള്ള ഗ്ലോബ്"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"അമാവാസി"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"ചന്ദ്രക്കല പൂർണ്ണത പ്രാപിക്കുന്ന അടയാളം"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"അർദ്ധ പൗർണ്ണമി"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"പൗർണ്ണമിയോടടുക്കുന്ന ചന്ദ്ര അടയാളം"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"പൂർണ്ണചന്ദ്ര അടയാളം"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"പൗർണ്ണമിയിൽ നിന്ന് അമാവാസിയിലേക്ക് മാറുന്ന അടയാളം"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"അർദ്ധ അമാവാസി"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"വിളറിയ ചന്ദ്രൻ"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"ചന്ദ്രക്കല"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"മുഖം ദൃശ്യമാകുന്ന അമാവാസി"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"മുഖം ദൃശ്യമാകുന്ന അർദ്ധ പൗർണ്ണമി"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"മുഖം ദൃശ്യമാകുന്ന അർദ്ധ അമാവാസി"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"മുഖം ദൃശ്യമാകുന്ന പൂർണ്ണ ചന്ദ്രൻ"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"മുഖം ദൃശ്യമാകുന്ന സൂര്യൻ"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"തിളങ്ങുന്ന നക്ഷത്രം"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"വാൽനക്ഷത്രം"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"ചെസ്‌റ്റ്നട്ട്"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"തളിര്"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"നിത്യഹരിത മരം"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"ഇലപൊഴിയും മരം"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"പന"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"കള്ളിമുൾച്ചെടി"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"റ്റുലിപ്"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"ചെറി ബ്ലോസം"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"റോസ്"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"ചെമ്പരത്തി"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"സൂര്യകാന്തി"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"പുഷ്‌പം"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"ചോളം"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"നെല്ല്"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"കുറ്റിച്ചെടി"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"നാലില ക്ലോവർ സസ്യം"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"മാപ്പിൾ ഇല"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"പൊഴിഞ്ഞുവീണ ഇല"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"കാറ്റിൽ പാറിക്കളിക്കുന്ന ഇല"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"കൂൺ"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"തക്കാളി"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"വഴുതന"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"മുന്തിരി"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"മത്തങ്ങ"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"തണ്ണിമത്തൻ"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"ടാംഗറിൻ"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"നാരങ്ങ"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"വാഴപ്പഴം"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"പൈനാപ്പിൾ"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"ചുവന്ന ആപ്പിൾ"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"പച്ച ആപ്പിൾ"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"പിയർ"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"പീച്ച്"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"ചെറി"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"സ്‌ട്രോബെറി"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ഹാംബർഗർ"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"പിസ്സയുടെ കഷ്‌ണം"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"എല്ലും ഇറച്ചിയും"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"കോഴിക്കാൽ"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"റൈസ്‌ ക്രാക്കർ"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"അരിയുണ്ട"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"ചോറ്"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"ചോറും കറിയും"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"ആവിവരുന്ന പാത്രം"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"സ്‌പാഗെട്ടി"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ബ്രെഡ്"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"ഫ്രഞ്ച് ഫ്രൈസ്"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"പൊരിച്ച മധുരക്കിഴങ്ങ്"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"ഡാൻഗോ"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ഒഡെൻ"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"സുഷി"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"വറുത്ത ചെമ്മീൻ"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"ചുരുൾ രൂപത്തിലുള്ള ഫിഷ് കേക്ക്"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"സോഫ്റ്റ് ഐസ്‌ക്രീം"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"ഷേവ്‌ഡ് ഐസ്"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ഐസ്‌ക്രീം"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ഡോനട്ട്"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"കുക്കി"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"ചോക്കലേറ്റ് ബാർ"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"മിഠായി"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"ലോലിപോപ്പ്"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"കസ്‌റ്റാർഡ്"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"തേൻ കുടം"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ഷോർട്ട്‌കേക്ക്"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"ബെന്റോ ബോക്‌‌സ്"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"ഭക്ഷണപാത്രം"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"പാചകം"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ഫോർക്കും കത്തിയും"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"കൈപ്പിടിയില്ലാത്ത ചായക്കപ്പ്"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"സേക്ക് കുപ്പിയും കപ്പും"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"വൈൻ ഗ്ലാസ്"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"കോക്ക്ടെയ്‌ൽ ഗ്ലാസ്"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"ട്രോപ്പിക്കൽ ഡ്രിങ്ക്"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"ബിയർ മഗ്ഗ്"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ചേർന്നിരിക്കുന്ന ബിയർ മഗ്ഗുകൾ"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"പാൽകുപ്പി"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"റിബൺ"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"സമ്മാനപ്പൊതി"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"ജന്മദിനകേക്ക്"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"ജാക്ക്-ഓ-ലാന്റേൺ"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"ക്രിസ്‌മസ് ട്രീ"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"ക്രിസ്‌മസ് അപ്പൂപ്പൻ"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"കരിമരുന്ന് പ്രയോഗം"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"കമ്പിത്തിരി"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"ബലൂൺ"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"പാർട്ടി പോപ്പർ"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"വർണ്ണ ബോൾ"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"ടാനബാറ്റ ട്രീ"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"കുറുകെവെച്ച പതാകകൾ"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"അലങ്കരിച്ച പൈൻ"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"ജാപ്പനീസ് പാവകൾ"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"കാർപ്പ് സ്‌ട്രീമെർ"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"വിൻഡ് ചിം"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"പൂർണ്ണചന്ദ്രനെ കാണൽ ചടങ്ങ്"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"സ്‌കൂൾ ബാഗ്"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"ബിരുദ തൊപ്പി"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"കറങ്ങുന്ന കുതിര"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"യന്ത്ര ഊഞ്ഞാൽ"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"റോളർ കോസ്‌റ്റർ"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"ചൂണ്ടയും മീനും"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"മൈക്രോഫോണ്‍"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"മൂവി ക്യാമറ"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"സിനിമ"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"ഹെഡ്ഫോൺ"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"ചായപ്പലക"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"ടോപ്പ് ഹാറ്റ്"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"സർക്കസ് കൂടാരം"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"ടിക്കറ്റ്"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"ക്ലാപ്പർ ബോർഡ്"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"പ്രകടന കലകൾ"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"വീഡിയോ ഗെയിം"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"ലക്ഷ്യസ്ഥാനം കൊള്ളിക്കുക"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"സ്ലോട്ട് യന്ത്രം"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"ബില്യാർഡ്‌സ്"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"ഗെയിം ഡൈ"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"ബോളിംഗ്"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"ഫ്ലവർ പ്ലേയിംഗ് കാർഡുകൾ"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"സംഗീത ലിപി"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"നിരവധി സംഗീത ലിപികൾ"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"സാക്സഫോൺ"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"ഗിത്താർ"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"സംഗീത കീബോർഡ്"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"കാഹളം"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"വയലിൻ"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"സംഗീത സ്‌കോർ"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"സാഷുള്ള റണ്ണിംഗ് ഷർട്ട്"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"ടെന്നീസ് റാക്കറ്റും ബോളും"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"സ്‌കീയും സ്‌കീ ബൂട്ടും"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"ബാസ്‌‌ക്കറ്റ് ബോളും വളയവും"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"ചതുരാടയാളമുള്ള കൊടി"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"സ്‌നോബോർഡർ"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"ഓട്ടക്കാരൻ"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"സർഫർ"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ട്രോഫി"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"കുതിര പന്തയം"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"അമേരിക്കൻ ഫുട്ബോൾ"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"റഗ്ഗി ഫുട്ബോൾ"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"നീന്തുന്നയാൾ"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"വീടുനിർമ്മാണം"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"പൂന്തോട്ടനുള്ള വീട്"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"ഓഫീസ് കെട്ടിടം"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"ജാപ്പനീസ്‌ പോസ്‌റ്റ് ഓഫീസ്"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"യൂറോപ്പ്യൻ പോസ്‌റ്റ് ഓഫീസ്"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"ആശുപത്രി"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ബാങ്ക്"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ഓട്ടോമേറ്റഡ് ടെല്ലർ മെഷീൻ"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ഹോട്ടൽ"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"ലൗ ഹോട്ടൽ"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"കൺവീനിയൻസ് സ്‌റ്റോർ"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"സ്‌കൂൾ"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ഡിപ്പാർട്ട്‌മെന്റ് സ്‌റ്റോർ"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"ഫാക്ടറി"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"ഇസാകയാ വിളക്ക്"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"ജാപ്പനീസ് കോട്ട"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"യൂറോപ്പ്യൻ കോട്ട"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"ചുണ്ടെലി"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"എലി"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"കാള"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"പോത്ത്"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"പശു"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"പല്ലി"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"മുയൽ"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"പൂച്ച"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ഡ്രാഗൺ"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"മുതല"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"തിമിംഗലം"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"ഒച്ച്"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"പാമ്പ്"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"കുതിര"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"മുട്ടനാട്"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"കോലാട്"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"ചെമ്മരിയാട്"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"കുരങ്ങൻ"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"പൂവൻകോഴി"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"പിടക്കോഴി"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"നായ"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"പന്നി"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"കാട്ടുപന്നി"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ആന"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"നീരാളി"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"പിരിയൻ കക്ക"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"ചെറുപ്രാണി"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"ഉറുമ്പ്"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"തേനീച്ച"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"ചെറു വണ്ട്"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"മത്സ്യം"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ട്രോപ്പിക്കൽ മത്സ്യം"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ബ്ലോഫിഷ്"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"കടലാമ"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"മുട്ടവിരിഞ്ഞ് കോഴിക്കുഞ്ഞ് പുറത്തുവരുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"കോഴിക്കുഞ്ഞ്"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"കോഴിക്കുഞ്ഞിന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"കിളി"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"പെൻഗ്വിൻ"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"കോല"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"പൂഡിൽ"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"ഡ്രോമെഡറി ഒട്ടകം"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"ബാക്‌ട്രിയൻ ഒട്ടകം"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"ഡോൾഫിൻ"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"എലിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"പശുവിന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"പുലിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"മുയലിന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"പൂച്ചയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ഡ്രാഗണിന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"സ്‌പൗട്ടിംഗ് തിമിംഗലം"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"കുതിരയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"കുരങ്ങന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"പട്ടിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"പന്നിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"തവളയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"എലിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"ചെന്നായയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"കരടിയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"പാൻഡയുടെ മുഖം"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"പന്നിയുടെ മൂക്ക്"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"മൃഗങ്ങളുടെ കാൽപ്പാടുകൾ"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"കണ്ണുകൾ"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"ചെവി"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"മൂക്ക്"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"വായ"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"നാക്ക്"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"മുകളിലേക്ക് ചൂണ്ടുന്ന വെളുത്ത കൈയ്യുടെ പിൻ ചൂണ്ടുവിരൽ"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"താഴോട്ട് ചൂണ്ടുന്ന കൈയ്യുടെ പിൻ ചൂണ്ടുവിരൽ"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"ഇടതുവശത്തേക്ക് ചൂണ്ടുന്ന വെളുത്ത കൈയ്യുടെ പിൻ ചൂണ്ടുവിരൽ"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"വലതുവശത്തേക്ക് ചൂണ്ടുന്ന വെളുത്ത കൈയ്യുടെ പിൻ ചൂണ്ടുവിരൽ"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"മുഷ്‌ടി അടയാളം"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"കൈ കൊണ്ട് അഭിസംബോധന ചെയ്യുന്ന അടയാളം"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"കൊള്ളാം എന്ന കൈയടയാളം"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"തംബ്‌സ് അപ്പ് അടയാളം"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"തംബ്‌സ് ഡൗൺ അടയാളം"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"കൈക്കൊട്ടുന്ന ചിത്രം"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"തുറന്ന കൈയ്യുടെ അടയാളം"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"കിരീടം"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"സ്‌ത്രീകളുടെ തൊപ്പി"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"കണ്ണടകൾ"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"ടൈ"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"ടീ ഷർട്ട്"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ജീൻസ്"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"വസ്ത്രം"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"കിമോണോ"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"ബിക്കിനി"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"സ്‌ത്രീകളുടെ വ‌സ്‌ത്രങ്ങൾ"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"പേഴ്‌സ്"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ഹാൻഡ്ബാഗ്"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"പോക്കറ്റ്"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"പുരുഷന്മാരുടെ ഷൂ"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"അത്‌ലറ്റിക് ഷൂ"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ഉയർന്ന ഹീലുള്ള ഷൂ"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"സ്‌ത്രീകളുടെ ചെരുപ്പ്"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"സ്‌ത്രീകളുടെ ബൂട്ടുകൾ"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"കാൽപ്പാടുകൾ"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"നെഞ്ചളവ് വരെയുള്ള നിഴൽ രൂപം"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"നെഞ്ചളവ് വരെയുള്ള നിഴൽ രൂപങ്ങൾ"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"ആൺകുട്ടി"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"പെൺകുട്ടി"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"പുരുഷൻ"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"സ്‌ത്രീ"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"കുടുംബം"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"കൈകോർത്തുപിടിച്ചിരിക്കുന്ന പുരുഷനും സ്‌ത്രീയും"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"കൈകോർത്തുപിടിച്ചിരിക്കുന്ന രണ്ടുപുരുഷന്മാർ"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"കൈകോർത്തുപിടിച്ചിരിക്കുന്ന രണ്ടുസ്‌ത്രീകൾ"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"പോലീസ് ഉദ്യോഗസ്ഥൻ"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"മുയൽചെവികളുള്ള സ്‌ത്രീകൾ"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"ശിരോവസ്‌ത്രം ഇട്ട മണവാട്ടി"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"സ്വർണ്ണത്തലമുടിയുള്ള വ്യക്‌തി"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"ഗുവാ പൈ മാവോ ധരിച്ച പുരുഷൻ"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"തലപ്പാവ് ധരിച്ച പുരുഷൻ"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"വൃദ്ധൻ"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"വൃദ്ധ"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"കുഞ്ഞ്"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"കെട്ടിടനിർമ്മാണ തൊഴിലാളി"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"രാജകുമാരി"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"ജാപ്പനീസ് രാക്ഷസൻ"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"ജാപ്പനീസ് ഭൂതം"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"ഭൂതം"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"കുഞ്ഞുമാലാഖ"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"അന്യഗ്രഹജീവി"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"ആന്യഗ്രഹ രാക്ഷസൻ"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"കുട്ടിപിശാച്"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"തലയോട്ടി"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"വിവരങ്ങൾ നൽകുന്ന വ്യക്തി"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"കാവൽക്കാരൻ"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"നൃത്തംചെയ്യുന്നയാൾ"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"ലിപ്‌സ്റ്റിക്ക്"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"നെയിൽ പോളിഷ്"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"മുഖം മസാജുചെയ്യൽ"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"ഹെയർകട്ട്"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"ബാർബർ പോൾ"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"സിറിഞ്ച്"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ഗുളിക"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"ചുംബന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"പ്രേമലേഖനം"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"റിംഗുചെയ്യുക"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"രത്നക്കല്ല്"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"ചുംബനം"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"പൂച്ചെണ്ട്"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"ഹൃദയ ചിഹ്നമുള്ള ദമ്പതികൾ"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"വിവാഹം"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"തുടിക്കുന്ന ഹൃദയം"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"മുറിഞ്ഞ ഹൃദയം"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"രണ്ട് ഹൃദയങ്ങൾ"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"തിളങ്ങുന്ന ഹൃദയം"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"വളരുന്ന ഹൃദയം"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"അമ്പടയാളമുള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"നീല നിറമുള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"പച്ച നിറമുള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"മഞ്ഞ നിറമുള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"പർപ്പിൾ നിറമുള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"റിബൺ ഉള്ള ഹൃദയം"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"കറങ്ങുന്ന ഹൃദയങ്ങൾ"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"ഹൃദയ രൂപത്തിൽ അലങ്കരിച്ചത്"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"അകത്ത് ഡോട്ടുള്ള ചതുർഭുജം"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"വൈദ്യുത ബൾബ്"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"ആംഗർ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"ബോംബ്"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"ഉറങ്ങുന്നതിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"കൂട്ടിയിടിയുടെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"തെറിക്കുന്ന വിയർപ്പുതുള്ളികളുടെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"വെള്ളതുള്ളി"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"കുതിച്ചുപായുന്നതിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"പൈൽ ഓഫ് പൂ"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"കൈമടക്കി മാംസപേശി കാണിക്കൽ"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"തലകറക്കത്തിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"സ്‌പീച്ച് ബലൂൺ"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"ചിന്തിക്കുന്നതിനെ സൂചിപ്പിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"വെളുത്തനിറമുള്ള പൂവ്"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"നൂറുപോയിന്റ് കാണിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"പണമടങ്ങിയ സഞ്ചി"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"കറൻസി വിനിമയം"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"കട്ടിയുള്ള ഡോളർ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"ക്രെഡിറ്റ് കാർഡ്"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"യെൻ ചിഹ്നമുള്ള ബാങ്ക്നോട്ട്"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ഡോളർ ചിഹ്നമുള്ള ബാങ്ക്നോട്ട്"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"യൂറോ ചിഹ്നമുള്ള ബാങ്ക്നോട്ട്"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"പൗണ്ട് ചിഹ്നമുള്ള ബാങ്ക്നോട്ട്"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"ചിറകുള്ള പണം"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"മുകളിലേക്ക് പോകുന്ന ചാർട്ടും യെൻ ചിഹ്നവും"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"സീറ്റ്"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"വ്യക്തിഗത കമ്പ്യൂട്ടർ"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"ബ്രീഫ്കെയ്‌സ്"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"മിനിഡിസ്‌ക്"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ഫ്ലോപ്പി ഡിസ്‌ക്"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ഒപ്‌റ്റിക്കൽ ഡിസ്‌ക്"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"ഡിവിഡി"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"ഫയൽ ഫോൾഡർ"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"തുറന്ന ഫയൽ ഫോൾഡർ"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"ചുരുളുള്ള പേജ്"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"മുകൾഭാഗം ചെറുതായി മടക്കിയ പേജ്"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"കലണ്ടർ"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"മുറിച്ചെടുക്കാവുന്ന കലണ്ടർ"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"കാർഡ് സൂചിക"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"ട്രെൻഡ് മുകളിലേക്കുള്ള ചാർട്ട്"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"ട്രെൻഡ് താഴേയ്‌ക്കുള്ള ചാർട്ട്"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"ബാർ ചാർട്ട്"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"ക്ലിപ്പ്ബോർഡ്"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"പുഷ്‌പിൻ"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"വൃത്താകൃതിയുള്ള പുഷ്‌പിൻ"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"പേപ്പർ ക്ലിപ്പ്"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"വളവില്ലാത്ത റൂളർ"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"ത്രികോണാകൃതിയുള്ള റൂളർ"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"ബുക്ക്‌മാർക്ക് ടാബുകൾ"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"ലെഡ്‌ജർ"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"നോട്ട്ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"അലങ്കരിച്ച കവറുള്ള നോട്ട്ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"അടച്ച ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"തുറന്ന ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"പച്ച നിറമുള്ള ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"നീല നിറമുള്ള ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"ഓറഞ്ച് നിറമുള്ള ബുക്ക്"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"ബുക്കുകൾ"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"നെയിം ബാഡ്ജ്"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"സ്‌ക്രോൾ"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"മെമോ"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"ടെലിഫോൺ റിസീവർ"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"പേജര്‍"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"ഫാക്‌സ് യന്ത്രം"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"സാറ്റലൈറ്റ് ആന്റിന"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"ഉച്ചഭാഷിണി"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"മെഗാഫോണിലൂടെ ശബ്‌ദമുണ്ടാകുമ്പോഴുള്ള ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"ഔട്ട്ബോക്‌സ് ട്രേ"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ഇൻബോക്‌സ് ട്രേ"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"പാക്കേജ്"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ഇമെയിൽ അടയാളം"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ഇൻകമിംഗ് എൻവലപ്പ്"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"മുകളിൽ താഴേക്കുള്ള അമ്പടയാളം കാണിക്കുന്ന എൻവലപ്പ്"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"കൊടി താഴ്‌ത്തിയ അടച്ച മെയിൽബോക്‌സ്"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"കൊടി മുകളിലുള്ള അടച്ച മെയിൽബോക്‌സ്"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"കൊടി മുകളിലുള്ള തുറന്ന മെയിൽ ബോക്‌സ്"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"കൊടി താഴെയുള്ള തുറന്ന മെയിൽബോക്‌സ്"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"പോസ്‌റ്റ് ബോക്‌സ്"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"പോസ്‌റ്റൽ ഹോൺ"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"വർത്തമാനപ്പത്രം"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"മൊബൈൽ ഫോൺ"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"ഇടതുവശത്തേക്ക് വലത്തേക്കുള്ള അമ്പടയാളമുള്ള മൊബൈൽ ഫോൺ"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"വൈബ്രേഷൻ മോഡ്"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"മൊബൈൽ ഫോൺ ഓഫാണ്"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"മൊബൈൽ ഫോണുകളൊന്നുമില്ല"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"ബാറുകളോടുകൂടിയ ആന്റിന"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"ക്യാമറ"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"വീഡിയോ ക്യാമറ"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"ടെലിവിഷൻ"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"റേഡിയോ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"വീഡിയോകാസറ്റ്"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"വലതുവശത്തേയ്‌ക്ക് ചുറ്റിയിരിക്കുന്ന അമ്പടയാളങ്ങൾ"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"ഘടികാരദിശയിൽ വലത്തേക്കും ഇടത്തേക്കുമുള്ള തുറന്ന വൃത്താകൃതിയിലെ അമ്പടയാളങ്ങൾ"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"വൃത്താകൃതിയിലുള്ള ഒരു ഓവർലേ ഉള്ള, ഘടികാരദിശയിൽ വലത്തേക്കും ഇടത്തേക്കുമുള്ള തുറന്ന വൃത്താകൃതിയിലുള്ള അമ്പടയാളങ്ങൾ"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"ഘടികാരദിശയിൽ താഴേക്കും മുകളിലേയ്‌ക്കുമുള്ള തുറന്ന വൃത്താകൃതിയിലുള്ള അമ്പടയാളങ്ങൾ"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"എതിർഘടികാര ദിശയിൽ താഴേക്കും മുകളിലേയ്‌ക്കുമുള്ള തുറന്ന വൃത്താകൃതിയിലുള്ള അമ്പടയാളങ്ങൾ"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"തെളിച്ചക്കുറവ് കാണിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"തെളിച്ചക്കൂടുതൽ കാണിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"സ്‌പീക്കറിൽ റദ്ദാക്കൽ വരയുള്ളത്"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"സ്പീക്കർ"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ഒറ്റ ശബ്‌ദ തരംഗമുള്ള സ്‌പീക്കർ"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"മൂന്ന് ശബ്‌ദ തരംഗമുള്ള സ്‌പീക്കർ"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"ബാറ്ററി"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"വൈദ്യുത പ്ലഗ്"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"ഇടത്തേക്ക് പോയിന്റുചെയ്യുന്ന മാഗ്‌നിഫൈയിംഗ് ഗ്ലാസ്"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"വലത്തേക്ക് പോയിന്റുചെയ്യുന്ന മാഗ്‌നിഫൈയിംഗ് ഗ്ലാസ്"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"മഷിപേന ചിഹ്നമുള്ള പൂട്ട്"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"താക്കോൽ ഉള്ള അടച്ച പൂട്ട്"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"താക്കോൽ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"പൂട്ട്"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"തുറന്ന പൂട്ട്"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"മണി"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"മണിയിൽ റദ്ദാക്കൽ വരയുള്ളത്"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"ബുക്ക്മാർക്ക്"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"ചങ്ങലക്കണ്ണിയുടെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"റേഡിയോ ബട്ടൺ"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"ഇടത്തേക്കുള്ള അമ്പടയാളമുള്ള Back"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"മുകളിൽ ഇടതുവശത്തേക്കുള്ള അമ്പടയാളമുള്ള \'അവസാനം\' എന്നത്"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"മുകളിൽ ഇടതുവശത്തേക്കും വലതുവശത്തെക്കും അമ്പടയാളമുള്ള, ആശ്ചര്യ ചിഹ്നത്തോടുകൂടിയ \'ഓണാണ്\'"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"മുകളിൽ വലതുവശത്തേക്ക് അമ്പടയാളമുള്ള \'ഉടനെ\' എന്നത്"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"മുകളിലേക്കുള്ള അമ്പടയാളമുള്ള \'മുകളിൽ\' എന്നത്"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"പതിനെട്ടിന് താഴെയുള്ളവർക്കുള്ളതല്ല എന്ന് കാണിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"കീക്യാപ്പ് പത്ത്"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"ലാറ്റിൻ വലിയക്ഷരങ്ങൾക്കുള്ള ഇൻപുട്ട് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"ലാറ്റിൻ ചെറിയക്ഷരങ്ങൾക്കുള്ള ഇൻപുട്ട് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"നമ്പരുകൾക്കുള്ള ഇൻപുട്ട് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"ചിഹ്നങ്ങൾക്കുള്ള ഇൻപുട്ട് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"ലാറ്റിൻ അക്ഷരങ്ങൾക്കുള്ള ഇൻപുട്ട് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"തീ"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"വൈദ്യുത ടോർച്ച്"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"റെഞ്ച്"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"ചുറ്റിക"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"നട്ടും ബോൾട്ടും"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"കത്തി"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"തോക്ക്"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"മൈക്രോസ്‌കോപ്പ്"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"ടെലിസ്‌കോപ്പ്"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"സ്ഥടിക ബോൾ"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"മധ്യഭാഗത്ത് കറുത്ത ഡോട്ടുള്ള ആറ് പോയിന്റുള്ള നക്ഷത്രം"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"തുടക്കക്കാർക്കുള്ള ജാപ്പനീസ്‌ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"ത്രിശൂലത്തിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"കറുത്ത ചതുര ബട്ടൺ"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"വെള്ള ചതുര ബട്ടൺ"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"ചുവന്ന നിറമുള്ള വലിയ വൃത്തം"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"നീല നിറമുള്ള വലിയ വൃത്തം"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"ഓറഞ്ച് നിറമുള്ള വലിയ ചതുർഭുജം"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"നീലനിറമുള്ള വലിയ ചതുർഭുജം"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"ഓറഞ്ച് നിറമുള്ള ചെറിയ ചതുർഭുജം"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"ചെറിയ നീല നിറമുള്ള ചതുർഭുജം"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"മുകളിലേക്ക് പോയിന്റുചെയ്യുന്ന ചുവന്ന നിറമുള്ള ത്രികോണം"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"താഴേക്ക് പോയിന്റുചെയ്യുന്ന ചുവന്ന നിറമുള്ള ത്രികോണം"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"മുകളിലേക്ക് പോയിന്റുചെയ്യുന്ന ചെറിയ ചുവന്ന നിറമുള്ള ത്രികോണം"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"താഴേക്ക് പോയിന്റുചെയ്യുന്ന ചെറിയ ചുവന്ന നിറമുള്ള ത്രികോണം"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"ഒരു മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"രണ്ട് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"മൂന്ന് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"നാല് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"അഞ്ച് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"ആറ് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"ഏഴ് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"എട്ട് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"ഒൻപത് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"പത്ത് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"പതിനൊന്ന് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"പന്ത്രണ്ട് മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"ഒന്നര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"രണ്ടര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"മൂന്നര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"നാലര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"അഞ്ചര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"ആറര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"ഏഴര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"എട്ടര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"ഒൻപതര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"പത്തര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"പതിനൊന്നര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"പന്ത്രണ്ടര മണി സമയം കാണിക്കുന്ന ക്ലോക്ക്"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ഫുജി പർവ്വതം"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"ടോക്കിയോ ടവർ"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"സ്‌റ്റാച്യൂ ഓഫ് ലിബെർട്ടി"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"ജപ്പാനിന്റെ നിഴൽ ചിത്രം"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"മോയായ്"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"വിഢിച്ചിരിയുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"ഗോഷ്‌ടിച്ചിരിയോടുകൂടി കണ്ണുകളാൽ പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"ആന്ദാശ്രുവുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"വായതുറന്ന് പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"വായ തുറന്ന് പുഞ്ചിരിക്കുന്ന കണ്ണുകളുള്ള പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"വായ തുറന്ന്, വിയർത്ത പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"വായ തുറന്ന്, ഇറുകെ കണ്ണുകളടച്ച് പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"പ്രകാശവലയമുള്ള പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"കൊമ്പുകളുള്ള പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"കണ്ണിറുക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"പുഞ്ചിരിക്കുന്ന കണ്ണുകളാൽ പുഞ്ചിരി തൂകുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"രുചികരമായ ഭക്ഷണത്തിന്റെ മണം ആസ്വദിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"ആശ്വാസകരമായ മുഖം"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"ഹൃദയ രൂപത്തിലുള്ള കണ്ണുകളുള്ള പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"സൺഗ്ലാസ്സുകൾ ധരിച്ച് പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"കൃത്രിമമായി പുഞ്ചിരിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"വികാരമൊന്നുമില്ലാത്ത മുഖം"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"ഭാവശൂന്യമായ മുഖം"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"സന്തോഷരഹിതമായ മുഖം"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"ഭയത്താൽ വിയർക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"ചിന്താകുലമായ മുഖം"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"ആശയക്കുഴപ്പമുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"ചിന്താക്കുഴപ്പമുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"ചുംബിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"ചുംബനം പറത്തിവിടുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"പുഞ്ചിരിക്കുന്ന കണ്ണുകളുള്ള ചുംബിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"അടഞ്ഞ കണ്ണുകളുള്ള ചുംബിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"പുറത്തേക്ക് നീട്ടിയ നാവുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"പുറത്തേക്കുനീട്ടിയ നാവുള്ള കണ്ണുചിമ്മുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"പുറത്തേക്കുനീട്ടിയ നാവും ഇറുകെ ചിമ്മിയ കണ്ണുകളുമുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"നിരാശനിറഞ്ഞ മുഖം"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"ദുഃഖിതമായ മുഖം"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"ദേഷ്യത്തോടെയുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"മുഷിച്ചിൽ പ്രകടമാക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"കരയുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"കഠിനാദ്ധ്വാനത്തിന്റെ മുഖം"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"വിജയാഹ്ലാദം പ്രകടിപ്പിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"നിരാശനിറഞ്ഞതെങ്കിലും ആശ്വാസകരമായ മുഖം"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"വായ തുറന്ന് നെറ്റി ചുളിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"വേദന പ്രകടമാക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"ഭയചകിതമായ മുഖം"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"ക്ഷീണിച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"നിദ്രാലസമായ മുഖം"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"ക്ഷീണിച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"വിഡ്‌ഢിച്ചിരിയുള്ള മുഖം"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"ഉച്ചത്തിൽ കരയുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"തുറന്ന വായോടുകൂടിയ മുഖം"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"നിശബ്‌ദമായ മുഖം"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"വായ തുറന്നിരിക്കുന്ന, ഭയത്താൽ വിയർക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"ഭയത്താൽ അലറിവിളിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"ആശ്ചര്യഭരിതമായ മുഖം"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"ചുവന്നുതുടുത്ത മുഖം"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"ഉറങ്ങുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"മോഹാലസ്യം കാണിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"വായില്ലാത്ത മുഖം"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"മെഡിക്കൽ മാസ്‌ക്കോടുകൂടിയ മുഖം"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"ഗോഷ്‌ടിച്ചിരിയുള്ള പുഞ്ചിരിക്കുന്ന കണ്ണുകളുള്ള പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"ആനന്ദാശ്രുവുള്ള പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"വായ തുറന്ന് പുഞ്ചിരിക്കുന്ന പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"ഹൃദയ രൂപത്തിലുള്ള കണ്ണുകളുള്ള പുഞ്ചിരിക്കുന്ന പൂച്ച"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"വക്രമായ ചിരിയോടുകൂടിയുള്ള പൂച്ചമുഖം"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"അടഞ്ഞ കണ്ണുകളുള്ള, ചുംബിക്കുന്ന പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"മുഷിച്ചിൽ അനുഭവപ്പെടുന്ന പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"കരയുന്ന പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"ക്ഷീണിതമായ പൂച്ച മുഖം"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"സമ്മതമല്ല എന്നു കാണിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"ശരി എന്നുകാണിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"തലകുനിച്ചിരിക്കുന്ന വ്യക്തി"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"കണ്ടില്ല എന്ന് കാണിക്കുന്ന കുരങ്ങൻ"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"കേൾക്കുന്നില്ല എന്ന് കാണിക്കുന്ന കുരങ്ങൻ"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"സംസാരിക്കുന്നില്ല എന്ന് കാണിക്കുന്ന കുരങ്ങൻ"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"സന്തോഷത്തോടെ ഒരു കൈ ഉയർത്തുന്ന വ്യക്തി"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"ആഘോഷവേളയിൽ രണ്ടുകൈയ്യും ഉയർത്തുന്ന വ്യക്തി"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"നെറ്റി ചുളിക്കുന്ന വ്യക്തി"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"മുഷിച്ചിൽ അനുഭവപ്പെടുന്ന മുഖമുള്ള വ്യക്തി"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"കെട്ടിയ കൈകളുള്ള വ്യക്തി"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"റോക്കറ്റ്"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ഹെലിക്കോപ്‌റ്റർ"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"തീവണ്ടി എഞ്ചിൻ"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"റെയിൽവേ കാർ"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"അതിവേഗ ട്രെയിൻ"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"മുൻഭാഗം ബുള്ളറ്റ് പോലെ കൂർത്തിരിക്കുന്ന അതിവേഗ ട്രെയിൻ"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ട്രെയിൻ"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"മെട്രോ"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"ലൈറ്റ് റെയിൽ"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"സ്‌റ്റേഷൻ"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ട്രാം"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ട്രാം കാർ"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"ബസ്"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"വരുന്ന ബസ്"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ട്രോളി ബസ്"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"ബസ് ‌സ്റ്റോപ്പ്"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"മിനിബസ്"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"ആംബുലൻസ്"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"അഗ്നിശമന എഞ്ചിൻ"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"പോലീസ് കാർ"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"വരുന്ന പോലീസ് കാർ"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"ടാക്‌സി"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"വരുന്ന ടാക്‌സി"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"ഓട്ടോമൊബൈൽ"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"വരുന്ന ഓട്ടോമൊബൈൽ"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"വിനോദത്തിനുപയോഗിക്കുന്ന വാഹനം"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"ഡെലിവറി ട്രക്ക്"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ആർട്ടിക്യുലേറ്റഡ് ലോറി"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ട്രാക്‌ടർ"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"മോണോറെയിൽ"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"മൗണ്ടെയ്‌ൻ റെയിൽവേ"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"തൂങ്ങിക്കിടക്കുന്ന റെയിൽവേ"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"കുന്നിൻ പ്രദേശത്തെ കേബിൾവേ"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ഏരിയൽ ട്രാംവേ"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"കപ്പൽ"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"വഞ്ചി"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"സ്‌പീഡ് ബോട്ട്"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"തിരശ്ചീനമായ ട്രാഫിക്ക് ലൈറ്റ്"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ലംബമായ ട്രാഫിക്കൽ ലൈറ്റ്"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"നിർമ്മാണത്തിലാണ് എന്ന് കാണിക്കുന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"ലൈറ്റ് ചുറ്റുന്ന പോലീസ് കാറുകൾ"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"പോസ്‌റ്റിലെ ത്രികോണാകൃതിയിലുള്ള പതാക"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"വാതിൽ"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"പ്രവേശനമില്ല ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"പുകവലി ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"പുകവലിക്കരുത് ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"ചവറിടേണ്ട സ്ഥലത്തുതന്നെയിടുക എന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"ചവറിടരുത് എന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"കുടിക്കാൻ യോഗ്യമായ വെള്ളത്തിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"കുടിക്കാൻ പാടില്ലാത്ത വെള്ളത്തിന്റെ ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"സൈക്കിൾ"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"സൈക്കിളുകളൊന്നുമില്ല"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"സൈക്കിൾ ഓടിക്കുന്നയാൾ"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"കുന്നിൻ പുറത്ത് സൈക്കിൾ ഓടിക്കുന്നയാൾ"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"കാൽനടയാത്രികൻ"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"കാൽനടയാത്രികരൊന്നുമില്ല"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"കുട്ടികൾ വഴി മുറിച്ചുകടക്കുന്നു"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"പുരുഷൻ എന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"സ്‌ത്രീകൾ എന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"മൂത്രപ്പുര"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"കുഞ്ഞ് എന്ന ചിഹ്നം"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"ശൗച്യാലയം"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"വാട്ടർ ക്ലോസറ്റ്"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"ഷവർ"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"കുളി"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"ബാത്ത്ടബ്ബ്"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"പാസ്‌പോർട്ട് നിയന്ത്രണം"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"തീരുവ"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"ബാഗേജ് ക്ലെയിം"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"ലഗേജ് വയ്‌ക്കാനുള്ള സ്ഥലം"</string>
+</resources>
diff --git a/java/res/values-ml-rIN/strings-talkback-descriptions.xml b/java/res/values-ml-rIN/strings-talkback-descriptions.xml
index 3577bbb..aacfca3 100644
--- a/java/res/values-ml-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-ml-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"വാചകമൊന്നും നൽകിയിട്ടില്ല"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>, <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> എന്നത് <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> എന്നതായി തിരുത്തുന്നു"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> യാന്ത്രിക-തിരുത്തൽ നിർവഹിക്കുന്നു"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"നിർദ്ദേശമൊന്നുമില്ല"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"അജ്ഞാത പ്രതീകം"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"കൂടുതൽ ചിഹ്നങ്ങൾ"</string>
@@ -58,7 +59,7 @@
     <string name="keyboard_mode_date" msgid="6597407244976713364">"തീയതി"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"തീയതിയും സമയവും"</string>
     <string name="keyboard_mode_email" msgid="1239682082047693644">"ഇമെയിൽ"</string>
-    <string name="keyboard_mode_im" msgid="3812086215529493501">"സന്ദേശമയയ്‌ക്കൽ"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"സന്ദേശം"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"നമ്പർ"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"ഫോൺ"</string>
     <string name="keyboard_mode_text" msgid="9138789594969187494">"ടെക്‌സ്‌റ്റ്"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"വലിയക്ഷരം I, മുകളിൽ ഡോട്ട്"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"അജ്ഞാത ചിഹ്നം"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"അജ്ഞാത ഇമോജി"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"മുഷിഞ്ഞ മുഖം"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"ചമ്മിയ മുഖം"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"സൺഗ്ലാസ് ധരിച്ച മുഖം"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"ആശ്‌ചര്യ ഭാവമുള്ള മുഖം"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"ചുംബിക്കുന്ന മുഖം"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"ദേഷ്യ ഭാവമുള്ള മുഖം"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ഇതര പ്രതീകങ്ങൾ ലഭ്യമാണ്"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ഇതര പ്രതീകങ്ങൾ നിരസിച്ചു"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ഇതര നിർദ്ദേശങ്ങൾ ലഭ്യമാണ്"</string>
diff --git a/java/res/values-ml-rIN/strings.xml b/java/res/values-ml-rIN/strings.xml
index e27df48..f24c5f2 100644
--- a/java/res/values-ml-rIN/strings.xml
+++ b/java/res/values-ml-rIN/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"കീ അമർത്തുമ്പോൾ വൈബ്രേറ്റുചെയ്യുക"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"കീ അമർത്തുമ്പോഴുള്ള ശബ്‌ദമുണ്ടാക്കുക"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"കീ അമർത്തുമ്പോൾ പോപ്പ്അപ്പ് ചെയ്യുക"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"മുൻഗണനകൾ"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"അക്കൗണ്ടുകളും സമന്വയവും"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"രൂപഭാവവും ലേഔട്ടുകളും"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ഗെസ്ചർ ടൈപ്പിംഗ്"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"വാചകം തിരുത്തൽ"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"വിപുലമായ"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"തീം"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"സ്‌പ്‌ലിറ്റ് കീബോർഡ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google കീബോർഡ് സമന്വയം"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"സമന്വയം ഓണാണ്"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ഉപകരണങ്ങളിലുടനീളം നിങ്ങളുടെ സ്വകാര്യ നിഘണ്ടു സമന്വയിപ്പിക്കുക"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ഇപ്പോൾ സമന്വയിപ്പിക്കുക"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ക്ലൗഡ് വിവരം ഇല്ലാതാക്കുക"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"നിങ്ങളുടെ സമന്വയിപ്പിച്ച വിവരം Google-ൽ നിന്ന് ഇല്ലാതാക്കുന്നു"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"നിങ്ങളുടെ സമന്വയിപ്പിച്ച വിവരം ക്ലൗഡിൽ നിന്ന് ഇല്ലാതാക്കും. തീർച്ചയാണോ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ഇല്ലാതാക്കുക"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"റദ്ദാക്കുക"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"നിങ്ങളുടെ സ്വകാര്യ നിഘണ്ടു Google സെർവറുകളിലേക്ക് സമന്വയിപ്പിച്ച് ബാക്കപ്പുചെയ്യും. ഞങ്ങളുടെ ഉൽപ്പന്നങ്ങൾ മെച്ചപ്പെടുത്താൻ സഹായിക്കുന്നതിന് പദങ്ങളുടെ ആവർത്തനം സംബന്ധിച്ച സ്ഥിതിവിവരക്കണക്കുകൾ ശേഖരിച്ചേക്കാം. എല്ലാ വിവരങ്ങളും ശേഖരിക്കുന്നതും ഉപയോഗിക്കുന്നതും "<a href="https://www.google.com/policies/privacy">"Google-ന്റെ സ്വകാര്യത നയത്തിന്"</a>" വിധേയമായിട്ടായിരിക്കും."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ഈ ഫീച്ചർ പ്രവർത്തനക്ഷമമാക്കാൻ ഈ ഉപകരണത്തിൽ Google അക്കൗണ്ട് ചേർക്കുക"</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">"ഭാഷ മാറൽ കീയിൽ മറ്റ് ടൈപ്പുചെയ്യൽ രീതികളും ഉൾപ്പെടുന്നു"</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">"സ്ലൈഡ് ഇൻഡിക്കേറ്റർ കാണിക്കുക"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shift അല്ലെങ്കിൽ ചിഹ്ന കീകളിൽ നിന്ന് സ്ലൈഡ് ചെയ്യുമ്പോൾ ദൃശ്യ സൂചകം പ്രദർശിപ്പിക്കുക"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"വോയ്‌സ് ടൈപ്പുചെയ്യൽ കീ"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"വോയ്‌സ് ടൈപ്പുചെയ്യൽ രീതികളൊന്നും പ്രവർത്തനക്ഷമമല്ല. ഭാഷ &amp; ടൈപ്പു ചെയ്യൽ ക്രമീകരണങ്ങൾ പരിശോധിക്കുക."</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="language_selection_title" msgid="3666971864764478269">"ഭാഷകള്‍‌"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"സഹായവും ഫീഡ്‌ബാക്കും"</string>
+    <string name="select_language" msgid="5709487854987078367">"ഭാഷകള്‍‌"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"സംരക്ഷിക്കുന്നതിനായി വീണ്ടും സ്‌പർശിക്കുക"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"സംരക്ഷിക്കാൻ ഇവിടെ സ്‌പർശിക്കുക"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"നിഘണ്ടു ലഭ്യമാണ്"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"കീബോർഡ് തീം"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"അക്കൗണ്ടുകൾ മാറുക"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"അക്കൗണ്ടുകളൊന്നും തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
+    <string name="account_selected" msgid="2846876462199625974">"നിലവിൽ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> എന്ന അക്കൗണ്ട് ഉപയോഗിക്കുന്നു"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ശരി"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"റദ്ദാക്കുക"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"സൈൻ ഔട്ട് ചെയ്യുക"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"ഉപയോഗിക്കാൻ ഒരു അക്കൗണ്ട് തിരഞ്ഞെടുക്കുക"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ഇംഗ്ലീഷ് (യുകെ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ഇംഗ്ലീഷ് (യുഎസ്)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"സ്‌പാനിഷ് (യുഎസ്)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ഹിംഗ്ലീഷ്"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"സെർബിയൻ (ലാറ്റിൻ)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ഇംഗ്ലീഷ് (യുകെ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ഇംഗ്ലീഷ് (യുഎസ്) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"സ്‌പാനിഷ് (യുഎസ്) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ഹിംഗ്ലീഷ് (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"സെർബിയൻ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (പരമ്പരാഗതം)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (സിറിലിക്)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ലാറ്റിൻ)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (കോം‌പാക്‌ട്)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ഭാഷയില്ല (അക്ഷരമാല)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"അക്ഷരമാല (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"അക്ഷരമാല (QWERTZ)"</string>
@@ -108,18 +121,9 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"അക്ഷരമാല (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"അക്ഷരമാല (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ഇമോജി"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"കീബോർഡ് തീം"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"ഇഷ്‌ടാനുസൃത ടൈപ്പുചെയ്യൽ ശൈലികൾ"</string>
-    <string name="add_style" msgid="6163126614514489951">"ശൈലി ചേർക്കുക"</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>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> ഭാഷയ്‌ക്കായി ശരിക്കും ഈ ഫയൽ ഇൻസ്‌റ്റാൾ ചെയ്യണോ?"</string>
-    <string name="error" msgid="8940763624668513648">"ഒരു പിശകുണ്ടായി"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"കീ ദീർഘനേരം അമർത്തിപ്പിടിക്കൽ കാലതാമസം"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"<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">"ലോഞ്ചറിൽ അപ്ലിക്കേഷൻ ഐക്കൺ പ്രദർശിപ്പിക്കുക"</string>
     <string name="app_name" msgid="6320102637491234792">"നിഘണ്ടു ദാതാവ്"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"നിഘണ്ടു ദാതാവ്"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"നിഘണ്ടു സേവനം"</string>
diff --git a/java/res/values-mn-rMN/strings-emoji-descriptions.xml b/java/res/values-mn-rMN/strings-emoji-descriptions.xml
index f09a51d..5014b2f 100644
--- a/java/res/values-mn-rMN/strings-emoji-descriptions.xml
+++ b/java/res/values-mn-rMN/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Печень"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Шоколад"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Чихэр"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Иштэй чихэр"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Шар тос"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Зөгийн бал"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Үелсэн бялуу"</string>
diff --git a/java/res/values-mn-rMN/strings-talkback-descriptions.xml b/java/res/values-mn-rMN/strings-talkback-descriptions.xml
index d2c583e..5b9da91 100644
--- a/java/res/values-mn-rMN/strings-talkback-descriptions.xml
+++ b/java/res/values-mn-rMN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Текст оруулаагүй"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> нь <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>-г <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> руу залруулна"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> авто-залруулалт хийдэг"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Зөвлөмж байхгүй"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Үл мэдэгдэх тэмдэгт"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Шифт"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Өөр тэмдэгтүүд"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Том I, дээрээ цэгтэй"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Үл мэдэгдэх симбол"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Үл мэдэгдэх эможи"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Уйтгартай царай"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Ичсэн царай"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Нарны шил зүүсэн царай"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Гайхсан царай"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Үнсэж буй царай"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Хөмсөг зангидсан царай"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Бусад тэмдэгтүүд ашиглах боломжтой"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Бусад тэмдэгтүүдийг хаагдсан"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Бусад санал болголтууд ашиглах боломжтой"</string>
diff --git a/java/res/values-mn-rMN/strings.xml b/java/res/values-mn-rMN/strings.xml
index 4d47dfe..3625089 100644
--- a/java/res/values-mn-rMN/strings.xml
+++ b/java/res/values-mn-rMN/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"Оруулгын тохируулга"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Харагдац"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Олон хэлний сонголтууд"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Зангалтын бичих тохируулга"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Тохируулга"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Хаяг &amp; Нууцлал"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Харагдах байдал &amp; Зураглал"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Зангаагаар бичих"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Текст залруулалт"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Дэлгэрэнгүй"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Загвар"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Хуваагдмал гарыг идэвхжүүлэх"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-н гарны тохиргоо"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Тохиргоо хийгдэх үйлдлийг идэвхжүүлсэн байна"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Төхөөрөмжинд өөрийн хувийн толь бичгийг тохируулах"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Одоо синк хийх"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Cloud-ын мэдээллийг устгах"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Таны синк хийсэн мэдээллийг Google-ээс устгана."</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Таны мэдээллийг cloud-с устгах болно. Та итгэлтэй байна уу?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Устгах"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Цуцлах"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Таны хувийн толь бичгийг синк хийж, Google-ийн серверүүд дээр хадгалж авч үлдэнэ. Манай бүтээгдэхүүнүүдийг сайжруулахад туслах зорилгоор үгийн давтамжийн статистик мэдээллийг цуглуулж болно. Бүх мэдээллийг "<a href="https://www.google.com/policies/privacy">"Google-ийн Нууцлалын бодлогын дагуу"</a>" цуглуулж, ашиглана."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Энэ горимыг идэвхжүүлэхийн тулд энэ төхөөрөмж рүү Google акаунт нэмж оруулна уу"</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">"Хэл солих түлхүүрт өөр оруулах аргууд мөн багтсан байгаа"</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">"Гулсалт заагчийг харуулах"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Сэлгэх буюу Симбол товчуудаас гулсах үед нүдэнд харагдуулах"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Дуун оруулгын товч"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ямар ч дуу оруулах хэрэглүүр идэвхжээгүй байна. Хэл болон оруулалтын тохиргоог шалгана уу."</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="language_selection_title" msgid="3666971864764478269">"Хэл"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Тусламж &amp; санал хүсэлт"</string>
+    <string name="select_language" msgid="5709487854987078367">"Хэл"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Хадгалахын тулд дахин хүрнэ үү"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Хадгалахын тулд хүрнэ үү"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Толь бичиг байна"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Гарын загвар"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Акаунт сэлгэх"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Акаунт сонгогдоогүй"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Одоо <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>-г ашиглаж байна"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ТИЙМ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Цуцлах"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Гарах"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Ашиглах акаунтаа сонгоно уу"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англи (ИБ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англи (АНУ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испани (АНУ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Серьби хэл (латин)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англи (ИБ) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англи (АНУ) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испани (АНУ-ын) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Серьби хэл (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (уламжлалт)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Кирилл)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Латин)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Компакт)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Хэл байхгүй (Цагаан толгой)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Цагаан толгой (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Цагаан толгой (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Цагаан толгой (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Инээмсэглэл"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Гарын загвар"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Холо Цагаан"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Холо Цэнхэр"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Материал Бараан"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Материал Цайвар"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Өөрийн оруулах загвар"</string>
     <string name="add_style" msgid="6163126614514489951">"Загвар нэмэх"</string>
     <string name="add" msgid="8299699805688017798">"Нэмэх"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>-д зориулсан энэ файлыг үнэхээр суулгах уу?"</string>
-    <string name="error" msgid="8940763624668513648">"Алдаа гарсан"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Товч удаан дарах хугацааны тохиргоо"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Та одоо өөрийн дуртай апп-ууд дотроо <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">"Эхлүүлэгч дээр аппликешний дүрсийг харуулах"</string>
     <string name="app_name" msgid="6320102637491234792">"Толь бичгээр хангагч"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Толь бичгээг хангагч"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Толь бичгийн үйлчилгээ"</string>
diff --git a/java/res/values-mr-rIN/strings-emoji-descriptions.xml b/java/res/values-mr-rIN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..87b6315
--- /dev/null
+++ b/java/res/values-mr-rIN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"कॉपीराइट चिन्ह"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"नोंदणीकृत चिन्ह"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"दुहेरी उदगार चिन्ह"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"उदगार प्रश्नचिन्ह"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"व्यापार चिन्ह"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"माहितीचा स्त्रोत"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"डावा उजवा बाण"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"वर खाली बाण"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"उत्तर दक्षिण बाण"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"उत्तर पूर्व बाण"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"दक्षिण पूर्व बाण"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"दक्षिण पश्चिम बाण"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"आकड्यासह डावीकडील बाण"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"आकड्यासह उजवीकडील बाण"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"घड्याळ"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"वाळूचे घड्याळ"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"काळा उजवीकडे निर्देशित करणारा दुहेरी त्रिकोण"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"काळा डावीकडे निर्देशित करणारा दुहेरी त्रिकोण"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"काळा वर निर्देशित करणारा दुहेरी त्रिकोण"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"काळा खाली निर्देशित करणारा दुहेरी त्रिकोण"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"गजराचे घड्याळ"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"वाहणार्‍या वाळूसह वाळूचे घड्याळ"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"मंडळातील लॅटिन कॅपिटल अक्षर m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"काळा लहान चौरस"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"पांढरा लहान चौरस"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"काळा उजवीकडे निर्देशित करणारा त्रिकोण"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"काळा डावीकडे निर्देशित करणारा त्रिकोण"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"पांढरा मध्यम चौरस"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"काळा मध्यम चौरस"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"पांढरा मध्यम लहान चौरस"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"काळा मध्यम लहान चौरस"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"किरणांसह काळा सूर्य"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"ढग"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"काळा टेलिफोन"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"चेक सह मतदान पेटी"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"पावसाच्या थेंबांसह छत्री"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"गरम पेय"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"पांढरी वर निर्देशित करणारी तर्जनी"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"पांढरा हसणारा चेहरा"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"मेष"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"वृषभ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"मिथुन"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"कर्क"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"सिंह"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"कन्या"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"तूळ"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"वृश्चिक"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"धनु"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"मकर"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"कुंभ"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"मीन"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"काळा इस्पिकच्या पत्त्याच्या पानांचा संच"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"काळ्या किल्वरच्या पत्त्याच्या पानांचा संच"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"काळ्या बदाम पत्त्याच्या पानांच संच"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"काळ्या चौकट च्या पत्त्याच्या पानांचा संच"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"गरम पाण्याचा झरा"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"काळे वैश्विक पुनश्चक्रण चिन्ह"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"व्हीलचेअर चिन्ह"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"अँकर"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"चेतावणी दृश्य"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"उच्च विद्युतदाब चिन्ह"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"मध्यम पांढरे वर्तुळ"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"मध्यम काळे वर्तुळ"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"सॉकर बॉल"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"बेसबॉल"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"बर्फ विरहित हिममानव"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"ढगामागचा सूर्य"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"भुजंगधारी"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"प्रवेश बंद"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"चर्च"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"कारंज"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"भोकामध्ये ध्वज"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"शिडाची होडी"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"तंबू"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"इंधन पंप"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"काळ्या कात्र्या"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"पांढरा ठळक चेकमार्क"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"विमान"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"लिफाफा"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"उन्नत मूठ"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"उन्नत हात"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"विजयी हात"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"पेन्सिल"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"काळी निब"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"ठळक चेक मार्क"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"ठळक गुणाकार x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"चकाकणे"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"आठ आरा असलेला तारा"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"आठ टोकांचा काळा तारा"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"हिमवर्षाव"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"चमक"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"फुलीचे चिन्ह"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"नकारार्थी चौरस फुलीचे चिन्ह"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"काळ्या प्रश्न चिन्हाचा अलंकार"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"पांढर्‍या प्रश्न चिन्हाचा अलंकार"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"पांढर्‍या उदगार चिन्हाचा दागिना"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"ठळक उदगार चिन्ह"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"ठळक काळे हृदय"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"ठळक अधिक चिन्ह"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"ठळक वजा चिन्ह"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"ठळक भागाकार चिन्ह"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"काळा उजवीकडे बाण"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"पीळदार लूप"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"दुहेरी पिळदार लूप"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"उजवीकडे निर्देशित करणारा नंतर वर वळणारा बाण"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"उजवीकडे निर्देशित करणारा नंतर खाली वळणारा बाण"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"डावीकडे काळा बाण"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"वर काळा बाण"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"खाली काळा बाण"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"काळा मोठा चौरस"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"पांढरा मोठा चौरस"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"पांढरा मध्यम तारा"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"ठळक मोठे मंडळ"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"लहरयुक्त डॅश"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"भागात फेरफार करण्याचा डॅश"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"वर्तुळाकृती कल्पनाचित्र अभिनंदन"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"वर्तुळाकृती कल्पनाचित्र गुपीत"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"महजोंग टाइल लाल ड्रॅगन"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"खेळण्याच्या पत्त्यातील काळा जोकर"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"रक्तगट A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"रक्तगट B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"रक्तगट O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"वाहनतळ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"रक्तगट AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"चौरसातील CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"चौरसातील छान"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"चौरसातील विनामूल्य"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"चौरसातील ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"चौरसातील नवीन"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"चौरसातील N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"चौरसातील ठीक"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"चौरसातील SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"उद्गार चिन्हासह चौरस असलेले"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"चौरसातील vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"चौरसातील कॅटाकाना येथे आहे"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"चौरसातील कॅटाकाना सेवा"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"चौरसातील कल्पनाचित्र निःशुल्क"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"चौरसातील कल्पनाचित्र आरक्षित-आसन"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"चौरसातील कल्पनाचित्र प्रतिबंध"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"चौरसातील कल्पनाचित्र रिकामी जागा"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"चौरसातील कल्पनाचित्र स्वीकार"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"चौरसातील कल्पनाचित्र पूर्ण ताबा"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"चौरसातील कल्पनाचित्र सशुल्क"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"चौरसातील कल्पनाचित्र मासिक"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"चौरसातील कल्पनाचित्र अनुप्रयोग"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"चौरसातील कल्पनाचित्र सवलत"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"चौरसातील व्यवसायातील कल्पनाचित्र"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"वर्तुळाकृती कल्पनाचित्र फायदा"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"वर्तुळाकार कल्पनाचित्र स्वीकार"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"चक्रीवादळ"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"अंधुक"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"बंद छत्री"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"चांदणे पडलेली रात्र"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"पर्वतांवरील सूर्योदय"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"सूर्योदय"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"तिन्हीसांजेचे शहराचे दृश्य"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"इमारतींवरून सूर्यास्ताचे दृश्य"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"इंद्रधनुष्य"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"रात्रीचा पूल"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"पाण्याची लाट"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"ज्वालामुखी"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"आकाशगंगा"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"पृथ्वीचा गोल युरोप-आफ्रिका"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"पृथ्वीचा गोल अमेरिका"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"पृथ्वीचा गोल आशिया-ऑस्ट्रेलिया"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"रेखावृत्तांसह पृथ्वीचा गोल"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"अमावस्येच्या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"कृष्ण पक्षातील कलेकलेने वाढणार्‍या चंद्रकोरीचे चिन्ह"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"चतुर्थीच्या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"कृष्ण पक्षातील कलेकलेने वाढणार्‍या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"पौर्णिमेच्या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"शुक्ल पक्षातील कलेकलेने कमी होणार्‍या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"अष्टमीच्या चंद्राचे चिन्ह"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"शुक्ल पक्षातील कलेकलेने कमी होणार्‍या चंद्रकोरीचे चिन्ह"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"चंद्रकोर"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"अमावस्येच्या चंद्राचा चेहरा"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"चतुर्थीच्या चंद्राचा चेहरा"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"अष्टमीच्या चंद्राचा चेहरा"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"पौर्णिमेच्या चंद्राचा चेहरा"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"सूर्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"चमकणारा तारा"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"उल्का"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"छोटा अक्रोड"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"रोप"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"सदाहरित वृक्ष"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"पानझडी वृक्ष"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"ताडवृक्ष"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"निवडुंग"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"टुलिप"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"चेरी ब्लॉसम"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"गुलाब"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"जास्वंद"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"सूर्यफुल"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"फुलोरा"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"मक्याचे कणीस"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"तांदुळाची ओंबी"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"वनस्पती"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"चार पानांची मेथी"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"मेपल पान"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"पडलेले पान"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"वार्‍यात फडफडणारे पान"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"भूछत्र"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"टोमॅटो"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"वांगे"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"द्राक्षे"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"खरबूज"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"टरबूज"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"संत्रे"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"लिंबू"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"केळे"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"अननस"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"लाल सफरचंद"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"हिरवे सफरचंद"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"नास्पति"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"पीच नावाचे फळ"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"चेरी"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"स्ट्रॉबेरी"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"हॅमबर्गर"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"पिझ्झा ची चकती"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"हाडावरील मटण"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"कोंबडीचा पाय"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"तांदुळाचे पापड"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"तांदुळाचा बॉल"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"शिजवलेला भात"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"आमटी आणि भात"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"वाफवलेला वाडगा"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"शेवया"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ब्रेड"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"चिप्स"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"भाजलेले रताळे"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"डँगो"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ओडेन"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"जपानी जेवण"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"तळलेली कोळंबी"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"भोवर्‍याच्या डिझाइनसह माश्याचा केक"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"नरम आईस्क्रीम"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"किसलेला बर्फ"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"आईस्क्रीम"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"डोनट"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"बिस्किट"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"चॉकलेट बार"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"कँडी"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"लॉलिपॉप"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"कस्टर्ड"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"मधाचे भांडे"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"कुरकुरित केक"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"बेंटो बॉक्स"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"अन्न ठेवायचे भांडे"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"स्वयंपाक"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"काटा आणि सुरी"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"कान नसलेला चहाचा कप"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"साकी बाटली आणि कप"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"दारुचा ग्लास"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"कॉकटेल ग्लास"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"उष्ण पेय"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"बीयरचा मग"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"बीयर मग वाजविणे"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"बाळाला दूध देण्याची बाटली"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"फीत"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"आच्छादलेली भेटवस्तू"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"वाढदिवसाचा केक"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"जॅक-ओ-कंदील"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"ख्रिसमस ट्री"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"धर्मगुरू ख्रिसमस"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"आतषबाजी"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"आतषबाजीची फुलबाजी"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"फुगा"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"पार्टी पॉपर"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"उधळलेले रंगीत बॉल"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"टानाबाटा झाड"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"काटकोनातील ध्वज"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"देवदार वृक्ष सजावट"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"जपानी बाहुल्या"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"कार्प पताका"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"वार्‍याचा आवाज"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"चंद्र दर्शन समारंभ"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"शाळेचे दप्तर"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"पदवीदान समारंभाची टोपी"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"फिरता पट्टा घोडा"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"आकाशपाळणा"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"रोलर कोस्टर"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"मासे पकडण्याची काठी आणि मासा"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"माइक्रोफोन"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"चित्रपट कॅमेरा"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"सिनेमा"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"हेडफोन"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"कलाकाराची रंगपेटी"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"टोप"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"सर्कसचा तंबू"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"तिकीट"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"फटमार फलक"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"कला सादर करणे"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"व्हिडिओ गेम"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"थेट मारणे"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"स्लॉट मशीन"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"बिलियर्ड्स"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"खेळाचा फासा"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"बॉलिंग"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"फुल असलेले खेळण्यातील पत्ते"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"संगीतिक स्वर"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"एकाधिक संगीतिक स्वर"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"सॅक्सोफोन"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"गिटार"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"संगीतिक कीबोर्ड"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ट्रम्पेट"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"व्हायोलिन"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"संगीतिय लिपी"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"चौकट असलेला धावण्याचा शर्ट"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"टेनिस रॅकेट आणि बॉल"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"स्की आणि स्की बूट"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"बास्केटबॉल आणि कडे"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"चौकडीचा ध्वज"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"स्नोबोर्डर"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"धावपटू"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"सर्फर"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"करंडक"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"अश्व शर्यत"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"अमेरिकन फुटबॉल"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"रग्बी फुटबॉल"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"जलतरणपटू"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"घराची इमारत"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"बगीचासह घर"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"कार्यालयाची इमारत"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"जपानी पोस्ट ऑफिस"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"युरोपियन पोस्ट ऑफिस"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"रुग्णालय"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"बँक"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"स्वयंचलित गणक यंत्र"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"हॉटेल"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"प्रेमाचे हॉटेल"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"सोयीस्कर स्टोअर"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"शाळा"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"एकछत्री वस्तुभांडार"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"कारखाना"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"इझाकाया कंदील"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"जपानी किल्ला"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"युरोपियन किल्ला"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"घूस"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"उंदीर"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"बैल"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"पाण्यातील म्हैस"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"गाय"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"चित्ता"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"ससा"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"मांजर"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ड्रॅगन"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"मगर"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"व्हेल"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"गोगलगाय"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"साप"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"घोडा"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"राम"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"बकरा"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"मेंढी"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"माकड"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"पाळीव कोंबडा"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"कोंबडी"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"कुत्रा"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"डुक्कर"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"रानडुक्कर"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"हत्ती"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ऑक्टोपस"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"वळणदार शिंपला"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"ढेकुण"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"मुंगी"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"मधमाशी"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"लेडी बीटल"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"मासा"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"उष्णकटिबंधीय मासा"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ब्लोफिश"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"कासव"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"अंड्यातून बाहेर आलेले कोंबडीचे पिल्लू"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"कोंबडीचे छोटे पिल्लू"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"समोरच्या-चेहर्‍याचे कोंबडीचे पिल्लू"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"पक्षी"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"पेंग्विन"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"कोलाला"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"केसाळ कुत्रा"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"गतिमान उंट"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"दोन पाठींचा उंट"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"डॉल्फिन"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"उंदराचे तोंड"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"गाईचे तोंड"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"वाघाचा चेहरा"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"सशाचा चेहरा"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ड्रॅगनचा चेहरा"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"फवारा सोडणारा व्हेल"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"घोड्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"माकडाचा चेहरा"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"कुत्र्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"डुकराचा चेहरा"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"बेडकाचा चेहरा"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"घुशीसारख्या प्राण्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"लांडग्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"अस्वलाचा चेहरा"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"पांडा चा चेहरा"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"डुकराचे नाक"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"पंजाचे ठसे"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"डोळे"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"कान"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"नाक"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"तोंड"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"जीभ"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"उलट्या हाताने स्पष्ट वर निर्देशित करणारी तर्जनी"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"उलट्या हाताने स्पष्ट खाली निर्देशित करणारी तर्जनी"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"उलट्या हाताने स्पष्ट डावीकडे निर्देशित करणारी तर्जनी"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"उलट्या हाताने स्पष्ट उजवीकडे निर्देशित करणारी तर्जनी"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"मूठ आवळलेल्या हाताचे चिन्ह"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"हलविणार्‍या हाताचे चिन्ह"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"ठीक आहे हाताचे चिन्ह"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"हाताचा अंगठा वर केलेले चिन्ह"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"हाताचा अंगठा खाली केलेले चिन्ह"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"टाळ्या वाजविणार्‍या हातांचे चिन्ह"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"मोकळ्या हातांचे चिन्ह"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"मुकुट"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"महिलेचा टोप"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"चष्मा"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"गळ्याचा टाय"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"टी-शर्ट"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"जीन्स"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"परिधान"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"सैल अंगरखा"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"बिकिनी"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"महिलांचे कपडे"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"पर्स"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"हँडबॅग"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"पाउच"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"पुरुषाचा बूट"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"खेळाडूचा बूट"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"उंच टाचेचा बूट"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"महिलांचा सँडल"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"महिलेचे बूट"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"पायाचे ठसे"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"काळ्या छायाकृती मधील अर्धपुतळा"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"काळ्या छायाकृतीमधील अर्धपुतळे"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"मुलगा"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"मुलगा"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"माणूस"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"महिला"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"कुटुंब"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"हातात हात घेतलेला माणूस आणि स्त्री"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"हातात हात घेतलेली दोन माणसे"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"हातात हात घेतलेल्या दोन स्त्रीया"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"पोलिस अधिकारी"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"सशासारखे कान असलेली स्त्री"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"पदर घेतलेली वधू"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"भुर्‍या केसांची व्यक्ती"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"गुआ पी माओ सह माणूस"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"पगडी घातलेला माणूस"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"वयस्कर माणूस"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"वयस्कर स्त्री"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"तान्हे मूल"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"बांधकाम कर्मचारी"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"राजकुमारी"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"जपानी दानव"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"जपानी पिशाच्च"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"भूत"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"तान्हा देवदूत"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"पृथ्वीबाह्य परकीय"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"परकीय राक्षस"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"खोडकर मुलगा"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"कवटी"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"महत्त्वाच्या डेस्कवरील व्यक्ती"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"खाजगी तैनातीतील सैनिक"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"नर्तक"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"लिप्स्टिक"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"नेल पॉलिश"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"चेहर्‍याचे मालिश"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"केस कापण्याची पद्धत"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"बार्बर पोल"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"सिरिंज"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"गोळी"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"चुंबन चिन्ह"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"प्रेम पत्र"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"अंगठी"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"मौल्यवान खडा"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"चुंबन"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"पुष्पगुच्छ"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"हृदयासह जोडपे"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"विवाहसोहळा"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"धडधडणारे हृदय"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"तुटलेले हृदय"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"दोन हृदये"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"चमकदार हृदय"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"वृद्धिंगत होणारे हृदय"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"बाणासह हृदय"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"निळे हृदय"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"हिरवे हृदय"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"पिवळे हृदय"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"जांभळे हृदय"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"फीत असलेले हृदय"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"परिभ्रमी हृदये"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"हृदयाची सजावट"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"आतमध्ये बिंदू असलेला हिर्‍याचा आकार"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"इलेक्ट्रिक लाइट बल्ब"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"रागाचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"बॉम्ब"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"झोपल्याचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"आघात चिन्ह"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"पाणी उडालेल्या घामाचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"लहान थेंब"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"डॅश चिन्ह"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"शी चा ढीग"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"आकुंचित बेटकुळ्या"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"चक्कर आल्याचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"भाषणाचा फुगा"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"विचाराचा फुगा"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"पांढरे फुल"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"शंभर गुणांचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"पैशांची पिशवी"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"चलन विनिमय"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"ठळक डॉलरचे चिन्ह"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"क्रेडिट कार्ड"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"येन चिन्ह असलेली बँकनोट"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"डॉलर चिन्ह असलेली बँकनोट"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"युरो चिन्ह असलेली बँकनोट"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"पाऊंड चिन्ह असलेली बँकनोट"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"पंखांसह पैसे"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"वरच्या दिशेसह आणि येन चिन्हासह चार्ट"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"आसन"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"वैयक्तिक संगणक"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"ब्रीफकेस"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"छोटीडिस्क"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"फ्लॉपी डिस्क"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ऑप्टिकल डिस्क"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"डीव्हिडी"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"फाईल फोल्डर"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"उघडे फाइल फोल्डर"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"वाकवलेले पृष्ठ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"वर अभिमुख पृष्ठ"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"कॅलेंडर"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"कॅलेंडर फाडणे"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"पत्ररूप निर्देशसूची"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"वरच्या दिशेने जाणारा चार्ट"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"खालच्या दिशेने जाणारा चार्ट"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"बार चार्ट"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"क्लिपबोर्ड"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"पुशपिन"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"गोल पुशपिन"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"पेपरक्लिप"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"सरळ मोजपट्टी"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"त्रिकोणी मोजपट्टी"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"बुकमार्क टॅब"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"लेजर"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"नोटबुक"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"नक्षीदार कव्हरसह नोटबुक"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"बंद पुस्तक"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"उघडे पुस्तक"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"हिरवे पुस्तक"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"निळे पुस्तक"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"केशरी पुस्तक"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"पुस्तके"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"नावाचा बॅज"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"स्क्रोल करा"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"मेमो"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"टेलिफोन रीसीव्हर"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"पेजर"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"फॅक्स मशीन"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"उपग्रह अँटेना"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"सार्वजनिक अभिभाषण ध्वनिक्षेपक"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"चीअरिंग मेगाफोन"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"आउटबॉक्स ट्रे"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"इनबॉक्स ट्रे"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"पॅकेज"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ई-मेल चिन्ह"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"येणारा लिफाफा"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"वर असलेला खालच्या दिशेने जाणारा बाण असलेला लिफाफा"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"अनुदात्त ध्वजासह बंद मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"उन्नत ध्वजासह बंद मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"उन्नत ध्वजासह उघडा मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"अनुदात्त ध्वजासह उघडे मेलबॉक्स"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"पोस्टबॉक्स"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"पोस्टल हॉर्न"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"वर्तमानपत्र"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"मोबाईल फोन"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"डावीकडे उजवीकडे जाणार्‍या बाणासह मोबाईल फोन"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"कंपन मोड"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"मोबाईल फोन बंद"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"मोबाईल फोन नाहीत"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"बार सह अँटेना"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"कॅमेरा"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"व्हिडिओ कॅमेरा"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"टेलीव्हिजन"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"रेडिओ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"व्हिडिओकॅसेट"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"वाकडेतिकडे उजवीकडे बाण"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"घड्याळाच्या दिशेने उजवीकडे आणि डावीकडे उघडे मंडळ बाण"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"एका वलयांकित आच्छादनासह घड्याळाच्या दिशेने उजवीकडे आणि डावीकडे उघडे मंडळ बाण"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"घड्याळाच्या दिशेने खाली आणि वर उघडे मंडळ बाण"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"घड्याळाच्या विरुद्ध दिशेने खाली आणि वर उघडे मंडळ बाण"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"कमी चमक चिन्ह"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"प्रखर चमक चिन्ह"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"रद्द करण्याच्या स्ट्रोकसह स्पीकर"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"स्पीकर"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"एका ध्वनी लहरीसह स्पीकर"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"तीन ध्वनी लहरींसह स्पीकर"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"बॅटरी"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"इलेक्ट्रिक प्लग"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"डाव्या-दिशेने निर्देशित करणारा भिंगकाच"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"उजव्या-दिशेने निर्देशित करणारा भिंगकाच"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"शाईच्या पेनसह कुलुप"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"किल्लीसह बंद कुलुप"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"किल्ली"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"कुलुप"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"उघडे कुलुप"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"घंटा"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"रद्द करण्याच्या स्ट्रोकसह घंटा"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"बुकमार्क"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"साखळी चिन्ह"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"रेडिओ बटण"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"वर असलेल्या डावीकडील बाणासह परत"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"वर असलेल्या डावीकडील बाणासह समाप्त"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"वर असलेल्या उजवीकडील बाणासह उदगार चिन्हासह चालू"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"वर असलेल्या उजवीकडील बाणासह लवकर"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"वर असलेल्या वरच्या बाणासह वर"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"अठरा वर्षाखालील कोणीही नाही चिन्ह"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"कीकॅप दहा"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"लॅटिन कॅपिटल अक्षरांसाठी इनपुट चिन्ह"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"लॅटिन लहान अक्षरांसाठी इनपुट चिन्ह"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"संख्यांसाठी लॅटिन चिन्ह"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"चिन्हांसाठी इनपुट चिन्ह"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"लॅटिन अक्षरांसाठी इनपुट चिन्ह"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"आग"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"इलेक्ट्रिक टॉर्च"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"पाना"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"हातोडी"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"नट आणि बोल्ट"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"होचो"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"पिस्तुल"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"सूक्ष्मदर्शक"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"टेलिस्कोप"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"स्फटिकाचा चेंडू"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"मध्यबिंदूसह सहा बिंदूंचा तारा"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"नवशिक्या साठी जपानी चिन्ह"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"त्रिशूळ चिन्ह"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"काळे चौरस बटण"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"पांढरे चौरस बटण"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"मोठे लाल मंडळ"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"मोठे निळे मंडळ"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"मोठा केशरी हिरा"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"मोठा निळा हिरा"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"लहान केशरी हिरा"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"लहान निळा हिरा"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"वरच्या-दिशेने निर्देशित करणारा लाल त्रिकोण"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"खाली-निर्देशित करणारा लाल त्रिकोण"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"वरच्या-दिशेने निर्देशित करणारा लहान लाल त्रिकोण"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"खाली-निर्देशित करणारे लहान लाल त्रिशूळ"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"घड्याळात एक वाजलेला दिसणे"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"घड्याळात दोन वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"घड्याळात तीन वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"घड्याळात चार वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"घड्याळात पाच वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"घड्याळात सहा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"घड्याळात सात वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"घड्याळात आठ वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"घड्याळात नऊ वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"घड्याळात दहा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"घड्याळात अकरा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"घड्याळात बारा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"घड्याळात दीड वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"घड्याळात अडीच वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"घड्याळात साडेतीन वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"घड्याळात साडेचार वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"घड्याळात साडेपाच वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"घड्याळात साडेसहा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"घड्याळात साडेसात वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"घड्याळात साडेआठ वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"घड्याळात साडेनऊ वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"घड्याळात साडेदहा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"घड्याळात साडेअकरा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"घड्याळात साडेबारा वाजलेले दिसणे"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"माउंट फुजी"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"टोकियो टॉवर"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"लिबर्टीचा पुतळा"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"जपानची काळी छायाकृती"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"मोयाई"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"उपहासाने हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"हसर्‍या डोळ्यांसह दात काढून हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"आनंदाश्रुंसह चेहरा"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"उघड्या तोंडाचा हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"उघड्या तोंडाचा आणि हसणार्‍या डोळ्यांचा हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"उघड्या तोंडाचा आणि थंड घामाचा हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"उघड्या तोंडाचा हसरा चेहरा आणि घट्टपणे मिटलेले डोळे"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"तेजोवलयासह हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"शिंगांसह हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"डोळे मारणारा चेहरा"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"हसणार्‍या डोळ्यांसह हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"चवदार पदार्थाचा स्वाद घेणारा चेहरा"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"चिंतामुक्त चेहरा"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"हृदयाच्या आकारातील डोळ्यांसह हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"उन्हाच्या चष्म्यासह हसणारा चेहरा"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"कपटहास्याचा चेहरा"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"तटस्थ चेहरा"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"निर्विकार चेहरा"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"कंटाळवाणा चेहरा"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"थंड घामासह चेहरा"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"चिंतामग्न चेहरा"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"गोंधळलेला चेहरा"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"गोंधळलेला चेहरा"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"चुंबन घेणारा चेहरा"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"चुंबन फेकणारा चेहरा"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"हसर्‍या डोळ्यांनी चुंबन घेणारा चेहरा"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"बंद डोळ्यांनी चुंबन घेणारा चेहरा"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"जीभ बाहेर काढणारा चेहरा"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"जीभ बाहेर काढणारा आणि डोळा मारणारा चेहरा"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"जीभ बाहेर काढणारा आणि डोळे घट्ट मिटलेला चेहरा"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"निराश चेहरा"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"काळजीत पडलेला चेहरा"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"रागावलेला चेहरा"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"चंबूभाव असलेला चेहरा"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"रडणारा चेहरा"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"पिच्छा न सोडणारा चेहरा"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"विजयी मुद्रेतील चेहरा"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"निराश परंतु चिंतामुक्त चेहरा"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"उघड्या तोंडासह कपाळावर आठ्या पडलेला चेहरा"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"काळजीत पडलेला चेहरा"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"भीतीदायक चेहरा"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"खूप थकलेला चेहरा"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"झोपाळलेला चेहरा"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"थकलेला चेहरा"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"वाकुल्या दाखविणारा चेहरा"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"मोठ्याने रडणारा चेहरा"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"उघड्या तोंडाचा चेहरा"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"स्तब्ध चेहरा"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"उघड्या तोंडाचा आणि थंड घामाचा चेहरा"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"भीतीने आरोळी मारणारा चेहरा"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"आश्चर्यचकित चेहरा"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"लाली आलेला चेहरा"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"झोपलेला चेहरा"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"चक्कर आलेला चेहरा"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"तोंडाशिवाय चेहरा"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"मेडिकल मास्कसह चेहरा"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"हसणार्‍या डोळ्यांसह दात काढून हसणार्‍या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"आनंदाश्रुंसह मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"उघड्या तोंडासह हसणार्‍या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"हृदयाच्या आकारातील डोळ्यांसह हसणार्‍या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"व्यंगपूर्ण हास्यासह मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"बंद डोळ्यांनी चुंबन घेणार्‍या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"चंबूभाव असलेल्या चेहर्‍याचे मांजर"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"रडणार्‍या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"खूप थकलेल्या मांजरीचा चेहरा"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"चांगले हावभाव नसलेला चेहरा"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"ठीक हावभाव असलेला चेहरा"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"पूर्णपणे नतमस्तक होणारी व्यक्ती"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"वाईट-पाहू-नका म्हणणारे माकड"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"वाईट-ऐकू-नका म्हणणारे माकड"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"वाईट-बोलू-नका म्हणणारे माकड"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"एक हात वर करणारी आनंदी व्यक्ती"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"आनंदोत्सवात दोन्ही हात वर करणारी व्यक्ती"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"संतापलेली व्यक्ती"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"चंबूभाव असलेल्या चेहर्‍याची व्यक्ती"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"दुमडलेल्या हातांची व्यक्ती"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"रॉकेट"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"हेलिकॉप्टर"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"वाफेवर चालणारे आगगाडीचे इंजिन"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"रेल्वे कार"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"उच्च-गती ट्रेन"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"बंदुकीचे नाक असलेली उच्च-गती ट्रेन"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ट्रेन"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"मेट्रो"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"लाइट रेल"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"स्टेशन"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ट्राम"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ट्राम कार"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"बस"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"आपल्या दिशेने येणारी बस"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ट्रॉलीबस"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"बस स्टॉप"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"मिनिबस"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"रुग्णवाहिका"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"आगीचा बंब"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"पोलिस कार"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"आपल्या दिशेने येणारी पोलिस कार"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"टॅक्सी"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"आपल्या दिशेने येणारी टॅक्सी"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"मोटार"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"आपल्या दिशेने येणारी मोटार"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"मनोरंजन वाहन"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"वितरण ट्रक"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"ट्रेलर ट्रक"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ट्रॅक्टर"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"मोनोरेल"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"पर्वतावरील रेल्वे"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"झुलती रेल्वे"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"पर्वतीय रज्जुमार्ग"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"एरियल ट्रामवे"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"जहाज"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"वल्हवण्याची नाव"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"वेगवान नाव"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"क्षैतिज रहदारी लाइट"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"अनुलंब रहदारी लाइट"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"बांधकाम चिन्ह"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"पोलिस कारचा परिभ्रमी लाइट"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"पोस्टवरील त्रिकोणी ध्वज"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"दरवाजा"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"प्रवेश बंद चिन्ह"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"धुम्रपान चिन्ह"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"धुम्रपान करू नका चिन्ह"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"कचरा त्याच्या जागेवरच टाकण्याचे चिन्ह"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"कचरा टाकू नका चिन्ह"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"पिण्यास योग्य पाणी चिन्ह"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"पिण्यास योग्य नसलेले पाणी चिन्ह"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"सायकल"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"सायकली नाहीत"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"सायकलस्वार"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"पर्वतावरील सायकलस्वार"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"पादचारी"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"पादचार्‍यांसाठी नाही"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"मुले ओलांडत आहेत"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"माणसे चिन्ह"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"स्त्रीया चिन्ह"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"शौचालय"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"तान्ह्या मुलाचे चिन्ह"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"शौचालय"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"शौचघर"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"शॉवर"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"आंघोळ"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"आंघोळीचा टब"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"पारपत्र नियंत्रण"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"जकातखाते"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"सामानाचा दावा"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"सोडलेले सामान"</string>
+</resources>
diff --git a/java/res/values-mr-rIN/strings-talkback-descriptions.xml b/java/res/values-mr-rIN/strings-talkback-descriptions.xml
index 41c64f4..c2ac29d 100644
--- a/java/res/values-mr-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-mr-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"मजकूर प्रविष्ट केला नाही"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> ला <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> मध्ये सुधारणा करते"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> स्वयं-सुधारणा करते"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"कोणतीही सूचना नाही"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"अज्ञात वर्ण"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"अधिक चिन्‍हे"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"कॅपिटल आय, वर बिंदू"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"अज्ञात प्रतीक"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"अज्ञात इमोजी"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"कंटाळलेला चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"गोरामोरा झालेला चेहरा"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"उन्हाचा चष्मा घातलेला चेहरा"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"आश्चर्यचकित झालेला चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"चुंबन घेणारा चेहरा"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"अत्यंत संतापलेला चेहरा"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"वैकल्पिक वर्ण उपलब्ध आहेत"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"वैकल्पिक वर्ण डिसमिस केलेले आहेत"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"वैकल्पिक सूचना उपलब्ध आहेत"</string>
diff --git a/java/res/values-mr-rIN/strings.xml b/java/res/values-mr-rIN/strings.xml
index 3ef3cf2..77110d1 100644
--- a/java/res/values-mr-rIN/strings.xml
+++ b/java/res/values-mr-rIN/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"कीप्रेस करताना होणारे कंपन"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"कीप्रेस करताना होणारा ध्वनी"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"कीप्रेस करताना पॉपअप"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"प्राधान्ये"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"खाती आणि गोपनीयता"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"स्वरूप आणि लेआउट"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"जेश्चर टायपिंग"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"मजकूर दुरुस्ती"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"प्रगत"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"थीम"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"विभाजित कीबोर्ड सक्षम करा"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google कीबोर्ड संकालन"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"संकालन चालू केले आहे"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"डिव्‍हाइसेस वरून आपला वैयक्तिक शब्दकोश संकालित करा"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"आता संकालन करा"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"मेघ डेटा हटवा"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google वरून आपला संकालित केलेला डेटा हटविते"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"आपला संकालित केलेला डेटा मेघवरून हटविला जाईल. आपल्‍याला खात्री आहे?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"हटवा"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"रद्द करा"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"आपली वैयक्तिक निर्देशिका Google सर्व्हरवर संकालित केली जाईल आणि बॅकअप घेतला जाईल. आमचे उत्पादन सुधारित करण्यात मदत करण्यासाठी शब्दाच्या वारंवारतेची आकडेवारी माहिती गोळा केली जाऊ शकते. सर्व माहितीचे संकलन आणि वापर "<a href="https://www.google.com/policies/privacy">"Google चे गोपनीयता धोरण"</a>" शी सुसंगत असेल."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"या डिव्हाइसमध्ये हे वैशिष्ट्य सक्षम करण्यासाठी कृपया एक Google खाते जोडा"</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">"भाषा स्विच की अन्य इनपुट पद्धती देखील समाविष्ट करते"</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">"स्लाइड दर्शक दर्शवा"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"व्हॉइस इनपुट की"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"व्हॉइस इनपुट पद्धती सक्षम केल्या नाहीत. भाषा आणि इनपुट सेटिंग्ज तपासा."</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="language_selection_title" msgid="3666971864764478269">"भाषा"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"मदत आणि अभिप्राय"</string>
+    <string name="select_language" msgid="5709487854987078367">"भाषा"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"जतन करण्यासाठी पुन्हा स्पर्श करा"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"जतन करण्यासाठी येथे स्पर्श करा"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"शब्दकोश उपलब्ध"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"कीबोर्ड थीम"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"खाती स्विच करा"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"कोणतीही खाती निवडली नाहीत"</string>
+    <string name="account_selected" msgid="2846876462199625974">"सध्‍या <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> चा वापर करीत आहे"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ठीक आहे"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"रद्द करा"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"साइन आउट करा"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"वापरण्‍यासाठी एक खाते निवडा"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"इंग्रजी (यूके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"इंग्रजी (यूएस)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पॅनिश (यूएस)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिंग्लिश"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"सर्बियन (लॅटिन)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"इंग्रजी (यूके) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"इंग्रजी (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्पॅनिश (यूएस) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिंग्लिश (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियन (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (पारंपारिक)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (लॅटिन)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (संक्षिप्त)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"भाषा नाही (वर्णमाला)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णमाला (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णमाला (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"वर्णमाला (कोलमॅक)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"वर्णमाला (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"इमोजी"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"कीबोर्ड थीम"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"सानुकूल इनपुट शैली"</string>
     <string name="add_style" msgid="6163126614514489951">"शैली जोडा"</string>
     <string name="add" msgid="8299699805688017798">"जोडा"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> साठी ही फाईल खरोखर स्थापित करायची?"</string>
-    <string name="error" msgid="8940763624668513648">"एक त्रुटी आली"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"की जास्त दाबण्यात विलंब"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"आता आपण <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">"लाँचर मध्ये अनुप्रयोग चिन्ह प्रदर्शित करा"</string>
     <string name="app_name" msgid="6320102637491234792">"शब्दकोश प्रदाता"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"शब्दकोश प्रदाता"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"शब्दकोश सेवा"</string>
@@ -181,9 +178,9 @@
     <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="1583881200688185508">"आपल्या मोबाईल डिव्हाइसवर निवडलेल्या भाषेमध्ये शब्दकोश उपलब्ध आहे.&lt;br/&gt; आम्ही आपला टायपिंग अनुभव सुधारण्यासाठी <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्दकोश &lt;b&gt;डाउनलोड करण्याची&lt;/b&gt; शिफारस करतो.&lt;br/&gt; &lt;br/&gt; डाउनलोड कऱण्यास 3G वर एक किंवा दोन मिनिट लागू शकतात. आपल्याकडे &lt;b&gt;अमर्यादित डेटा योजना&lt;/b&gt; नसल्यास शुल्क लागू शकते. आपल्याकडे असलेल्या डेटा योजनेबद्दल आपण सुनिश्चित नसल्यास, डाउनलोड स्वयंचलितपणे प्रारंभ करण्यासाठी Wi-Fi कनेक्शन शोधण्याची शिफारस आम्ही करतो.&lt;br/&gt; &lt;br/&gt; टीप: आपण आपल्या मोबाईल डिव्हाइसच्या &lt;b&gt;सेटिंग्ज&lt;/b&gt;मेनूमधील &lt;b&gt;भाषा आणि इनपुट&lt;/b&gt; वर जाऊन शब्दकोश डाउनलोड करू आणि काढू शकता."</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"आपल्या मोबाईल डिव्हाइसवर निवडलेल्या भाषेमध्ये शब्दकोश उपलब्ध आहे.&lt;br/&gt; आम्ही आपला टायपिंग अनुभव सुधारण्यासाठी <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> शब्दकोश &lt;b&gt;डाउनलोड करण्याची&lt;/b&gt; शिफारस करतो.&lt;br/&gt; &lt;br/&gt; डाउनलोड कऱण्यास 3G वर एक किंवा दोन मिनिट लागू शकतात. आपल्याकडे &lt;b&gt;अमर्यादित डेटा योजना&lt;/b&gt; नसल्यास शुल्क लागू शकते. आपल्याकडे असलेल्या डेटा योजनेबद्दल आपण सुनिश्चित नसल्यास, डाउनलोड स्वयंचलितपणे प्रारंभ करण्यासाठी वाय-फाय कनेक्शन शोधण्याची शिफारस आम्ही करतो.&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>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi वर डाउनलोड करा"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"वाय-फाय वर डाउनलोड करा"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> साठी शब्दकोश उपलब्ध आहे"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"पुनरावलोकन करण्यासाठी आणि डाउनलोड करण्यासाठी दाबा"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"डाउनलोड करत आहे: <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> साठी सूचना लवकरच तयार होतील."</string>
diff --git a/java/res/values-ms-rMY/strings-talkback-descriptions.xml b/java/res/values-ms-rMY/strings-talkback-descriptions.xml
index d5ae637..ed4ff0d 100644
--- a/java/res/values-ms-rMY/strings-talkback-descriptions.xml
+++ b/java/res/values-ms-rMY/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Tiada teks dimasukkan"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> membetulkan <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> menjadi <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> melakukan auto pembetulan"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Tiada cadangan"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Aksara yang tidak diketahui"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Lagi simbol"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I huruf besar, titik di atas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol yang tidak diketahui"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji yang tidak dikethui"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Muka bosan"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Muka malu"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Muka memakai cermin mata hitam"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Muka terkejut"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Muka bercium"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Muka masam"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Aksara alternatif adalah tersedia"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Aksara alternatif diketepikan"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Cadangan alternatif tersedia"</string>
diff --git a/java/res/values-ms-rMY/strings.xml b/java/res/values-ms-rMY/strings.xml
index 1abe4fc..ac482d1 100644
--- a/java/res/values-ms-rMY/strings.xml
+++ b/java/res/values-ms-rMY/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Getar pada tekanan kekunci"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Bunyi pada tekanan kekunci"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop timbul pada tekanan kunci"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Pilihan input"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Tampilan"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Pilihan berbilang bahasa"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Plhn taipan gerak isyarat"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Pilihan"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Akaun &amp; Privasi"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Penampilan &amp; Bentangan"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Taipan Gerak Isyarat"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Pembetulan teks"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Lanjutan"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Dayakan papan kekunci terpisah"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Penyegerakan Papan Kekunci Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Penyegerakan dihidupkan"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Segerakkan kamus peribadi anda merentas peranti"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Segerakkan sekarang"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Padamkan data awan"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Memadam data disegerak anda dari Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Data yang disegerakkan akan dipadamkan daripada awan. Anda pasti?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Padam"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Batal"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Kamus peribadi anda akan disegerakkan dan disandarkan ke pelayan Google. Maklumat statistik kekerapan perkataan mungkin dikumpulkan untuk membantu mempertingkatkan produk kami. Pengumpulan dan penggunaan semua maklumat adalah selaras dengan "<a href="https://www.google.com/policies/privacy">"Dasar Privasi Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Sila tambahkan akaun Google pada peranti ini untuk mendayakan ciri ini"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Tukar ke kaedah input lain"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kunci pertukaran bahasa meliputi kaedah masukan lain juga"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Kekunci tukar bahasa"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Tunjukkan apabila berbilang bahasa input didayakan"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Tunjukkan penunjuk slaid"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Paparkan petunjuk visual semasa meluncur daripada kekunci Shift atau Simbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Pop tmbl knci ketpkn lengah"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tiada kelewatan"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Lalai"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Kamus utama"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Tunjukkan cadangan pembetulan"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Paparkan cadangan perkataan semasa menaip"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Sentiasa tunjukkan"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Tunjukkan dalam mod potret"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Sentiasa sembunyikan"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Sekat perkataan yg menyinggung"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Jangan cadangkan perkataan yang boleh menyinggung"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Auto pembetulan"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Kunci input suara"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Tiada kaedah input suara didayakan. Semak Bahasa &amp; tetapan input."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Hantar maklum balas"</string>
-    <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Bahasa"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Bantuan &amp; m/balas"</string>
+    <string name="select_language" msgid="5709487854987078367">"Bahasa"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Sentuh lagi untuk menyimpan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Sentuh di sini untuk menyimpan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema papan kekunci"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Beralih akaun"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Tiada akaun dipilih"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Pada masa ini menggunakan <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Batal"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Log keluar"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Pilih akaun untuk digunakan"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Bahasa Inggeris (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Bahasa Inggeris (Australia)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Bahasa Sepanyol (AS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Bahasa Serbia (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Bahasa Inggeris (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Bahasa Inggeris (AS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Bahasa Sepanyol (AS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Bahasa Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradisional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyril)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Sarat)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Tiada bahasa (Abjad)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Abjad (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Abjad (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Abjad (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Tema papan kekunci"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Putih Halo"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Biru Halo"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Gelap Fizikal"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Terang Fizikal"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Gaya input peribadi"</string>
     <string name="add_style" msgid="6163126614514489951">"Tambah gaya"</string>
     <string name="add" msgid="8299699805688017798">"Tambah"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Dayakan"</string>
     <string name="not_now" msgid="6172462888202790482">"Bukan sekarang"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"The same input style already exists: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Kelewatan tekan lama kekunci"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Tempoh getaran tekan kekunci"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Kelantangan bunyi tekan kekunci"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Baca fail kamus luaran"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Tiada fail kamus dalam folder Muat Turun"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pilih fail kamus untuk dipasang"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Betul-betul pasang fail ini untuk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Berlaku ralat"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Kelewatan tekan lama kekunci"</string>
     <string name="button_default" msgid="3988017840431881491">"Lalai"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Selamat datang ke <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"dengan Taipan Gerak Isyarat"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Kini anda boleh menaip dalam semua apl kegemaran anda dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurasikan bahasa tambahan"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Selesai"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Tunjukkan ikon apl"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Paparkan ikon apl dalam pelancar"</string>
     <string name="app_name" msgid="6320102637491234792">"Pembekal Kamus"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Pembekal Kamus"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Perkhidmatan Kamus"</string>
diff --git a/java/res/values-my-rMM/strings-action-keys.xml b/java/res/values-my-rMM/strings-action-keys.xml
index 888f551..d15c9e5 100644
--- a/java/res/values-my-rMM/strings-action-keys.xml
+++ b/java/res/values-my-rMM/strings-action-keys.xml
@@ -20,19 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for label_go_key (4033615332628671065) -->
-    <skip />
-    <!-- no translation found for label_next_key (5586407279258592635) -->
-    <skip />
-    <!-- no translation found for label_previous_key (1421141755779895275) -->
-    <skip />
-    <!-- no translation found for label_done_key (7564866296502630852) -->
-    <skip />
-    <!-- no translation found for label_send_key (482252074224462163) -->
-    <skip />
+    <string name="label_go_key" msgid="4033615332628671065">"သွားပါ"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"ရှေ့ဆက်ရန်"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"ယခင်က"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"လုပ်ပြီး"</string>
+    <string name="label_send_key" msgid="482252074224462163">"ပို့ရန်"</string>
     <string name="label_search_key" msgid="7965186050435796642">"ရှာဖွေရန်"</string>
-    <!-- no translation found for label_pause_key (2225922926459730642) -->
-    <skip />
-    <!-- no translation found for label_wait_key (5891247853595466039) -->
-    <skip />
+    <string name="label_pause_key" msgid="2225922926459730642">"ဆိုင်းငံ့ရန်"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"စောင့်ဆိုင်းရန်"</string>
 </resources>
diff --git a/java/res/values-my-rMM/strings-appname.xml b/java/res/values-my-rMM/strings-appname.xml
new file mode 100644
index 0000000..9ab48f4
--- /dev/null
+++ b/java/res/values-my-rMM/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<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">"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-my-rMM/strings-config-important-notice.xml b/java/res/values-my-rMM/strings-config-important-notice.xml
new file mode 100644
index 0000000..724ff50
--- /dev/null
+++ b/java/res/values-my-rMM/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"အကြံပေးမှုတိုးတက်စေရန် သင့်လူမှုအဖွဲ့စည်းမှ သင်ယူကာ အချက်လက်ကို ရိုက်ပါ"</string>
+</resources>
diff --git a/java/res/values-my-rMM/strings-emoji-descriptions.xml b/java/res/values-my-rMM/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..4caf8d5
--- /dev/null
+++ b/java/res/values-my-rMM/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"မူပိုင်ခွင့်အမှတ်"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"မှတ်ပုံတင်သင်္ကေတ"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"နှစ်ထပ် အာမေဍိတ် အမှတ်"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"အာမေဍိတ် မေးခွန်းအမှတ်အသား"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"ကုန်သွယ်မှု အမှတ်အသား"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"သတင်းဌာန"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"ဘယ်ညာမြှား"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"အပေါ်အောက် မြှား"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"အနောက်မြောက်မြှား"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"အရှေ့မြောက်မြှား"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"အရှေ့တောင်မြှား"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"အနောက်တောင် မြှား"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"ဘယ်ဖက်ညွှန်နေသည့် ချိတ်နှင့်မြှား"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"ညာဖက်ညွှန်နေသည့် ချိတ်နှင့်မြှား"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"လက်ပတ်နာရီ"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"သဲနာရီ"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"အမဲရောင် ညာဘက်ညွှန်ပြသော တြိဂံနှစ်ခု"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"အမဲရောင် ဘယ်ဘက်ညွှန်ပြသော တြိဂံနှစ်ခု"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"အမဲရောင် အပေါ်ဘက်ညွှန်ပြသော တြိဂံနှစ်ခု"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"အမဲရောင် အောက်ဘက်ညွှန်ပြသော တြိဂံနှစ်ခု"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"နာရီနှိုးစက်"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"သဲမှုန်များစီးနေသည့် သဲနာရီ"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"စက်ဝိုင်းဝိုင်းထားသည့် လက်တင် m စာလုံးကြီး"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"အမဲရောင် သေးငယ်သည့် စတုရန်း"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"အဖြူရောင်လေးထောင့်ငယ်"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"အမဲရောင် ညာဘက်ညွှန်ပြသော တြိဂံ"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"အမဲရောင် ဘယ်ဘက်သို့ညွှန်ပြသော တြိဂံ"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"အဖြူရောင်လေးထောင့်လတ်"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"အမဲရောင်လေးထောင့်လတ်"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"အဖြူရောင်လေးထောင့်အလတ်ငယ်"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"အမဲရောင် အလယ်လတ်သေးငယ်သည့် လေးထောင့်"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"အလင်းတန်းများနှင့် အမဲရောင်နေ"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"မိုးတိမ်"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"အမဲရောင် တယ်လီဖုန်း"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"အမှန်ခြစ်ပါသည့် လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"ထီးနှင့် မိုးရေစက်များ"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"အပူ သောက်စရာ"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"အပေါ်ညွှန်ပြသည့် လက်ညိုး"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"အဖြူရောင် ပြုံးနေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"မိဿ"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"ပြိဿ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"မေထုန်"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"ကရကဋ်"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"သိဟ်"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"ကန်"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"တူ"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"ဗြိစ္ဆာ"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"ဓနု"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"မကာရ"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"ကုံ"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"မိန်"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"အမဲရောင် စပိတ်ဖဲ"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"အမဲရောင် ကလပ်ဖဲ"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"အမဲရောင် အသဲနှလုံးဖဲ"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"အမဲရောင် စိန်ပွင့်ဖဲ"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"ပူသည့် နွေရာသီ"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"အမဲရောင် ကမ္ဘာလုံးဆိုင်ရာ ပြန်လည်သုံးစွဲရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"ဘီးတက်ကုလားထိုင် သင်္ကေတ"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"ကျောက်ဆူး"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"သတိပေး သင်္ကေတ"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"ဗို့အားမြင့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"အလယ်လတ် အဖြူရောင်စက်ဝိုင်း"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"အမဲရောင် အလယ်လတ် စက်ဝိုင်း"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"ဘောလုံးကန်သည့် ဘောလုံး"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"ဘေ့စ်ဘော"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"နှင်းမရှိသည့် နှင်းလူသား"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"တိမ်နောက်ကွယ်က နေ"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"အိုဖီယူချက်စ်"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"မဝင်ရ"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"ခရစ်ယာန် ဘုရားကျောင်း"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"ဖောင်တိန်"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"အပေါက်ထဲရှိ အလံ"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"ရွက်လှေ"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"တဲ"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"လောင်စာဆီပိုက်"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"အမဲရောင်ကပ်ကြေး"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"ထူထဲသည့် အဖြူရောင် အမှန်ခြစ် အမှတ်အသား"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"လေယာဉ်ပျံ"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"စာအိတ်"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"လက်သီးထောင်"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"လက်မြောက်"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"အောင်မြင်သည့်လက်"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"ခဲတံ"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"အမဲရောင်ထိပ်"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"ထူထဲသည့် အမှန်ခြစ် အမှတ်အသား"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"ထူထဲသည့် အမြောက် အမှတ်အသား"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"မီးပန်း"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"ရှစ်ချောင်းပါ ကြယ်ပွင့်"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"ရှစ်မှတ်ပါသော အမဲရောင်ကြယ်"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"နှင်းပွင့်"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"မီးပန်း"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"ကြက်ခြေခက်အမှတ်အသား"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"ကြက်ခြေခက် စတုရန်းကွက်အား ရွှေ့ရန်"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"အမဲရောင် မေးခွတ်းအမှတ်သား အဆင်တန်ဆာ"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"အဖြူရောင် မေးခွန်းအမှတ်သား အဆင်တန်ဆာ"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"အဖြူရောင် အာမေဍိတ်အမှတ်သား အဆင်တန်ဆာ"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"ထူထဲသည့် အာမေဍိတ်အမှတ်သား သင်္ကေတ"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"လေးလံသည့် အမဲရောင် အသဲနှလုံး"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"ထူထဲသည့် အပေါင်းလက္ခဏာ"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"ထူထဲသည့် အနုတ်လက္ခဏာ"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"ထူထဲသည့် အစားလက္ခဏာ"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"အမဲရောင် ညာဘက်ပြသည့် မြှား"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"မြင်းကွေးအကွင်း"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"မျဉ်းကွေးနှစ်ထပ်"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"ညာဘက်ပြ၍ အပေါ်သို့ကွေးတက်သွားသည့် မြှား"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"ညာဘက်ပြ၍ အောက်သို့ကွေးဆင်းသွားသည့် မြှား"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"ဘယ်ဖက်သို့ညွှန်ပြသော အမဲရောင်မြှား"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"အပေါ်ထောင် အမဲရောင်မြှား"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"အောက်စိုက် အမဲရောင်မြှား"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"အမဲရောင် အတုရန် အကြီး"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"အဖြူရောင် စတုရန်း အကြီး"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"အဖြူရောင် အလယ်လတ်ကြယ်"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"ထူထဲသည့် စက်ဝိုင်းကြီး"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"ကွေးကောက်သည့်"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"အစိတ်ပိုင်း ပြောင်းလဲခြင်း အမှတ်"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"ဝိုင်ထားသည့် စာသင်္ကေတ ဝမ်းသာပါသည်"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"စက်ဝိုင်းဝိုင်းထားသည့် အရုပ်စာ လျှို့ဝှက်ချက်"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"မာကျောင်တုံး နဂါးနီ"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"အမဲရောင်ဂျိုကာ ဖဲကစား"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"သွေးအမျိုးအစား A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"သွေးအမျိုးအစား B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"သွေးအမျိုးအစား O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"ကားရပ်ရန်နေရာ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"သွေးအမျိုးအစား AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"လေးထောင့်ကွက် CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Squared အေး"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"လေးထောင့်ကွက် အခမဲ့"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Squared အိုင်ဒီ"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"လေးထောင့်ကွက်အသစ်"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Squared N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"အိုကေ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Squared SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"လေးထောင့်ကွက် အာမေဍိတ် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"လေးထောင့်ကွက် vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"ဤနေရာတွင် ကသကန လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"ကသကန လေးထောင့်ကွက် ဝန်ဆောင်မှု"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"အခမဲ့ အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"ကြိုတင်မှာယူထားသည့် ထိုင်ခုံနေရာ အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"တားမြစ်ခြင်း အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"လစ်လပ်နေရာ အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"လက်ခံခြင်း အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"အပြည့်အဝလုပ်ဆောင်ခြင်း အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Squared သင်္ကေတပေးချေပြီး"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"လစဉ် အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"အပလီကေးရှင်း အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"လျှော့ဈေး အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"စီးပွားရေးတွင် အရုပ်စာ လေးထောင့်ကွက်"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"စက်ဝိုင်းအရုပ်စာ အားသာမှု"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"စက်ဝိုင်းအရုပ်စာ လက်ခံ"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"ဆိုင်ကလုန်း"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"မြူဆိုင်း"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"ထီးပိတ်"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"ကြယ်များနှင့်ည"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"တောင်များကြား နေထွက်"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"နေထွက်"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"မှောင်ရီစချိန် မြို့တော်"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"အဆောက်အဦများကြား နေဝင်"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"သက်သန့်"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"ညတံတား"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"ရေလှိုင်း"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"မီးတောင်"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"နဂါးငွေ့တန်း"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"ကမ္ဘာ့စက်ဝန်း ဉရောပ−အာဖရိက"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"အမေရိကန် ကမ္ဘာလုံး"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"ကမ္ဘာ့စက်ဝန်း အာရှ−ဩစတြေးလျား"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"လောင်တီတွတ် လိုင်းများနှင့် ကမ္ဘာလုံး"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"လအသစ် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"လဆန်းသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"ပထမ လေးခြမ်းလသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"လဆန်း လဝန်းသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"လပြည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"လဆုတ် လဝန်းသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"နောက်ဆုံးအခြမ်း လသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"လဆုတ် လခြမ်းသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"လခြမ်း"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"လအသစ်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"ပထမအခြမ်း လမျက်နှာ"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"နောက်ဆုံးအခြမ်း လမျက်နှာ"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"လပြည့် လမျက်နှာ"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"နေမျက်နှာ"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"စိတ်ဝင်စားဖွယ် ကြယ်"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"ကြယ်ကြွေ"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"သစ်အယ်သီး"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"ကြီးထွားလာသော အပင်ငယ်"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"အမြဲစိမ်းသစ်ပင်"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"ရွက်ပြက်သစ်ပင်"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"အုန်းပင်"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"ရှားစောင်းပင်"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"ခတ္တာ"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"ချယ်ရီပွင့်"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"နှင်းဆီ"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"ခေါင်ရမ်းပန်း"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"နေကြာပန်း"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"ပွင့်လန်း"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"ပြောင်းဖူးစေ့"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"ဆန်ဆေ့"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"ဆေးဘက်ဝင်အပင်"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"လေးပွင့်ဆိုင်အရွက်"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"မေပယ်ရွက်"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"ရွက်ကြွေ"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"လေထဲဝဲနေသည့် အရွက်"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"မှို"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"ခရမ်းချဉ်သီး"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"ခရမ်းသီး"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"စပျစ်သီး"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"ဖရဲသီး"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"ဖရဲသီး"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"ပြားလိမ္မော်"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"သံပုရာ"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"ငှက်ပျောသီး"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"နာနက်"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"အနီရောင် ပန်းသီး"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"အစိမ်းရောင် ပန်းသီး"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"သစ်သော်သီး"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"မက်မွန်"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"ချယ်ရီ"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"စတော်ဘယ်ရီ"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ဟမ်ဘာဂါ"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"ပီဇာအစိတ်"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"အရိုးများနှင့်အသား"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"ကြက်ခြေထောက်"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"ဆန်လုံးစိကျော်"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"ထမင်းလုံး"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"ချက်ထားသည့်ထမင်း"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"ဟင်းနှင့်ထမင်း"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"ပြုတ်သည့်အိုး"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"အီတာလျံခေါက်ဆွဲ"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ပေါင်မုန့်"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"အာလူးချောင်းကျော်"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"အာလူးအချိုကင်"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"သာဂူလုံး"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ဂျပန်ဆောင်းရာသီ အစားစာ"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"ဆူရှီ"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"ပုဇွန်ထုပ်ကျော်"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"ပန်းဒီဇိုင်းနှင့် ငါးကိတ်"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"ရေခဲမုန့်ပျော့"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"ရေခဲခြစ်"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"အိုက်စ်ကရင်မ်"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ဒိုးနတ်"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"ကွတ်ကီ"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"ချောကလတ်ချောင်း"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"ချိုချဉ်"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"လော်လီပေါ့"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"ကြက်ဉနို့ပေါင်း"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"ပြားရည်အိုး"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ကိတ်သေး"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"ထမင်းဘူး"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"ဟင်းအိုး"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"ချက်ပြုတ်ခြင်း"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ခက်ရင်းနှင့်ဓါး"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"လက်ကိုင်မပါသော လဖ္ဘက်ရည်ခွက်"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"အရက်ပုလင်းနှင့် ခွက်"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"ဝိုင်ပုလင်း"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"အရက်ချိုခွက်"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"အရက်ချို"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"ဘီယာခွက်"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ဘီယာခွက်များတိုက်ခြင်း"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ကလေးပုလင်း"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ဖဲကြိုး"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"ထုပ်ပိုးထားသည့် လက်ဆောင်"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Birthday cake"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"ဖယုံသီးအားထွင်းထားသည့် မီးအိမ်"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"ခရစ္စမတ် သစ်ပင်"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"အဖေခရစ္စမတ်"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"မီးရှူးမီးဆိုင်း"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"မီးရှူးမီးဆိုင်းဖောက်တံ"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"မိုးပျံပူဖောင်း"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"ပါတီ ဖောက်တံ"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"ရောင်စုံစက္ကူဘောလုံး"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"သနဘာသပင်"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"ကြက်ခြေခက် အလံများ"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"သစ်တော အလှဆင်ခြင်း"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"ဂျပန်အရုပ်များ"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"ငါးသဏ္ဍာန်လေလွင့် ခြေအိပ်"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"လေတူရိယာ"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"လကြည့်ပွဲ"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"ကျောင်း သားရေလွယ်အိတ်"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"ဘွဲ့ဦးထုပ်"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"မြင်းချားရဟတ်"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"ချားရဟတ်"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"ရိုလာကိုစတာ"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"ငါးမြားတံနှင့် ငါး"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"မိုက်ခရိုဖုန်း"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"ရုပ်ရှင်ကင်မရာ"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"ရုပ်ရှင်"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"နားကြပ်"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"အနုပညာရှင် ဆေးချယ်ဘမ်း"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"ထိပ်ဆုံးဦးထုပ်"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"ဆပ်ကပ်တဲ"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"လက်မှတ်"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"ရုပ်ရှင်ကလက်"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"တင်ဆက်ခြင်း အနုပညာ"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"ဗီဒီယိုဂိမ်း"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"တိုက်ရိုက်ထိချက်"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"အကြွေစေ့ထည့်စက်"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"ဘီလိယပ်"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"ဂိမ်းအံစာတုံး"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"ဘိုးလင်းပစ်ကစားခြင်း"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"ပန်းပွင့်ဖဲချပ်များ"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"တေးဂီတ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"များပြားသည့် တေးဂီတ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"ဆက်ဆိုဖုန်း"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"ဂီတာ"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"ဂီတကီးဘုတ်"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"လေမုတ်ခရာ"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"သယော"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"ဂီတနုတ်"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"အပြေးအင်္ကျီနှင့် စလွယ်"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"တင်းနစ် ရက်ကက်နှင့် ဘောလုံး"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"နှင်းလျှောစီးခြင်းနှင့် နှင်းလျှောစီးဘုတ်"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"ဘတ်စကတ်ဘောနှင့် သံပတ်ပြား"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"အကွက်ဆင်အလံ"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"ရေခဲပြင်လျှောစီး"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"အပြေးသမား"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"ရေလှိုင်းစီးသူ"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ဒိုင်းဆု"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"မြင်းအပြေးပြိုင်"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"အမေရိကန် ဘောလုံး"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"ရက်ဘီဘောလုံး"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"ရေကူးသမား"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"အိမ်အဆောက်အဦး"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"အိမ်နှင့် ပန်းခြံ"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"ရုံးအဆောက်အဦး"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"ဂျပန်စာတိုက်ရုံး"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"ဉရောပစာတိုက်ရုံး"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"ဆေးရုံ"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ဘဏ်"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"အလိုလျောက်ပြောသည့်စက်"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ဟော်တယ်"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"အချစ်ဟော်တယ်"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"ကုန်စုံဆိုင်"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"ကျောင်း"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ကုန်စုံဆိုင်ကြီး"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"စက်ရုံ"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"စက္ကူမီးအိမ်"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"ဂျပန်ရဲတိုက်"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"ဥရောပရဲတိုက်"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"ကြွက်"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"ကြွက်"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"နွားထီး"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"ရေကျွဲ"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"နွား"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"ကျားသစ်"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"ယုံ"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"ကြောင်"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"နဂါး"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"မိကျောင်း"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"ဝေလှငါး"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"ခရု"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"မြွေ"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"မြင်း"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"သိုးထီး"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"ဆိတ်"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"သိုး"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"မျောက်"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"ကြက်ဖ"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"ကြက်မ"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"ခွေး"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"ဝက်"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"ဝက်သိုး"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ဆင်"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ရေဘဝဲ"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"ခရုခွံ"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"ကြမ်းပိုး"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"ပုရွက်ဆိပ်"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"ပြား"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"နွားချေးပိုး"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"ငါး"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"အပူပိုင်းဒေသငါး"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"အဆူးငါး"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"လိပ်"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"ကြက်ပေါက်"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"ကြက်ကလေး"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"အရှေ့ဘက်မျက်နှာမူနေသည့် ကြက်ကလေး"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"ငှက်"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"ပင်ဂွင်း"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"ကိုလာဝက်ဝံ"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"အမွေးဆုတ်ဖွားခွေး"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"သစ်ကုလားအုပ်"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"ဘို့နှစ်လုံးရှိသော ကုလားအုတ်"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"ဖျံ"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"ကြွက်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"နွားမျက်နှာ"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"ကျားမျက်နှာ"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"ယုံမျက်နှာ"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"နဂါးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"ရေစုတ်ထုတ်နေသည့် ဝေလှငါး"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"မြင်းမျက်နှာ"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"မျောက်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"ခွေးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"ဝက်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"ဖားမျက်နှာ"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"မြီးတိုပါးတွဲကြွက် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"မြေခွေးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"ဝက်ဝံမျက်နှာ"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"ပန်ဒါဝက်ဝံ မျက်နှာ"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"ဝက်နှာခေါင်း"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"ခြေရာများ"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"မျက်လုံးများ"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"နားရွက်"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"နှာခေါင်း"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"ပါးစပ်"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"လျှာ"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"လက်ညိုးအပေါ်သို့ထိုး"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"လက်ညိုးအောက်သို့ထိုး"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"လက်ညိုးဘယ်သို့ထိုး"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"လက်ညိုးညာသို့ထိုး"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"လက်သီးဆုပ်သည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"လက်ဝှေ့ယမ်းသည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"အိုကေလက် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"လက်မထောင် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"လက်မ အောက်စိုက် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"လက်ခုပ်တီးနေသည့်သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"လက်ဖြန့်သည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"သရဖူ"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"အမျိုးသမီးဦးထုပ်"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"မျက်မှန်"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"နက်တိုင်"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"တီရှပ်"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ဂျင်း"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"ဝတ်ရုံ"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"ကီမိုနို"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"ရေကူးဝတ်စုံ"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"အမျိုးသမီးအဝတ်အထည်များ"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"ပိုက်ဆံအိပ်"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"လက်ကိုင်အိပ်"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"အိတ်သေး"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"အမျိုးသားရှူးဖိနပ်"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"အားကစားရှုးဖိနပ်"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ဒေါက်မြင့်ဖိနပ်"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"အမျိုးသမီး ညှပ်ဖိနပ်"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"အမျိုးသမီးဘွတ်ဖိနပ်"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"ခြေရာများ"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"တစ်ရောင်တည်း လူကိုယ်တစ်ပိုင်း ရုပ်ပုံ"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"အဖြူမဲ ကိုယ်တစ်ပိုင်းပုံ"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"ယောက်ျားလေး"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"မိန်းကလေး"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"ယောက်ျား"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"မိန်းမ"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"မိသားစု"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"ယောက်ျားနှင့် မိန်းမလက်တွဲထား"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"ယောက်ျားနှစ်ယောက် လက်တွဲထား"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"မိန်းမနှစ်ယောက် လက်တွဲထား"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"ရဲအရာရှိ"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"ယုံနားရွက်နှင့် မိန်းမ"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"ခေါင်းဆောင်းပုဝါနှင့် သတို့သမီး"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"ရွှေရောင်ဆံပင်နှင့် လူ"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"တရုတ်ခေါင်းဆောင်းနှင့် ယောက်ျား"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"ပန်ချာပီခေါင်းဆောင်းနှင့် ယောက်ျား"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"အသက်ကြီးယောက်ျား"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"အသက်ကြီးမိန်းမ"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"ကလေး"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"ဆောက်လုပ်ရေး အလုပ်သမား"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"မင်းသမီး"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"ဂျပန်ဘီလူး"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"ဂျပန်မှင်စာ"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"သရဲ"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"ကလေးနတ်သမီး"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"အခြားဂြိုလ်သား"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"ဂြိုလ်သားဘီလူး"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"မှင်စာ"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"ဦးခေါင်းခွန်"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"အချက်လက်ကောင်တာ လူ"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"အစောင့်"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"အကသမား"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"နှုတ်ခမ်းနီ"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"လက်သည်းဆိုးဆေး"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"မျက်နှာ နှိပ်နယ်ခြင်း"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"ဆံပင်ညှပ်"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"ဆံပင်ညှပ်ဆိုင် အလိပ်တိုင်"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"ဆေးထိုးအပ်"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ဆေးလုံး"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"အနမ်းသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"အချစ်စာ"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"အသံမြည်ပေးရန်"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"ကျောက်မျက်ရတနာ"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"အနမ်း"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"ပန်းစည်း"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"အသဲနှလုံးနှင့် အတွဲ"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"မင်္ဂလာဆောင်ခြင်း"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"ခုန်နေသော နှလုံး"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"အသဲကွဲ"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"အသဲနှလုံး နှစ်ခု"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"တောက်ပနေသော နှလုံး"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"ကြီးထွားနေသည့် နှလုံး"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"မြှားနှင့် အသဲနှလုံး"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"အပြာရောင် နှလုံးသား"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"အစိမ်းရောင် နှလုံးသား"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"အဝါရောင် အသဲနှလုံး"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"ခရမ်းရောင် အသဲနှလုံး"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"ဖဲပြားနှင့် အသဲနှလုံး"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"လည်နေသည့် နှလုံးသားများ"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"အသဲနှလုံး အလှဆင်ခြင်း"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"အတွင်းတွင် အစက်တစ်စက်နှင့် စိန်ပုံ"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"လျှပ်စစ်မီးလုံး"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"ဒေါသသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"ဗုံး"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"အိပ်စက်နေသည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"ပေါက်ကွဲသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"ချွေးထွက်နေသည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"ရေစက်"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"အနုတ်သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"မစင်ပုံ"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"လက်မောင်းသား"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"မှူးဝေသည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"စကားပြော ပူပေါင်းကွက်"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"အတွေး ပူပေါင်းကွက်"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"အဖြူရောင်ပန်း"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"အမှတ်တစ်ရာ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"ပိုက်ဆံအိတ်"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"ငွေကြေး လဲလှယ်ခြင်း"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"လေးလံသည့် ဒေါ်လာသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"အကြွေးဝယ်ကဒ်"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ယန်းသင်္ကေတဖြင့် ဘဏ်မှတ်ချက်"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ဒေါ်လာသင်္ကေတနှင့် ဘဏ်မှတ်ချက်"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ယူရိုသင်္ကေတဖြင့် ဘဏ်မှတ်ချက်"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ပေါင်သင်္ကေတနှင့် ဘဏ်မှတ်ချက်"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"အတောင်ပံများနှင့် ပိုက်ဆံ"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"ယန်းသင်္ကေတနှင့် အပေါ်တက်နေသည့် ဇယားကွက်"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"ထိုင်ခုံ"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"ကုဂ္ဂိုလ်ရေးကွန်ပျူတာ"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"သားရေအိပ်ပြား"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"ဒစ်အသေး"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ဖလော့ပီဒစ်"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ဒစ်ခွေ"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"ဒီဗီဒီ"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"ဖိုင်တွဲ"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"ဖိုင်တွဲဖွင့်"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"စာရွက်ကော့်ဖြင့် စာမျက်နှာ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"အပေါ်ထောင်နေသည့် စာမျက်နှာ"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"ပြက္ခဒိန်"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ရွက်ဆုတ် ပြက္ခဒိန်"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"ကဒ်အညွှန်း"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"အပေါ်တက်နေသည့် ဇယား"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"လူကြိုက်များသည့် ဒေါင်းလုပ်များနှင့် ဇယား"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"ဘားတန်းဇယား"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"ကလစ်ဘုတ်"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"ပင်"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"ပင်အဝိုင်း"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"စာရွက်ညှပ်"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"ပေတံဖြောင့်"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"သုံးထောင့်ပေတံ"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"ဘွတ်မှတ်တပ်များ"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"လယ်ဂျာ"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"မှတ်စုစာအုပ်"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"အလှဆင်ထားသည့် အခွံနှင့် မှတ်စုစာအုပ်"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"ပိတ်ထားသည့်စာအုပ်"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"စာအုပ်အပွင့်"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"အစိမ်းရောင်စာအုပ်"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"အပြာရောင်စာအုပ်"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"လိမ္မော်ရောင်စာအုပ်"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"စာအုပ်များ"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"နာမည်တံဆိပ်"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"လိမ့်ချ"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"မီမို"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"တယ်လီဖုန်း လက်ခံစက်"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"ပေဂျာ"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"ဖက်စ်စက်"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"ဂြိုလ်တုအင်တင်နာ"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"ပြည်သူသုံး အသံချဲ့စက်"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ဩဘာပေးသည့် အသံချဲ့စက်"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"အထွက်စာဘန်း"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"အဝင်စာဘန်း"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"အထုပ်"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"အီးမေးလ်သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"စာအိတ်အဝင်"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"အပေါ်တွင် ဒေါင်းလုပ်မြှားပါသည့် စာအိတ်"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"အောက်ခြေအလံပါသည့် စာပုံးအပိတ်"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"အလံပြထားသည့် ပိတ်ထားသော စာပုံး"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"အထက်တွင်အလံပါသည့် စာပုံးအဖွင့်"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"အောက်ခြေတွင်အလံပါသည့် စာပုံးအပွင့်"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"စာတိုက်ပုံး"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"ခရာ"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"သတင်းစာ"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"မိုဘိုင်းဖုန်း"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"ဘယ်ဖက်ရှိ ညာဖက်ဦးတည်သည့်မြှားနှင့် မိုဘိုင်းဖုန်း"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"တှုန်ခါမုဒ်"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"မိုဘိုင်းဖုန်း ပိတ်"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"မိုဘိုင်းဖုန်းများမရှိပါ"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"ဘားတန်းများနှင့် အင်တင်နာ"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"ကင်မရာ"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"ဗီဒီယိုကင်မရာ"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"ရုပ်သံ"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"ရေဒီယို"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"ဗီဒီယိုကက်ဆက်"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"ညာဖက်ညွှန်းနေသေည လှည့်ထားသည့်မြှားများ"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"ညာဖက်နှင့် ဘယ်ဖက်သို့ဦးတည်သည့် နာရီလက်တံအတိုင်းလှည့်သော စက်ဝိုင်းပွင့်မြှားများ"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"နာရီလက်တံအတိုင်း ဘယ်ဖက်နှင့် ညာဖက်သို့ညွှန်းသည့် စက်ဝိုင်းထပ်ထားသော စက်ဝိုင်းအပွင့်မြှား"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"အောက်ဖက်နှင့် အပေါ်ဖက်သို့ဦးတည်သည့် နာရီလက်တံအတိုင်းလှည့်သော စက်ဝိုင်းပွင့်မြှားများ"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"နာရီလက်တံအတိုင်း အောက်ဖက်နှင့် အပေါ်ဖက်သို့ဦးတည်သည့် နာရီလက်တံအတိုင်းလှည့်သော စက်ဝိုင်းပွင့်မြှားများ"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"တောက်ပမှုနည်းသည့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"တောက်ပမှုမြင့် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"ပယ်ဖျက်သည့် ဘေးတိုက်မျဉ်းနှင့် စပီကာ"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"စပီကာ"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"အသံလှိုင်းတစ်ခုနှင့် စပီကာ"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"အသံလှိုင်းသုံးခုနှင့် စပီကာ"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"ဘတ်ထရီ"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"လျှစ်စစ် ပလပ်"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"ဘယ်ဘက်သို့ညွှန်နေသည့် မှန်ဘီလူး"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"ညာဘက်သို့ညွှန်နေသည့် မှန်ဘီလူး"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"မှင်ဘောပင်ဖြင့် သော့ခတ်"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"ကီးဖြင့်သော့ပိတ်"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"သော့"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"သော့ပိတ်ရန်"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"သော့ပွင့်"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"ခေါင်းလောင်း"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"ပယ်ဖျက်သည့် ဘေးတိုက်မျဉ်းနှင့် ခေါင်းလောင်း"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"စာညုပ်"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"လင့်ခ်သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ရေဒီယို ခလုတ်"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"အပေါ်တွင် ဘယ်ဘက်ပြမြှားနှင့် အနောက်"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"အပေါ်တွင် ဘယ်ဘက်ပြမြှားနှင့် အဆုံး"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"အပေါ်တွင် ဘယ်ညာမြှားနှင့် ဖွင့်ရန် နှင့်အာမေဍိတ် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"ညာဘက်ပြမြှားနှင့် မကြာမှီ"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"အပေါ်ပြမြှားနှင့် အပေါ်"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"ဆယ့်ရှစ်နှစ်အောက် မဝင်ရသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"တစ်ဆယ်ခလုတ်"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"လက်တင်စာလုံးကြီးအတွက် ထည့်သွင်းရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"လက်တင်စာလုံးသေးများအတွက် ထည့်သွင်းရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"ဂဏန်းများအတွက် ထည့်သွင်းရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"သင်္ကေတများအတွက် ထည့်သွင်းရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"လက်တင်စာလုံးများအတွက် ထည့်သွင်းရန် သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"မီး"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"လျှပ်စစ်တို့ထိမှု"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"မူလီလှည့်"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"တူ"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"မူလီနှင့် ဝါရှာ"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"ဓါးသေး"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"ပစ်စတို"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"မိုက်ခရိုစကုပ်"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"တယ်လီစကုပ်"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"အရည်ကြည် ဘောလုံး"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"ခြောက်ထောင့်ရှိ၍ အလယ်မှတ်ပါသော ကြယ်"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"အစပြုသူအတွက် ဂျပန်သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"နေနတ်သင်္ကေတ အမှတ်အသား"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"အမဲရောင် စတုရန်း ခလုတ်"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"အဖြူရောင် လေးထောင့်ခလုတ်"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"အနီရောင် စက်ဝိုင်းကြီး"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"အပြာရောင်စက်ဝိုင်းကြီး"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"လိမ္မော်ရောင် စိန်ကြီး"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"အပြာရောင် စိန်ကြီး"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"လိမ္မော်ရောင် စိန်သေး"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"အပြာရောင် စိန်သေး"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"ပေါ်သို့ညွှန်နေသည့် တြိဂံ"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"အောက်စိုက် အနီရောင်တြိဂံ"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"အပေါ်ထောင်သည့် အနီရောင်တြိဂံ"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"အောက်စိုက် အနီရောင်တြိဂံအသေး"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"နာရီမျက်နှာပြင် တစ်နာရီ"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"နာရီမျက်နှာပြင် နှစ်နာရီ"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"နာရီမျက်နှာပြင် သုံးနာရီ"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"နာရီမျက်နှာပြင် လေးနာရီ"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"နာရီမျက်နှာပြင် ငါးနာရီ"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"နာရီမျက်နှာပြင် ခြောက်နာရီ"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"နာရီမျက်နှာပြင် ခုနှစ်နာရီ"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"နာရီမျက်နှာပြင် ရှစ်နာရီ"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"နာရီမျက်နှာပြင် ကိုးနာရီ"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"နာရီမျက်နှာပြင် ဆယ်နာရီ"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"နာရီမျက်နှာပြင် ဆယ့်တစ်နာရီ"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"နာရီမျက်နှာပြင် ဆယ့်နှစ်နာရီ"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"နာရီမျက်နှာပြင် တစ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"နာရီမျက်နှာပြင် နှစ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"နာရီမျက်နှာပြင် သုံးနာရီခွဲ"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"နာရီမျက်နှာပြင် လေးနာရီခွဲ"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"နာရီမျက်နှာပြင် ငါးနာရီခွဲ"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"နာရီမျက်နှာပြင် ခြောက်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"နာရီမျက်နှာပြင် ခုနှစ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"နာရီမျက်နှာပြင် ရှစ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"နာရီမျက်နှာပြင် ကိုးနာရီခွဲ"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"နာရီမျက်နှာပြင် ဆယ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"နာရီမျက်နှာပြင် ဆယ့်တစ်နာရီခွဲ"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"နာရီမျက်နှာပြင် ဆယ့်နာနာရီခွဲ"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ဖူဂျီတောင်"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"တိုကျိုတာဝါ"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"လေဘာတီရုပ်တု"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"ဂျ"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"မိုရိုက်းရုပ်တု"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"သွားကြိတ်နေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"ပြုံးနေသည့်မျက်လုံးများဖြင့် ကြိတ်သည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"အငိုမျက်လုံး အပြုံးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"ပါးပစ်ပွင့်လျက်သားနှင့် ရီနေသည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"အပြုံးမျက်လုံးများဖြင့် ပါးစပ်ဖွင့်ကာ ရီမောခြင်း"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"ပါးစပ်ဖွင့် ပြုးနေလျက် ချွေးစေးထွက်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"တင်းကြပ်စွာပိတ်ထားသည့် မျက်လုံးများဖြင့် ပါးစပ်ဖွင့်ကာ ရီမောခြင်း"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"ရောင်ခြည်တော်စက်ဝန်းနှင့် အပြုံးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"ဦးချိုနှင့် အပြုံးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"မျက်လုံးမိတ်ပြသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"အပြုံးမျက်လုံးဖြင့် အပြုံးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"အရသာရှိသည့်အစားစာကို သွားရည်ကျသည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"စိတ်သက်သာရာရသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"နှလုံးသားပုံ မျက်လုံးများဖြင့် ရီနေသည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"နေကာမျက်မှန်နှင့် အပြုံးမျက်နှာ"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"ရွဲ့သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"ဓါတ်ပျယ်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"ခံစားချက်မဲ့သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"မပျော်ရွှင်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"ချွေးအေးများနှင့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"စိုးရိမ်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"ဇဝေဇဝါ မျက်နှာ"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"ချွေးပြန်နေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"နမ်းနေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"အနမ်းပေးသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"ပြုံးနေသည့်မျက်လုံးများဖြင့် နမ်းနေသည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"မျက်လုံးပိတ်များဖြင့် နမ်းနေသည့်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"လျှာထုပ်ထားသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"လျှာထုတ်ပြ၍ မျက်လုံး မှိတ်ပြသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"လျှာထုတ်ပြ၍ မျက်လုံး တင်းကြပ်စွာမှိတ်ပြသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"စိတ်ပျက်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"စိုးရိမ်နေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"စိတ်တိုသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"နှုတ်ခမ်းစူသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"ငိုနေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"ဇွဲသန်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"အောင်ပွဲခံသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"စိတ်ပျက်သော်လည်း စိတ်သက်သာရာရသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"ပါးစပ်ဖွင့်လျက် မျက်မှောင်ကြုပ်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"မချိတင်ကဲမျက်နှာ"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"ကြောက်လန့်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"ငြီးငွေ့သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"အိပ်ငိုက်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"မောပန်းသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"မဲ့ရွဲ့သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"ကျယ်လောင်စွာအော်ငိုသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"ပါးစပ်ဟောင်းနေတဲ့ မျက်နှာ"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"တိတ်ဆိတ်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"ပါးစပ်ဖွင့်လျက် ချွေးစေးထွက်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"ကြောက်ရွံ့၍အော်သော မျက်နှာ"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"အံ့အားသင့်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"ရှက်သည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"အိပ်နေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"ခေါင်းမူးသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"ပါးစပ်မပါသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"ဆေးမျက်နှာဖုံးနှင့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"ပြုံးနေသည့်မျက်လုံးများဖြင့် ကြိတ်ကိုက်နေသည့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"အငိုမျက်လုံး အပြုံးနှင့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"ပါးပစ်ပွင့်လျက်သားနှင့် ရီနေသည့်ကြောင်"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"အသဲပုံမျက်နှာများဖြင့် ပြုံးနေသည့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"မချဉ်ပြုံးပြုံးနေသော ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"မျက်လုံးပိတ်များဖြင့် နမ်းနေသည့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"နှုတ်ခမ်းစူနေသည့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"ငိုနေသည့် ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"ငြီးငွေ့စရာ ကြောင်မျက်နှာ"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"အမူအယာ မကောင်းသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"အမူအယာအိုကေသည့် မျက်နှာ"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"ဦးညွှတ်နေသည့် လူ"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"မကောင်းတာမကြည့်သည့် မျောက်"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"မကောင်းတာမနားထောင်သည့် မျောက်"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"မကောင်းတာမပြောသည့် မျောက်"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"လက်တစ်ဖက်ကို ပျော်ရွှင်စွာမြောက်သည်လူ"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"လက်နှစ်ဖက်မြောက်ကာ ပွဲတည်နေသည့်လူ"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"ရှုံမဲ့နေသည့် လူ"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"နှုတ်ခမ်းစူနေသည့် မျက်နှာနှင့်လူ"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"လက်အုပ်ချီထားသည့် လက်နှင့်လူ"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"ဒုံးပျံ"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ဟယ်လီကော်ပတာ"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"ရေနွေးငွေ့ရထား"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"သံလမ်းကား"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"မြန်နှုန်းမြင့် ရထား"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"ကျည်ဆံနှာခေါင်းနှင့် မြန်နှုန်းမြင့် ရထား"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ရထား"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"မြေအောက်ရထား"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"ပေါ့ပါးသည့် ရထား"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"ဘူတာ"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ဓါတ်ကြိုး"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ဓါတ်ကြိုးကား"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"ဘက်စ်"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"လာနေသည့်ဘတ်စ်ကား"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ထရော်လီဘတ်စ်"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"ဘက်စ်ကားဂိတ်"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"ဘက်စ်အသေး"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"လူနာတင်ယာဉ်"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"မီးအင်ဂျင်"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"ရဲကား"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"လာနေသည့် ရဲကား"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"တက္ကစီ"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"လာနေသည့် တက္ကစီ"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"လေးအီးယာဉ်"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"လာနေသည့် ယာဉ်"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"ဖျော်ဖြေရေးယာဉ်"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"ကုန်တင်ယာဉ်"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"နောက်ဆက်တွဲ လော်ရီ"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ထွန်စက်"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"တစ်လိုင်းပြေးရထားလမ်း"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"တောင်တက်ရထားလမ်း"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"အောက်လှိုင်းရထား"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"တောင်တက်ဓါတ်ကြိုးလိုင်း"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ကောင်းကင်ကြိုးရထားလမ်း"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"သင်္ဘော"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"လှော်သည့်လှေ"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"အမြန်သင်္ဘော"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"ရေပြင်ညီယာဉ်အသွားအလာမီး"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ဒေါင်လိုက် မီးပွိုင့်"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"ဆောက်လုပ်ရေး သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"မီးလှည့်နေသောရဲကား"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"စာတိုက်ပေါ်ရှိ သုံးထောင့်အလံ"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"တံခါး"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"ဝင်ပေါက်သင်္ကေတမရှိ"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"ဆေးလိပ်သောခြင်း သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"ဆေးလိပ်မသောက်ရ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"သူ့နေရာနှင့်သူ အမှိုက်ပစ်ပါ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"အမှိုက်မပစ်ရ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"သောက်၍ရသော ရေသင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"သောက်၍မရသော ရေ သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"စက်ဘီး"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"စက်ဘီးမစီးရ"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"စက်ဘီးစီးသူ"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"တောင်တက်စက်ဘီးစီးသူ"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"လမ်းဖြတ်ကူးခြင်း"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"လမ်းဖြတ်မကူးရ"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"ကလေးများ လမ်းဖြတ်ကူးခြင်း"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"ယောက်ျား သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"အမျိုးသမီး သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"နားနေခန်း"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"ကလေး သင်္ကေတ"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"အိမ်သာ"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"ရေအိမ်"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"ရေချိုး"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"ရေချိုးခန်း"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"ရေချိုးကန်"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"ပတ်စပို့ထိန်းချုပ်"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"အကောက်ခွန်"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"ခရီးဆောင်အိတ် ထုတ်ယူရန်"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"ဘယ်ဖက်အိတ်"</string>
+</resources>
diff --git a/java/res/values-my-rMM/strings-letter-descriptions.xml b/java/res/values-my-rMM/strings-letter-descriptions.xml
index 6dabe0f..2d5338b 100644
--- a/java/res/values-my-rMM/strings-letter-descriptions.xml
+++ b/java/res/values-my-rMM/strings-letter-descriptions.xml
@@ -200,7 +200,7 @@
     <string name="spoken_symbol_2105" msgid="7289404939366976829">"Care of"</string>
     <string name="spoken_symbol_2192" msgid="827804523596125414">"ညာညွှန်း မြား"</string>
     <string name="spoken_symbol_2193" msgid="2659541693445985717">"အောက်ညွှန်း မြား"</string>
-    <string name="spoken_symbol_2205" msgid="4457188084269117343">"ပလာ set"</string>
+    <string name="spoken_symbol_2205" msgid="4457188084269117343">"နေရာလွတ်"</string>
     <string name="spoken_symbol_2206" msgid="4856786565708380687">"Increment"</string>
     <string name="spoken_symbol_2264" msgid="5092061257745123554">"ထက်နည်း သို့မဟုတ် တူညီ"</string>
     <string name="spoken_symbol_2265" msgid="1907966479878036357">"ထက်ကြီး သို့မဟုတ် တူညီ"</string>
diff --git a/java/res/values-my-rMM/strings-talkback-descriptions.xml b/java/res/values-my-rMM/strings-talkback-descriptions.xml
index 6908b58..96066f3 100644
--- a/java/res/values-my-rMM/strings-talkback-descriptions.xml
+++ b/java/res/values-my-rMM/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"စကားဝှက်ပြောဆိုမှုကို ကျယ်လောင်စွာ ကြားနိုင်ရန် မိုက်ခွက်ပါနားကြပ် တပ်ပြီး နားထောင်ပါ"</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"လက်ရှိစာသည် %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"စာမရိုက်ထည့်ထားပါ"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> မှ <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> သို့ <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> မှန်ကန်စေသည်"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> အလိုအလျောက် မှန်ကန်ခြင်း လုပ်ဆောင်သည်"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"အကြံပြုချက် မရှိပါ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"မသိရ စာလုံး"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Shiftခလုတ်"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"နောက်ထပ် သင်္ကေတများ"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shiftခလုတ်"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"သင်္ကေတများ"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shiftခလုတ်"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"ဖျက်ရန်"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"သင်္ကေတများ"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"စာများ"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"နံပါတ်များ"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"ဆက်တင်များ"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"တဲဘ်"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"space"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"အသံထည့်သွင်းမှု"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"ရုပ်ပုံသင်္ကေတ"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"နောက်ပြန်သွားရန်"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"ရှာဖွေရန်"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"အစက်"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"ဘာသာစကား ပြောင်းလဲရန်"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"ရှေ့သို့"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"အနောက်သို့"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Shift ဖွင့်ထားသည်"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"စာလုံးကြီးရိုက်ရန် ဖွင့်ထားသည်"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"သင်္ကေတမုဒ်"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"နောက်ထပ်သင်္ကေတမုဒ်"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"စာသားမုဒ်"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"ဖုန်းမုဒ်"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"ဖုန်းသင်္ကေတမုဒ်"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"ဝှက်ထားသည့် ကီးဘုတ်"</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"ဖော်ထားသည့် <xliff:g id="KEYBOARD_MODE">%s</xliff:g> ကီးဘုတ်"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"ရက်စွဲ"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"ရက်စွဲနှင့် အချိန်"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"အီးမေးလ်"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"စာပို့ခြင်း"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"နံပါတ်"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"ဖုန်း"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"စာတို"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"အချိန်"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"မကြာသေးခင်က"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"လူ"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"အရာဝတ္ထုများ"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"သဘာဝ"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"နေရာများ"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"သင်္ကေတများ"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"ခံစားချက်ရုပ်ပုံများ"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"စာလုံးကြီး <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"I အကြီး"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I အကြီး၊ အပေါ်မှာ အစက်"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"မသိရ သင်္ကေတ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"မသိရ အီမိုဂျီ"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"စိတ်ကုန်နေသော မျက်နှာ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"ကသိကအောက် မျက်နှာ"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"နေကာမျက်မှန်တပ် မျက်နှာ"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"အံ့အားသင့်နေသော မျက်နှာ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"နမ်းနေသော မျက်နှာ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"မှုန်ကုပ်ကုပ် မျက်နှာ"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"အစားထိုးစရာ စာလုံးများ ရှိနိုင်"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"အစားထိုးစရာ စာလုံးများကို ပယ်ထား"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"အစားထိုးစရာ အကြံပေးချက်များ ရှိနိုင်"</string>
diff --git a/java/res/values-my-rMM/strings.xml b/java/res/values-my-rMM/strings.xml
index 63cbca3..eafddb1 100644
--- a/java/res/values-my-rMM/strings.xml
+++ b/java/res/values-my-rMM/strings.xml
@@ -20,355 +20,188 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for english_ime_input_options (3909945612939668554) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
-    <skip />
-    <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
-    <skip />
-    <!-- no translation found for sound_on_keypress (6093592297198243644) -->
-    <skip />
-    <!-- no translation found for popup_on_keypress (123894815723512944) -->
-    <skip />
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key (5915478828318774384) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
-    <skip />
-    <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
-    <skip />
-    <!-- no translation found for settings_system_default (6268225104743331821) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict (4435317977804180815) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
-    <skip />
-    <!-- no translation found for use_personalized_dicts (5167396352105467626) -->
-    <skip />
+    <string name="english_ime_input_options" msgid="3909945612939668554">"ထည့်သွင်းရန် နည်းလမ်းများ"</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="settings_screen_preferences" msgid="2696713156722014624">"ရွေးချယ်စရာများ"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"အကောင့်များ &amp; ကိုယ်ပိုင်ကိစ္စ"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"ပုံပန်းသွင်ပြင် &amp; အပြင်အဆင်များ"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"လှုပ်ရှားမှုဖြင့်စာရိုက်ခြင်း"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"စာအမှားပြပြင်ခြင်း"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"အဆင့်မြင့်"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"အပြင်အဆင်"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"ကီးဘုတ် ခွဲခြမ်းမှု ဖွင့်ထားရန်"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Keyboard စင့်လုပ်ရန်"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"စင့် ဖွင့်ထားသည်"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"သင့် ကိုယ်ပိုင်သုံး အဘိဓာန်အား စက်များအားလုံးတွင် စင့်လုပ်ရန်"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ထပ်တူညီအောင် ယခုပြုလုပ်နေပါပြီ…"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Cloud ဒေတာ ဖျက်ရန်"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"သင်၏ စင့်က် လုပ်ပြီးသား ဒေတာ Google ထဲမှ ဖျက်ခံရမည်။"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"သင့် စင့်လုပ်ထားသော ဒေတာများအား cloud မှ ဖျက်လိမ့်မည်။ သေချာသလား?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ဖျက်ရန်"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ဖျက်သိမ်းရန်"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"သင့်ရဲ့ကိုယ်ပိုင်အဘိဓါန်ကို Google server များမှာ ထပ်တူညီအောင်လုပ် ပြီး မူလပုံစံ ပြန်သွားမည်။ အိုင်တီထုတ်ကုန်များ တိုးတက်မှုရှိအောင် စာလုံးရေ ကောက်ယူမှု အချက်အလက်ကို စုစည်းပါသည်။ အဆိုပါအချက်အလက်စုယူ သုံးစွဲမှုကို "<a href="https://www.google.com/policies/privacy">" Google၏မိမိအတွင်းရေးသီးသန့် မူဝါဒ "</a>" ဖြင့် စောဒကတက် နိုင်သည်။"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"ဒီအင်္ဂါရပ်တွေကို ရဖို့ဒီစက်မှာ Google account တစ်ခုကို ဖွင့်ပါ"</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">"ဘာသာပြောင်းသည့် ကီးသည် အခြားထည့်သွင်းရန် နည်းလမ်းများလည်း ပါဝင်သည်"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"ဘာသာစကား ပြောင်းခလုတ်"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"များပြားသည့် ထည့်သွင်းရန်နည်းလမ်းများဖွင့်ထားလျှင် ပြပါ"</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>ms"</string>
+    <string name="settings_system_default" msgid="6268225104743331821">"စနစ်ပုံသေ"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"အဆယ်ကသွယ်အမည်များ အကြံပြုမည်"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"အကြံပြုချက်များနှင့် အမှားပြင်ခြင်းများအတွက် အဆက်သွယ်မှ အမည်များ အသုံးပြုမည်"</string>
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"ကိုယ်ရေးကိုယ်တာ အကြံပြုချက်များ"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"မြှင့်တင်ပါ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <!-- no translation found for use_double_space_period (8781529969425082860) -->
-    <skip />
-    <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
-    <skip />
-    <!-- no translation found for auto_cap (1719746674854628252) -->
-    <skip />
-    <!-- no translation found for auto_cap_summary (7934452761022946874) -->
-    <skip />
-    <!-- no translation found for edit_personal_dictionary (3996910038952940420) -->
-    <skip />
-    <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
-    <skip />
-    <!-- no translation found for main_dictionary (4798763781818361168) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
-    <skip />
-    <!-- no translation found for auto_correction (7630720885194996950) -->
-    <skip />
-    <!-- no translation found for auto_correction_summary (5625751551134658006) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) -->
-    <skip />
-    <!-- no translation found for bigram_prediction (1084449187723948550) -->
-    <skip />
-    <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
-    <skip />
-    <!-- no translation found for gesture_input (826951152254563827) -->
-    <skip />
-    <!-- no translation found for gesture_input_summary (9180350639305731231) -->
-    <skip />
-    <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware (2078291600664682496) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware_summary (4371385818348528538) -->
-    <skip />
-    <!-- no translation found for voice_input (3583258583521397548) -->
-    <skip />
-    <!-- no translation found for voice_input_disabled_summary (8141750303464726129) -->
-    <skip />
-    <!-- no translation found for configure_input_method (373356270290742459) -->
-    <skip />
-    <!-- no translation found for language_selection_title (1651299598555326750) -->
-    <skip />
-    <!-- no translation found for send_feedback (1780431884109392046) -->
-    <skip />
-    <!-- no translation found for select_language (3693815588777926848) -->
-    <skip />
-    <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
-    <skip />
-    <!-- no translation found for has_dictionary (6071847973466625007) -->
-    <skip />
-    <!-- no translation found for keyboard_layout (8451164783510487501) -->
-    <skip />
-    <!-- no translation found for subtype_en_GB (88170601942311355) -->
-    <skip />
-    <!-- no translation found for subtype_en_US (6160452336634534239) -->
-    <skip />
-    <!-- no translation found for subtype_es_US (5583145191430180200) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_GB (1931018968641592304) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_US (8809311287529805422) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_es_US (510930471167541338) -->
-    <skip />
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <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 />
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
-    <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
-    <skip />
-    <!-- no translation found for add_style (6163126614514489951) -->
-    <skip />
-    <!-- no translation found for add (8299699805688017798) -->
-    <skip />
-    <!-- no translation found for remove (4486081658752944606) -->
-    <skip />
-    <!-- no translation found for save (7646738597196767214) -->
-    <skip />
-    <!-- no translation found for subtype_locale (8576443440738143764) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
-    <skip />
-    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
-    <skip />
-    <!-- no translation found for enable (5031294444630523247) -->
-    <skip />
-    <!-- no translation found for not_now (6172462888202790482) -->
-    <skip />
-    <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
-    <skip />
-    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
-    <skip />
-    <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_confirm_install_message (4782116251651288054) -->
-    <skip />
-    <!-- no translation found for error (8940763624668513648) -->
-    <skip />
-    <!-- no translation found for button_default (3988017840431881491) -->
-    <skip />
-    <!-- no translation found for setup_welcome_title (6112821709832031715) -->
-    <skip />
-    <!-- no translation found for setup_welcome_additional_description (8150252008545768953) -->
-    <skip />
-    <!-- no translation found for setup_start_action (8936036460897347708) -->
-    <skip />
-    <!-- no translation found for setup_next_action (371821437915144603) -->
-    <skip />
-    <!-- no translation found for setup_steps_title (6400373034871816182) -->
-    <skip />
-    <!-- no translation found for setup_step1_title (3147967630253462315) -->
-    <skip />
-    <!-- no translation found for setup_step1_instruction (2578631936624637241) -->
-    <skip />
-    <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
-    <skip />
-    <!-- no translation found for setup_step1_action (4366513534999901728) -->
-    <skip />
-    <!-- no translation found for setup_step2_title (6860725447906690594) -->
-    <skip />
-    <!-- no translation found for setup_step2_instruction (9141481964870023336) -->
-    <skip />
-    <!-- no translation found for setup_step2_action (1660330307159824337) -->
-    <skip />
-    <!-- no translation found for setup_step3_title (3154757183631490281) -->
-    <skip />
-    <!-- no translation found for setup_step3_instruction (8025981829605426000) -->
-    <skip />
-    <!-- no translation found for setup_step3_action (600879797256942259) -->
-    <skip />
-    <!-- no translation found for setup_finish_action (276559243409465389) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon (5008028590593710830) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) -->
-    <skip />
-    <!-- no translation found for app_name (6320102637491234792) -->
-    <skip />
-    <!-- no translation found for dictionary_provider_name (3027315045397363079) -->
-    <skip />
-    <!-- no translation found for dictionary_service_name (6237472350693511448) -->
-    <skip />
-    <!-- no translation found for download_description (6014835283119198591) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_title (8091417676045693313) -->
-    <skip />
-    <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_summary (5305694987799824349) -->
-    <skip />
-    <!-- no translation found for user_dictionaries (3582332055892252845) -->
-    <skip />
-    <!-- no translation found for default_user_dict_pref_name (1625055720489280530) -->
-    <skip />
-    <!-- no translation found for dictionary_available (4728975345815214218) -->
-    <skip />
-    <!-- no translation found for dictionary_downloading (2982650524622620983) -->
-    <skip />
-    <!-- no translation found for dictionary_installed (8081558343559342962) -->
-    <skip />
-    <!-- no translation found for dictionary_disabled (8950383219564621762) -->
-    <skip />
-    <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) -->
-    <skip />
-    <!-- no translation found for no_dictionaries_available (8039920716566132611) -->
-    <skip />
-    <!-- no translation found for check_for_updates_now (8087688440916388581) -->
-    <skip />
-    <!-- no translation found for last_update (730467549913588780) -->
-    <skip />
-    <!-- no translation found for message_updating (4457761393932375219) -->
-    <skip />
-    <!-- no translation found for message_loading (5638680861387748936) -->
-    <skip />
-    <!-- no translation found for main_dict_description (3072821352793492143) -->
-    <skip />
-    <!-- no translation found for cancel (6830980399865683324) -->
-    <skip />
-    <!-- no translation found for go_to_settings (3876892339342569259) -->
-    <skip />
-    <!-- no translation found for install_dict (180852772562189365) -->
-    <skip />
-    <!-- no translation found for cancel_download_dict (7843340278507019303) -->
-    <skip />
-    <!-- no translation found for delete_dict (756853268088330054) -->
-    <skip />
-    <!-- no translation found for should_download_over_metered_prompt (1583881200688185508) -->
-    <skip />
-    <!-- no translation found for download_over_metered (1643065851159409546) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (2176209579313941583) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_title (4583842811218581658) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_description (1075194169443163487) -->
-    <skip />
-    <!-- no translation found for toast_downloading_suggestions (6128155879830851739) -->
-    <skip />
-    <!-- no translation found for version_text (2715354215568469385) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
-    <skip />
-    <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
-    <skip />
+    <string name="use_double_space_period" msgid="8781529969425082860">"နှစ်နေရာခြား အဆုံးသတ်"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"အချိန်ကာလ"</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_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>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"ထိထိရောက်ရောက်"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"အလွန်ထိရောက်"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"နောက်စကားလုံး အကြံပြုချက်များ"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"အကြံပြုချက်များပြုလုပ်ရာ၌ ပြီးခဲ့သည့် စကားလုံးကို အသုံးပြုရန်"</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="gesture_space_aware" msgid="2078291600664682496">"စကားစု အမူယာ"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"နေရာခြားသည့်ကီးကိုနှိပ်ခြင်းဖြင့် အမူအယာပြုလုပ်စဉ်တွင် နေရာခြား ထည့်သွင်းရန်"</string>
+    <string name="voice_input" msgid="3583258583521397548">"အသံထည့်သွင်းရန် ခလုတ်"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"မည်သည့် Check Language &amp; input settings."</string>
+    <string name="configure_input_method" msgid="373356270290742459">"ထည့်သွင်းရန် နည်းလမ်းကို ပြုပြင်မည်"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"ဘာသာစကားများ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"အကူအညီ &amp; တုံ့ပြန်ချက်"</string>
+    <string name="select_language" msgid="5709487854987078367">"ဘာသာစကားများ"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"သိမ်းရန် နောက်တစ်ကြိမ်နှိပ်ပါ"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"သိမ်းရန် ဤနေရာကို ထိပါ"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"အဘိဓါန်ရနိုင်"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"ကီးဘုတ်အရောင်"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"အကောင့်များကို ပြောင်းရန်"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"အကောင့်များ မရွေးရသေးပါ"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>အား လတ်တလော သုံးန​ေ၏"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"အိုကေ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"ထားတော့"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ထွက်ရန်"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"သုံးမည့်အကောင့်ကို ရွေးရန်"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"အင်္ဂလိပ်(ယူကေ)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"အင်္ဂလိပ် (ယူအက်စ်)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"စပိန် (ယူအက်စ်)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ဟင်ဂလိပ်"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"ဆားဘီယား (လက်တင်)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"အင်္ဂလိပ် (ယူကေ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"အင်္ဂလိပ် (ယူအက်စ်) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"စပိန် (ယူအက်စ်) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ဟင်ဂလိပ် (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"ဆားဘီယား (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ရိုးရာ)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ကျစ်လစ်သော)"</string>
+    <string name="subtype_no_language" msgid="7137390094240139495">"ဘာသာစကားမရှိ (ဗျည်းအက္ခရာ)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ဗျည်းအက္ခရာ (ကွာတီ)"</string>
+    <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ဗျည်းအက္ခရာ (ကွာတီ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8144348527575640087">"ဗျည်း (အဇာတည်)"</string>
+    <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"ဗျည်းအက္ခရာ (ဒီဘိုရခ်)"</string>
+    <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ဗျည်းအက္ခရာ (ကိုလ်မာ့ခ်)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ဗျည်း (PC)"</string>
+    <string name="subtype_emoji" msgid="7483586578074549196">"အီမိုဂျီ"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"ကီးဘုတ်အဆင်အပြင်"</string>
+    <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_keypress_vibration_duration_settings" msgid="7918341459947439226">"ခလုတ်နှိပ်တုန်ခါမှု ကြာမြင့်ချိန်"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"ခလုတ်နှိပ်သည့် အသံအတိုးကျယ်"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"ကီးကြာမြင့်စွာ ဖိနှိပ်မှုနှုန်း"</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">"သင့်ဘာသာစကား&amp; စာရိုက်ထည့်မှု ဆက်တင်များတွင် \"<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> သည် သင့်ဘာသာစကား &amp; စာရိုက်ထည့်မှု ဆက်တင်များတွင် ဖွင့်ပြီးသောကြောင့်၊ ဤအဆင့်ပြီးပါပြီ။ နောက်တစ်ခုသို့!"</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">"<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="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="5638680861387748936">"တင်နေ…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"အဓိက အဘိဓါန်"</string>
+    <string name="cancel" msgid="6830980399865683324">"ထားတော့"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"ဆက်တင်များ"</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="1583881200688185508">"သင့်ဖုန်းရှိ ရွေးချယ်ထားသည့် ဘာသာအတွက် အဘိဓါန်ရှိပါသည်။ &lt;br/&gt; အဘိဓါန်အား &lt;b&gt;ဒေါင်းလုပ်လုပ်ကာ&lt;/b&gt; the <xliff:g id="LANGUAGE_NAME">%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;ဘာသာ &amp; စာရိုက်ထည့်မှု&lt;/b&gt; သို့သွားကာ အဘိဓါန်များကို ဒေါင်းလုပ်လုပ်နိုင် ဖယ်ရှားနိုင်ပါသည်။"</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"ယခုဒေါင်းလုပ်လုပ်မည် (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi အသုံးပြု၍ ဒေါင်းလုပ်လုပ်ရန်"</string>
+    <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> အတွက် အဘိဓါန် ရနိုင်ပါသည်"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"ပြန်လည်ဆန်းစစ်ကာ ဒေါင်းလုပ်လုပ်ရန် နှိပ်ပါ"</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"ဒေါင်းလုပ်လုပ်နေသည်: <xliff:g id="LANGUAGE_NAME">%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">"အိုကေ"</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">"စိတ်ကြိုက်ရွေးစရာအတိုကောက်"</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/values-nb/strings-emoji-descriptions.xml b/java/res/values-nb/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..6811188
--- /dev/null
+++ b/java/res/values-nb/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Opphavsrett-symbol"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Varemerkesymbol"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dobbelt utropstegn"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Utrops- og spørsmålstegn"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Varemerkesymbol"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informasjonskilde"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Venstre- og høyrepil"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Opp- og nedpil"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Nordvest-pil"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Nordøst-pil"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Sørøst-pil"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Sørvest-pil"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Venstrepil med sving"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Høyrepil med sving"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Klokke"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Timeglass"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Spol fremover"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Spol tilbake"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Dobbeltpil opp"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Dobbeltpil ned"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Alarmklokke"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Timeglass med sand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"M i sirkel"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Liten firkant med fargefyll"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Liten firkant, omriss"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Fargefylt høyrepil"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Fargefylt venstrepil"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Middels stor firkant, omriss"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Middels stor firkant, fargefylt"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Middels liten firkant, omriss"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Middels liten firkant, fargefylt"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Fargefylt sol med stjerner"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Sky"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Avmerkingshake"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraply med regndråper"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Varm drikke"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Pekefinger opp"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Smilefjes"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Væren"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Tyren"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Tvillingene"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Krepsen"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Løven"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Jomfruen"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Vekten"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpionen"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Skytten"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Steinbukken"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vannmannen"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Fiskene"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Spar"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Kløver"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Hjerter"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Ruter"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Varme kilder"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Resirkulering"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Rullestol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anker"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Advarsel"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Høyspenning"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Middels stor sirkel, omriss"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Middels stor sirkel, fargefylt"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Fotball"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snømann uten snø"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol bak sky"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Slangebæreren"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Ingen adgang"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kirke"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontene"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Golfhull"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Seilbåt"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Telt"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bensinpumpe"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Saks"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Hake"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Fly"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Konvolutt"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Knyttet neve"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Hevet hånd"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Seiershånd"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Blyant"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Pennesplitt"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Hake"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Gangetegn"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Stjerner"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Stjerne med åtte spisser"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Åttekantet stjerne"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snøflak"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Stjernesymbol"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kryss"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Kryss i firkant"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Spørsmålstegn, fargefylt"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Spørsmålstegn, omriss"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Utropstegn, omriss"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Utropstegn, fargefylt"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Fargefylt hjerte"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Plusstegn, fargefylt"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Minustegn, fargefylt"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Deletegn, fargefylt"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Pil til høyre"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Løkke"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dobbeltløkke"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pil til høyre og opp"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pil til høyre og ned"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Venstrepil. fargefylt"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Opp-pil, fargefylt"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Ned-pil, fargefylt"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Stor fargefylt firkant"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Stor firkant"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Middels stor stjerne"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Stor, tykk sirkel"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Bølgestrek"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Japansk sangtegn"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideogram i sirkel, «gratulerer»"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideogram i sirkel «hemmelig»"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjongbrikke, rød drage"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Spillkort, svart joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blodtype A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blodtype B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blodtype O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkeringsplass"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blodtype AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"fjern-symbol"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Kult-symbol"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Gratis-symbol"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID-symbol"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"nytt-symbol"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Ikke bra-symbol"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK-symbol"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS-symbol"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Opp-symbol med utropstegn"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"versus-symbol"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Japansk ord, «her»"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Japansk ord, «tjeneste»"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogram i firkant, «gratis»"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogram i firkant, «reservert sitteplass»"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogram i firkant, «forbud»"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogram i firkant, «ledig»"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogram i firkant, «aksept»"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogram i firkant, «fullt»"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogram i firkant, «betalt»"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogram i firkant, «månedlig»"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogram i firkant, «søknad»"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogram i firkant, «rabatt»"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogram i firkant, «åpent»"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideogram i sirkel, «fordel»"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideogram i sirkel, «aksept»"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Syklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Tåkete"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Lukket paraply"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Natt med stjerner"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Soloppgang over fjell"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Soloppgang"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Bylandskap i skumring"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Solnedgang over byhorisont"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Regnbue"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Bro om natten"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vannbølge"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Melkeveien"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Jordklode, Europa og Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Jordklode, Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Jordklode, Asia, Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Jordklode med meridianer"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Nymåne"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Tiltakende måne"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Tiltakende kvartmåne"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Tiltakende måne"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Fullmåne"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Avtakende måne"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Avtakende kvartmåne"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Avtakende måne"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Halvmåne"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nymåne med fjes"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Tiltakende kvartmåne med fjes"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Avtakende kvartmåne med fjes"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Fullmåne med fjes"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol med fjes"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Skinnende stjerne"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Stjerneskudd"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanje"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Spire"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Grantre"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Løvtre med fallende blader"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palme"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Hvitveis"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rose"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Solsikke"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blomst"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Maiskolbe"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Risplante"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Urte"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Firkløver"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Lønneblad"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Fallende blad"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blader i vinden"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Sopp"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Druer"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Vannmelon"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Sitron"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rødt eple"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Grønt eple"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pære"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Fersken"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kirsebær"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jordbær"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzastykke"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Kjøttbein"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Kyllinglår"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Riskjeks"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Risball"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kokt ris"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry og ris"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Dampende bolle"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Brød"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Pommes frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Ovnsstekt søtpotet"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Mochi"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Sjømat"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Stekt reke"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fiskekake med sirkelmønster"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Soft-is"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Shave-ice"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Iskrem"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Kjeks"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Sjokoladeplate"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Godteri"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Pudding"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honningkrukke"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Kakestykke"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Lunsjboks"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Matgryte"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Matlaging"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Kniv og gaffel"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tekopp uten håndtak"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake-flaske og -kopp"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vinglass"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktailglass"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropisk drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Ølglass"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Skål med ølglass"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Tåteflaske"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Bånd"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Innpakket gave"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Bursdagskake"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Halloween-lykt"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Juletre"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Julenissen"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fyrverkeri"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Stjerneskudd"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballong"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Smellbongbong"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettikule"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tre med papirremser"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Kryssede flagg"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Furudekorasjon"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanske dukker"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Fiskedekorasjon"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vindspill"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Månesermoni"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Skolesekk"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Studentlue"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karusellhest"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Pariserhjul"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Berg- og dalbane"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Fiskestang og fisk"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmkamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Hodetelefoner"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palett"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Flosshatt"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Sirkustelt"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Billett"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Filmklapper"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Scenekunst"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videospill"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Blinkskudd"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Spillemaskin"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Terning"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Spillkort med blomster"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musikknote"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Musikknoter"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Keyboard"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Fiolin"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"G-nøkkel"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Løpetopp"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisracket og -ball"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski og skistøvler"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball og kurv"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bilraceflagg"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Løper"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofé"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Hesteveddeløp"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikansk fotball"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Svømmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Husbygging"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Hus med hage"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kontorbygning"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japansk postkontor"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europeisk postkontor"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Sykehus"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Minibank"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotell"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Kjærlighetshotell"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Dagligvarehandel"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Skole"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Storsenter"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrikk"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Rød lykt"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japansk slott"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europeisk slott"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rotte"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mus"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Okse"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vannbøffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Ku"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Hare"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Katt"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drage"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodille"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Hval"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Snegle"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Slange"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Hest"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Bukk"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Geit"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Sau"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Ape"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Hane"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kylling"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hund"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Gris"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Villsvin"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Blekksprut"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiralskjell"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insekt"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Maur"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Honningbie"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Bille"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fisk"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropisk fisk"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Kulefisk"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Skilpadde"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Nyklekket kylling"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kylling"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kylling forfra"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Fugl"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koalabjørn"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Puddel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedar"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kamel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mousefjes"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Kufjes"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigerfjes"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Harefjes"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kattefjes"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Dragehode"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Sprutende hval"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Hestefjes"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Apefjes"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hundefjes"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Grisefjes"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Froskefjes"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamsterfjes"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Ulvefjes"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Bjørnefjes"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandafjes"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Grisenese"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Poteavtrykk"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Øyne"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Øre"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nese"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Munn"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tunge"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Finger som peker opp"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Finger som peker ned"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Finger som peker til venstre"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Finger som peker til høyre"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Knyttet neve"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Vinkende hånd"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK-håndtegn"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Tommel opp"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Tommel ned"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Klappende hender"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Åpne hender"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Krone"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Damehatt"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Briller"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Slips"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-skjorte"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Olabukser"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Kjole"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Dameklær"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Veske"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Håndveske"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Portemoné"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Herresko"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Treningssko"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Høyhælt sko"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Damesandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Damestøvletter"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Fotavtrykk"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Siluett av byste"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Siluett av byster"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Gutt"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Jente"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mann"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Kvinne"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familie"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Mann og kvinne som holder hender"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"To menn som holder hender"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"To kvinner som holder hender"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Politibetjent"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Dame med kaninører"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Brud med slør"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Blond person"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Mann med lue"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Mann med turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Eldre mann"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Eldre kvinne"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Anleggsarbeider"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinsesse"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japansk monster"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japansk troll"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spøkelse"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Babyengel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Romvesen"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Utenomjordisk monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Liten djevel"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Hodeskalle"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Resepsjonist"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Vaktmann"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danser"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Leppestift"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Neglelakk"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Ansiktsmassasje"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Hårklipp"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Frisør"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Sprøyte"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pille"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kyssemerke"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Kjærlighetsbrev"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Edelsten"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kyss"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bukett"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Par med hjerte"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Bryllup"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Bankende hjerrte"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Kunst hjerte"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"To hjerter"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Skinnende hjerte"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Voksende hjerte"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hjerte med pil"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blått hjerte"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Grønt hjerte"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Gult hjerte"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lilla hjerte"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hjerte med bånd"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Snurrende hjerter"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Hjertedekorasjon"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamantform med prikk"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektrisk lyspære"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Sint"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bombe"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Sover"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Krasj"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Svettedråper-symbol"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Dråpe"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Forsvinne"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Hundebæsj"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Flekset biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Svimmel"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Snakkeboble"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Tankeboble"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Hvit blomst"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Hundre poeng"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Pengesekk"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valutakonvertering"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dollartegn"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredittkort"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Seddel med yentegn"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Seddel med dollartegn"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Seddel med eurotegn"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Seddel med pundtegn"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Penger med vinger"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Stigende graf"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sitteplass"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Datamaskin"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Koffert"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskett"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Blu-ray"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Filmappe"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Åpne filmappen"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Opprullet ark"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Ark som vender opp"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Riv-av-kalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kortindeks"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Stigende graf"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Synkende graf"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Stolpediagram"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Utklippstavle"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Stift"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Knappenål"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Binders"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Linjal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trekantlinjal"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Bokmerkerfane"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Spiralblokk"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notatbok"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Notatbok med dekorativt omslag"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Lukket bok"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Åpen bok"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Grønn bok"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blå bok"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oransje bok"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Bøker"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Navneskilt"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Rull"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Notatbok"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefon"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Personsøker"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faks"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellittantenne"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Megafon"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ropert"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Utboks"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Innboks"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakke"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-post-symbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Innkommende e-post"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Utgående e-post"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Lukket postkasse med senket flagg"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Lukket postkasse med heist flagg"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Åpen postkasse med heist flagg"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Åpen postkasse med senket flagg"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postboks"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posthorn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Avis"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiltelefon med pil"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibreringsmodus"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiltelefon av"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobiltelefon forbudt"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Singalstyrke"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"TV"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videoopptak"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Kryssede piler"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Piler med klokken, åpne sirkler"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Piler med klokken, åpne sirkler med overlegg"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Piler med klokken, åpne sirkler"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Piler mot klokken, åpne sirkler"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Lav lysstyrke"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Høy lysstyrke"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Stille"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Høyttaler"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Høyttaler med lavt volum"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Høyttaler med høyt volum"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batteri"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektrisk støpsel"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Forstørrelsesglass mot venstre"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Forstørrelsesglass mot høyre"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lås med blekkpenn"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Lukket lås med nøkkel"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Nøkkel"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lås"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Åpen lås"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Klokke"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Stille"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bokmerke"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Link-symbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Alternativknapp"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Tilbake, venstre"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Avslutt, venstre"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"«På» med utropstegn og pil"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"«Snart» med høyrepil"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"topp med pil"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Aldersgrense 18 år"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"10-tast"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Store bokstaver"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Små bokstaver"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Tall"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Inndatasymbol for symboler"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Latinsk alfabet"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Brann"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Lommelykt"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Skiftenøkkel"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Mutter og skrue"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Kokkekniv"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Krystallkule"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sekskantet stjerne med prikk i midten"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japansk symbol for nybegynner"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Tridentsymbol"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Firkantknapp med fargefyll"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Firkantknapp uten fargefyll"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Stor rød sirkel"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Stor blå sirkel"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Stort oransje rutersymbol"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Stort blått rutersymbol"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Lite oransje rutersymbol"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Lite blått rutersymbol"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Rødt oppovervendt trekant"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Rød nedovervendt trekant"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Liten rød oppovervendt trekant"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Liten rød nedovervendt trekant"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Klokka ett"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Klokka to"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Klokka tre"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Klokka fire"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Klokka fem"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Klokka seks"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Klokka sju"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Klokka åtte"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Klokka ni"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Klokka ti"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Klokka elleve"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Klokka tolv"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Klokka halv to"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Klokka halv tre"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Klokka halv fire"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Klokka halv fem"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Klokka halv seks"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Klokka halv sju"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Klokka halv åtte"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Klokka halv ni"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Klokka halv ti"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Klokka halv elleve"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Klokka halv tolv"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Klokka halv ett"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji-fjellet"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo-tårnet"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Frihetsgudinnen"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Kart over japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai-statue"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Glisefjes"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Smileansikt med smilende øyne"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Fjes med gledestårer"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Smilende fjes med tenner"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Smil med tennene"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Smilefjes med kaldsvette"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Smilefjes med lukkede øyne"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Smilefjes med glorie"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Smilefjes med horn"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Blinkende ansikt"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Smilende fjes og øyne"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Nam-nam-fjes"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lettet fjes"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Smilefjes med hjerteøyne"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Smilefjes med solbriller"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Lurt smil"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Nøytralt ansikt"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Uttrykksløst ansikt"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Misfornøyd ansikt"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Kaldsvette"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Bekymret"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Forvirret"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Forbannet"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kyssende fjes"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Slengkyss"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kyssende fjes med smil"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kyss med lukkede øyne"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Fjes som rekker tunge"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Rekke tunge med blunk"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Tungen ut med øynene lukket"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Skuffet fjes"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Bekymret fjes"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Sint ansikt"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Rødt ansikt"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Gråtende ansikt"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Sta"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Triumferende"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Skuffet, men lettet"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Sjokkert med åpen munn"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Forskrekket ansikt"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Redd ansikt"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Slitent ansikt"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Trøtt ansikt"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Slitent ansikt"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimase"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Hylgråting"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Åpen munn"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Overrasket"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Kaldsvette og åpen munn"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Skrikende ansikt"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Sjokkert ansikt"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Rødmer"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Sovende fjes"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Svimmelt"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Fjes uten munn"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Fjes med bakteriemaske"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Smilende katt"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Kattefjes med gledestårer"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Smilende katt med åpen munn"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Smilende kattefjes med hjerteøyne"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Kattefjes med lurt smil"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kyssende katt med lukkede øyne"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Katt med trutmunn"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Gråtende katt"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Sjokkert kattefjes"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Forbudt"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OK-bevegelse"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Person som bukker dypt"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Ser ingenting ondt-ape"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Hører ingenting ondt-ape"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Sier ingenting ondt-ape"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Rekker opp hånden"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person som feirer med hendene i været"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Person som rynker brynene"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Person med trutmunn"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person med foldede hender"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rakett"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Damplokmotiv"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Tog"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Lyntog"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Lyntog med flysnute"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tog"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Undergrunn"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tog"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stasjon"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Trikk"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Trikkevogn"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Buss"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Møtende buss"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Buss"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bussholdeplass"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibuss"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulanse"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Brannbil"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Politibil"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Møtende politibil"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Møtende taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Bil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Møtende bil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Fritidskjøretøy"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Varebil"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Vogntog"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Fjellbane"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Svevebane"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Kabelbane"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Taubane"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Skip"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Robåt"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedbåt"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horisontalt trafikklys"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikale trafikklys"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Byggeplass-skilt"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Politilys"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Posisjonsflagg"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Dør"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Ingen adgang-skilt"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Røykesymbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Røyking ikke tillatt-symbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Avfall-skilt"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Ikke kast søppel-skilt"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Drikkbart vann"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ikke drikkbart vann"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Sykkel"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"No bicycles"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Syklist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Fjellsyklist"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Fotgjenger"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Fotgjengere ikke tillatt"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Kryssende barn"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Menn"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Kvinner"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toalett"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Baby"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toalett"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Do"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dusj"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Badekar"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badekar"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Passkontroll"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Toll"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Baggasjebånd"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Glemt bagasje"</string>
+</resources>
diff --git a/java/res/values-nb/strings-talkback-descriptions.xml b/java/res/values-nb/strings-talkback-descriptions.xml
index cdb6858..d282006 100644
--- a/java/res/values-nb/strings-talkback-descriptions.xml
+++ b/java/res/values-nb/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Ingen tekst er skrevet inn"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> retter <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> til <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> utfører automatisk retting"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ingen forslag"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Ukjent tegn"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Flere symboler"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Stor I med prikk over"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ukjent symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Ukjent emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Uinteressert fjes"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Flaut fjes"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Fjes med solbriller"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Overrasket fjes"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kyssende fjes"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Fjes med rynket panne"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternative tegn er tilgjengelige"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternative tegn fjernes"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternative forslag er tilgjengelige"</string>
diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml
index 29fd367..db04ee5 100644
--- a/java/res/values-nb/strings.xml
+++ b/java/res/values-nb/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrer ved tastetrykk"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Lyd ved tastetrykk"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Hurtigvindu ved tastetrykk"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Innstillinger"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Kontoer og personvern"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Utseende og utforming"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Ordføring"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Tekstkorrigering"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avansert"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktivér delt tastatur"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Syknronisering av Google-tastatur"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synkronisering er slått på"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synkroniser den personlige ordboken din på alle enheter"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synkroniser nå"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Slett nettskydata"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Sletter de synkroniserte dataene dine fra Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"De synkroniserte dataene blir slettet fra skyen. Er du sikker?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Slett"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Avbryt"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Den personlige ordlisten din blir synkronisert og sikkerhetskopiert til Google-tjenere. For å bidra til å forbedre produktene våre, kan det hende vi samler inn informasjon om ordfrekvens. Innsamling og bruk av all informasjon skjer i henhold til "<a href="https://www.google.com/policies/privacy">"Googles personvernregler"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Legg en Google-konto til enheten for å aktivere denne funksjonen"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Bytt inndatametode"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten for språkbytte dekker også andre inndatametoder"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Nøkkel for språkskifte"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Vis når flere inndataspråk er aktivert"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Vis lysbildeindikator"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Bruk en visuell indikator når du skyver fra Shift- eller symboltaster"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tregt tastevindu"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"U/ forsinkelse"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hovedordliste"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Vis rettingsforslag"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Vis ordforslag under skriving"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vis alltid"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Vis i stående modus"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Skjul alltid"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokkér støtende ord"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ikke foreslå potensielt støtende ord"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autokorrektur"</string>
@@ -85,39 +87,41 @@
     <string name="voice_input" msgid="3583258583521397548">"Tast for taleinndata"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ingen taleinndatametoder er aktivert. Sjekk Språk og inndata-innstillingene."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Send tilbakemelding"</string>
-    <string name="select_language" msgid="3693815588777926848">"Inndataspråk"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Språk"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hjelp og tilbakemelding"</string>
+    <string name="select_language" msgid="5709487854987078367">"Språk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Trykk på nytt for å lagre"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Trykk her for å lagre"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tastaturtema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Bytt konto"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Ingen kontoer er valgt"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Du bruker for øyeblikket <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Avbryt"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Logg av"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Velg kontoen du vil bruke"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelsk (Storbritannia)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelsk (USA)"</string>
-    <string name="subtype_es_US" msgid="5583145191430180200">"Spansk (USA)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"spansk (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbisk (latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelsk (Storbritannia) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelsk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
-    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spansk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"spansk (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbisk (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradisjonelt)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Ingen språk (alfabet)"</string>
-    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
     <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Alfabet (AZERTY)"</string>
     <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Alfabet (Dvorak)"</string>
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tastaturtema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Egendefinerte inndata"</string>
     <string name="add_style" msgid="6163126614514489951">"Legg til stil"</string>
     <string name="add" msgid="8299699805688017798">"Legg til"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktiver"</string>
     <string name="not_now" msgid="6172462888202790482">"Ikke nå"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Inndatastilen finnes allerede: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinkelse lange tastetrykk"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrasjonstid ved tastetrykk"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Lydstyrke ved tastetrykk"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Bruk en ekstern ordlistefil"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Det ligger ingen ordboksfiler i Nedlastinger-mappen"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Velg ordboksfilen du vil installere"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vil du virkelig installere denne filen for <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Det oppsto en feil"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Forsinkelse lange tastetrykk"</string>
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Velkommen til <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"med Ordføring"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nå kan du skrive inn alle favorittappene dine med <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurer flere språk"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Ferdig"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Vis app-ikonet"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Vis app-ikonet i appvelgeren"</string>
     <string name="app_name" msgid="6320102637491234792">"Ordlisteleverandør"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Ordlisteleverandør"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Ordlistetjeneste"</string>
diff --git a/java/res/values-ne-rNP/strings-emoji-descriptions.xml b/java/res/values-ne-rNP/strings-emoji-descriptions.xml
index a3419b8..39e5bc0 100644
--- a/java/res/values-ne-rNP/strings-emoji-descriptions.xml
+++ b/java/res/values-ne-rNP/strings-emoji-descriptions.xml
@@ -129,8 +129,8 @@
     <string name="spoken_emoji_27A1" msgid="3513434778263100580">"कालो दाँयातीर तीर"</string>
     <string name="spoken_emoji_27B0" msgid="203395646864662198">"घुम्रिएको फेरो"</string>
     <string name="spoken_emoji_27BF" msgid="4940514642375640510">"दोहोरो घुम्रिएको फेरो"</string>
-    <string name="spoken_emoji_2934" msgid="9062130477982973457">"दाँयातीर इशारा तीर त्यसपछि माथिको घुमाँइ"</string>
-    <string name="spoken_emoji_2935" msgid="6198710960720232074">"दाँयातीर इशारा तीर त्यसपछि तलको घुमाँइ"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"दाँया तिर  देखादने तीर त्यसपछि माथिको घुमाई"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"दाँया तिर देखाउने तीर त्यसपछि तलको घुमाँइ"</string>
     <string name="spoken_emoji_2B05" msgid="4813405635410707690">"कालोतीर बायाँतर्फ"</string>
     <string name="spoken_emoji_2B06" msgid="1223172079106250748">"कालो तीर माथि तर्फ"</string>
     <string name="spoken_emoji_2B07" msgid="1599124424746596150">"कालो तीर तल तर्फ"</string>
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"कुकीज"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"चकलेट बार"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"क्यान्डी"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"लालीपप"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"कस्तार्ड"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"महदानी"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"सर्टकेक"</string>
@@ -669,10 +669,10 @@
     <string name="spoken_emoji_1F537" msgid="3158915214347274626">"ठूलो नीलो हीरा"</string>
     <string name="spoken_emoji_1F538" msgid="4300084249474451991">"लघु सुन्तला हीरा"</string>
     <string name="spoken_emoji_1F539" msgid="6535159756325742275">"लघु नीलो हीरा"</string>
-    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"माथी-इशारा रातो त्रिकोण"</string>
-    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"तल-इशारा रातो त्रिकोण"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"माथि-देखाउने रातो त्रिकोण"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"तल-देखाउने रातो त्रिकोण"</string>
     <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"माथी इशारा सानो रातो त्रिकोण"</string>
-    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"तल-इशारा सानो रातो त्रिकोण"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"तल-देखाउने सानो रातो त्रिकोण"</string>
     <string name="spoken_emoji_1F550" msgid="7761392621689986218">"घडी अनुहार एक बजे"</string>
     <string name="spoken_emoji_1F551" msgid="2699448504113431716">"घडी अनुहार दुई बजे"</string>
     <string name="spoken_emoji_1F552" msgid="5872107867411853750">"घडी अनुहार तीन बजे"</string>
diff --git a/java/res/values-ne-rNP/strings-talkback-descriptions.xml b/java/res/values-ne-rNP/strings-talkback-descriptions.xml
index 2bbd178..4177f71 100644
--- a/java/res/values-ne-rNP/strings-talkback-descriptions.xml
+++ b/java/res/values-ne-rNP/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"कुनै पाठ प्रविष्टि गरिएको छैन"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ले <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> लाई <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> मा सच्याउँछ"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ले स्वतः सच्याउने गर्छ"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"कुनै सुझाव छैन"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"अज्ञात वर्ण"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"सिफ्ट"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"थप प्रतीकहरु"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, dot above"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"अज्ञात प्रतीक"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"अज्ञात इमोजी"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"थकित अनुहार"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"लज्जित अनुहार"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"घाम चस्मा लगाएको अनुहार"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"छक्क परेको अनुहार"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"चुम्बन अनुहार"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"पालिस लगाएको अनुहार"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"वैकल्पिक वर्णहरू उपलब्ध छन्"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"वैकल्पिक वर्णहरू खारेज गरियो"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"वैकल्पिक सुझावहरू उपलब्ध छन्"</string>
diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml
index 3220169..bc96c49 100644
--- a/java/res/values-ne-rNP/strings.xml
+++ b/java/res/values-ne-rNP/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"निवेश प्राथमिकता"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"उपस्थिति"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"बहुभाषी विकल्प"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"इशारा टाइप प्राथमिकता"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"प्राथमिकताहरू"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"खाताहरू तथा गोपनीयता"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"आवरण तथा लेआउटहरू"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"इशारा टाइपिङ"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"पाठ सुधार"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"उन्नत"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"विषयवस्तु"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"विभाजित कुञ्जीपाटी सक्षम गर्नुहोस्"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google किबोर्ड सिंक गर्नुहोस्"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"सिंक सक्रिय गरिएको छ"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"तपाईंको व्यक्तिगत शब्दकोषलाई यन्त्रहरूमा सिंक गर्नुहोस्"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"अहिले सिंक गर्नुहोस्"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"क्लाउड डेटा मेटाउनुहोस्"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google बाट तपाईँको सिङ्क गरिएको डाटा मेटाउँछ"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"तपाईंको सिंक गरिएको डेटालाई क्लाउडबाट मेटाइनेछ। के तपाईं निश्चित हुनुहुन्छ?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"मेटाउनुहोस्"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"रद्द गर्नुहोस्"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"तपाईँको व्यक्तिगत शब्दकोश सिंक गरेर Google सर्भरहरूमा जगेडा राखिने छ। शब्द आवृत्तिको तथ्याङ्क जानकारी हाम्रो उत्पादनहरू सुधार गर्न मद्दतका लागि संकलन हुन सक्छ। संग्रह र सबै जानकारीको प्रयोग  "<a href="https://www.google.com/policies/privacy">" Google को गोपनीयता नीति "</a>" अनुरूप हुने छ।"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"कृपया यो सुविधा सक्षम गर्न यो यन्त्रमा एउटा Google खाता थप्नुहोस्"</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">"भाषा स्विच किले अन्य इनपुट विधि पनि समेट्छ"</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">"स्लाइड सूचक देखाउनुहोस्"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"सिफ्ट वा प्रतिक कुञ्जीमा स्लाइड गर्ने बेला दृश्य सङ्केत देखाउनुहोस्"</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>
@@ -49,16 +60,13 @@
     <string name="enable_metrics_logging" msgid="5506372337118822837">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>सुधार गर्नुहोस्"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"डबल-स्पेस पूर्णविराम"</string>
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"स्पेसबारमा डबल ट्याप गर्नाले पूर्णविरामपछि स्पेस राख्दछ"</string>
-    <string name="auto_cap" msgid="1719746674854628252">"स्वतः पूँजिकरण"</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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"आवाज इनपुट कुञ्जी"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"कुनै आवाज इनपुट विधिहरू सक्षम गरिएका छैनन्। भाषा र इनपुट सेटिङहरूको जाँच गर्नुहोस्।"</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="language_selection_title" msgid="3666971864764478269">"भाषाहरू"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"मद्दत र प्रतिक्रिया"</string>
+    <string name="select_language" msgid="5709487854987078367">"भाषाहरू"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"बचत गर्न पुनः छुनुहोस्"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"सुरक्षित गर्न यहाँ छुनुहोस्"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"उपलब्ध शब्दकोश"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"किबोर्ड थिम"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"खाताहरू स्विच गर्नुहोस्"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"कुनै खाता चयन गरिएको छैन"</string>
+    <string name="account_selected" msgid="2846876462199625974">"हाल प्रयोग गर्दै <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ठीक छ"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"रद्द गर्नुहोस्"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"बाहिर निकल्नुहोस्"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"प्रयोग गर्न खाता चयन गर्नुहोस्"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"अंग्रेजी (युके)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"अंग्रेजी (युएस्)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"स्पेनिस (युएस्)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"हिङ्लिस"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"सर्बियाई (ल्याटिन)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"अंग्रेजी (बेलायत) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"अंग्रेजी (अमेरिका) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"स्पेनेली (अमेरिका) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"हिङ्लिस (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"सर्बियाई (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (परम्परागत)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (सिरिलिक)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ल्याटिन)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (संकुचित)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"कुनै भाषा होइन (वर्णमाला)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"वर्णमाला (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"वर्णमाला (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"वर्णमाला (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"इमोजी"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"किबोर्ड थिम"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"होलो सेतो"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"होलो नीलो"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"सामाग्री कालो"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"सामाग्री प्रकाश"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"अनुकूलन इनपुट शैली"</string>
     <string name="add_style" msgid="6163126614514489951">"शैली थप्नुहोस्"</string>
     <string name="add" msgid="8299699805688017798">"थप्नुहोस्"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"वास्तवमै <xliff:g id="LANGUAGE_NAME">%s</xliff:g> को लागि यो फाइल स्थापना गर्नुहुन्छ?"</string>
-    <string name="error" msgid="8940763624668513648">"कुनै त्रुटि भयो"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"कुञ्जी लामो थिचाइ ढिलाइ"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"अब तपाईँ <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">"लन्चरमा अनुप्रयोग आइकन देखाउनुहोस्"</string>
     <string name="app_name" msgid="6320102637491234792">"शब्दकोश प्रदायक"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"शब्दकोश प्रदायक"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"शब्दकोश सेवा"</string>
diff --git a/java/res/values-nl/strings-emoji-descriptions.xml b/java/res/values-nl/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..3b29890
--- /dev/null
+++ b/java/res/values-nl/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Copyrightsymbool"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Gedeponeerd-symbool"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dubbel uitroepteken"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Uitroepteken vraagteken"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Handelsmerksymbool"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informatiebron"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Pijl links-rechts"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Pijl omhoog-omlaag"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Pijl naar noordwesten"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Pijl naar noordoosten"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Pijl naar zuidoosten"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Pijl naar zuidwesten"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Gehoekte pijl naar links"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Gehoekte pijl naar rechts"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Horloge"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Zandloper"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Zwarte dubbele driehoekjes naar rechts"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Zwarte dubbele driehoekjes naar links"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Zwarte dubbele driehoekjes omhoog"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Zwarte dubbele driehoekjes omlaag"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Wekker"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Zandloper met lopend zand"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Omcirkelde Latijnse hoofdletter M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Zwart klein vierkant"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Wit klein vierkant"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Zwart driehoekje naar rechts"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Zwart driehoekje naar links"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Wit middelgroot vierkant"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Zwart middelgroot vierkant"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Wit middelgroot klein vierkant"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Zwart middelgroot klein vierkant"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Zwarte zon met stralen"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Wolk"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Zwarte telefoon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Stembus met vinkje"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraplu met regendruppels"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Warme drank"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Witte wijsvinger omhoog"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Wit lachend gezicht"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Ram"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Stier"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Tweelingen"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Kreeft"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leeuw"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Maagd"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Weegschaal"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Schorpioen"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Boogschutter"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Steenbok"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Waterman"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Vissen"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Zwarte schoppen"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Zwarte klavers"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Zwarte harten"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Zwarte ruiten"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Heetwaterbronnen"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Zwart universeel recyclingsymbool"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Rolstoelsymbool"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Anker"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Waarschuwingsbord"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Hoogspanningsbord"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Middelgrote witte cirkel"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Middelgrote zwarte cirkel"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Voetbal"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Honkbal"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Sneeuwpop zonder sneeuw"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Zon achter wolk"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Slangendrager"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Verboden toegang"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kerk"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontein"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Vlag in hole"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Zeilboot"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tent"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Benzinepomp"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Zwarte schaar"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Wit vinkje"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Vliegtuig"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Envelop"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Vuist omhoog"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Hand omhoog"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Overwinningsgebaar"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Potlood"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Zwarte vulpen"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Gevuld vinkje"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Gevuld vermenigvuldigingsteken x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Sterretjes"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Sterretje met acht spaken"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Zwarte achtpuntige ster"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Sneeuwvlok"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Fonkeling"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kruis"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Kruis in zwart vierkant"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Gevuld vraagteken"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Vraagteken met omtrek"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Uitroepteken met omtrek"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Gevuld uitroepteken"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Effen zwart hart"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Gevuld plusteken"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Gevuld minteken"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Gevuld deelteken"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Gevulde pijl naar rechts"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Gekrulde lus"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dubbele gekrulde lus"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Pijl naar rechts en vervolgens omhoog"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Pijl naar rechts en vervolgens omlaag"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Zwarte pijl naar links"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Zwarte pijl-omhoog"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Zwarte pijl-omlaag"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Zwart groot vierkant"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Wit groot vierkant"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Witte middelgrote ster"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Gevulde grote cirkel"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Golvend streepje"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Beurtwisselingsteken"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Omcirkeld ideogram \'Gefeliciteerd\'"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Omcirkeld ideogram \'Geheim\'"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong-steen rode draak"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Speelkaart zwarte joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Bloedgroep A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Bloedgroep B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Bloedgroep O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkeerplaats"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Bloedgroep AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL in vierkant"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"COOL in vierkant"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"FREE in vierkant"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID in vierkant"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"NEW in vierkant"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG in vierkant"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK in vierkant"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS in vierkant"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"UP met uitroepteken in vierkant"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS in vierkant"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana \'Hier\' in vierkant"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Katakana \'Service\' in vierkant"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogram \'Kosteloos\' in vierkant"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogram \'Gereserveerde plaats\' in vierkant"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogram \'Verbod\' in vierkant"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogram \'Ruimte beschikbaar\' in vierkant"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogram \'Acceptatie\' in vierkant"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogram \'Volledig bezet\' in vierkant"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogram \'Betaald\' in vierkant"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogram \'Maandelijks\' in vierkant"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogram \'Aanvraag\' in vierkant"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogram \'Korting\' in vierkant"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogram \'In bedrijf\' in vierkant"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideogram\' Voordeel\' in cirkel"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideogram \'Acceptatie\' in cirkel"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cycloon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Mistig"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Dichte paraplu"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Night met sterren"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Zonsopgang boven de bergen"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Zonsopgang"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Stadslandschap bij zonsondergang"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Zonsondergang over gebouwen"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Regenboog"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Brug bij nacht"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Golf"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkaan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Melkweg"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Aardbol Europa-Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Aardbol Noord- en Zuid-Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Aardbol Azië-Australië"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Aardbol met meridianen"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbool voor nieuwe maan"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbool voor wassende halvemaan"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbool voor maan in eerste kwartaal"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbool voor wassende bolvormige maan"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbool voor volle maan"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbool voor afnemende bolvormige maan"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbool voor maan in laatste kwartier"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbool voor afnemende halvemaan"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Halvemaan"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nieuwe maan met gezicht"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Maan in eerste kwartier met gezicht"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Maan in laatste kwartier met gezicht"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Volle maan met gezicht"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Zon met gezicht"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Stralende ster"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Vallende ster"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanje"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Zaailing"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Groenblijvende boom"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Loofboom"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmboom"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulp"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kersenbloesem"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Roos"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Zonnebloem"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Bloesem"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Maïskolf"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Rijstaar"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Kruid"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Klavertje vier"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Esdoornblad"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Gevallen blad"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blad dwarrelt in de wind"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Paddestoel"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomaat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Druiven"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Meloen"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Watermeloen"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarijn"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citroen"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banaan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rode appel"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Groene appel"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Peer"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Perzik"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kersen"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Aardbei"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzapunt"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Vlees op het bot"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Kippenpoot"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rijstcracker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rijstballetje"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Gekookte rijst"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry en rijst"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Stomende kom"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Brood"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Friet"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Gepofte zoete aardappel"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Gefrituurde garnaal"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Viskoekje met krul"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Softijs"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Geschaafd ijs"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"IJs"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chocoladereep"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Snoep"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lolly"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vla"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honingpot"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Cake"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento box"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Stoofschotel"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Koken"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Vork en mes"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Theekopje zonder oor"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakefles en kopje"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wijnglas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktailglas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropisch drankje"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Bierglas"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Klinkende bierglazen"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Babyflesje"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Strik"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Ingepakt cadeau"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Verjaardagstaart"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Pompoenlantaarn"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Kerstboom"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Kerstman"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Vuurwerk"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Sterretje"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Party-popper"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Confettibal"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Boom met papierlinten"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Gekruiste vlaggen"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Dennentakdecoratie"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanse poppen"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Karperwimpel"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Windklok"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Maankijkceremonie"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Schooltas"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Diplomeringshoed"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Draaimolenpaard"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Reuzenrad"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Achtbaan"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Hengel en vis"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microfoon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmcamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Bioscoop"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Hoofdtelefoon"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Schilderspalet"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Hoge hoed"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Circustent"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Kaartje"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klapbord"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Podiumkunsten"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videogame"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Voltreffer"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Fruitautomaat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljart"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dobbelsteen"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowlen"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Speelkaarten met bloemen"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Muzieknoot"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Meerdere muzieknoten"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofoon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitaar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Keyboard"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Viool"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Notenschrift"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Hardloopshirt met sjerp"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisracket en bal"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski\'s en skischoen"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbal en basket"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Geblokte vlag"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Hardloper"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofee"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Paardenrennen"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"American football"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Zwemmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Huis bouwen"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Huis met tuin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kantoorgebouw"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japans postkantoor"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europees postkantoor"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Ziekenhuis"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Pinautomaat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love-hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Supermarkt"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"School"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Warenhuis"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabriek"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya-lantaarn"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japans kasteel"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europees kasteel"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Rat"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Muis"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Os"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Waterbuffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Koe"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Luipaard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Konijn"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kat"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Draak"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Walvis"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Slak"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Slang"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Paard"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ram"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Geit"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Schaap"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Aap"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Haan"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kip"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hond"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Varken"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Everzwijn"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Olifant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Octopus"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiraalvormige schelp"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Insect"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mier"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Honingbij"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Lieveheersbeestje"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Vis"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropische vis"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Kogelvis"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Schildpad"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kuiken dat uit het ei komt"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kuikentje"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kuikentje dat naar voren kijkt"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Vogel"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pinguïn"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poedel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedaris"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kameel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dolfijn"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Muizengezicht"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Koeiengezicht"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tijgergezicht"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Konijnengezicht"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kattengezicht"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Drakengezicht"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Spuitende walvis"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Paardengezicht"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Apengezicht"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hondengezicht"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Varkensgezicht"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Kikkergezicht"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamstergezicht"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Wolvengezicht"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Berengezicht"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandagezicht"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Varkensneus"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pootafdrukken"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ogen"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Oor"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Neus"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mond"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tong"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Witte hand met wijsvinger omhoog"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Witte hand met wijsvinger omlaag"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Witte hand met wijsvinger naar links"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Witte hand met wijsvinger naar rechts"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Gebalde vuist"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Zwaaiende hand"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK-handgebaar"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Duim omhoog"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Duim omlaag"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Klappende handen"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Open handen"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Kroon"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Dameshoed"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Bril"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Stropdas"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Jurk"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Dameskleding"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Portemonnee"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handtas"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Tasje"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Herenschoen"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportschoen"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Schoen met hoge hak"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Damessandaal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Dameslaars"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Voetafdrukken"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Buste in silhouet"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Bustes in silhouet"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Jongen"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Meisje"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Man"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Vrouw"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familie"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Man en vrouw hand in hand"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Twee mannen hand in hand"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Twee vrouwen hand in hand"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Politieagent"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Vrouw met konijnenoren"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Bruid met sluier"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Persoon met blond haar"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Man met Chinees hoedje"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Man met tulband"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Oudere man"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Oudere vrouw"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Bouwvakker"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinses"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanse oger"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanse kobold"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spook"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Baby-engel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Buitenaards wezen"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Buitenaards monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Duiveltje"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Schedel"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Persoon van informatiebalie"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardesoldaat"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Danser"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lippenstift"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nagellak"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Gezichtsmassage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Kapsel"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Kapperspaal"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Injectiespuit"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pil"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kusafdruk"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Liefdesbrief"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Edelsteen"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Kus"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Boeket"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Stel met hartje"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Bruiloft"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Kloppend hart"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Gebroken hart"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Twee harten"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Glinsterend hart"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Groeiend hart"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hart met pijl"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blauw hart"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Groen hart"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Geel hart"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Paars hart"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hart met lint"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Draaiende harten"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Hartdecoratie"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Ruitvorm met stip in het midden"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektrische gloeilamp"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbool voor woede"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bom"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbool voor slapen"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbool voor botsing"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbool voor spattende zweetdruppels"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Druppel"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbool voor wegrennen"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Poep"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Gespannen biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbool voor duizelig"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Spraakballon"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Gedachtenballon"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Witte bloem"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbool voor honderd punten"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Zak met geld"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valutaconversie"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Vetgedrukt dollarteken"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Creditcard"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bankbiljet met Yen-teken"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Bankbiljet met dollarteken"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bankbiljet met euroteken"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bankbiljet met pondteken"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Geld met vleugels"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Grafiek met opwaartse trend en Yen-teken"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Stoel"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Pc"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Koffertje"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskette"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optische schijf"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Bestandsmap"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Bestandsmap openen"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Gekrulde pagina"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Naar voren gerichte pagina"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Scheurkalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kaartindex"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Grafiek met opwaartse trend"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Grafiek met neerwaartse trend"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Staafdiagram"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Klembord"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Punaise"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Kopspeld"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Paperclip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Liniaal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Geodriehoek"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Bladwijzertabs"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Grootboek"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Schrift"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Schrift met decoratie"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Gesloten boek"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Geopend boek"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Groen boek"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blauw boek"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranje boek"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Boeken"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Naamkaartje"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Rol"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefoonhoorn"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faxapparaat"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellietantenne"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Handluidspreker"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafoon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Postvak UIT"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Postvak IN"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pakket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mailsymbool"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Inkomende envelop"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Envelop met pijl-omlaag daarboven"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Gesloten brievenbus met vlag omlaag"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Gesloten brievenbus met vlag omhoog"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Open brievenbus met vlag omhoog"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Open brievenbus met vlag omlaag"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Brievenbus"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posthoorn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Krant"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiele telefoon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiele telefoon met pijl-rechts aan linkerkant"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Trilstand"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiele telefoon uit"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Geen mobiele telefoons"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenne met streepjes"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Camera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videocamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisie"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videoband"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Gekruiste pijlen naar rechts"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Twee open horizontale pijlen die rechtsom draaien"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Twee open horizontale pijlen die rechtsom draaien met een cirkel met het cijfer 1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Twee open verticale pijlen die rechtsom draaien"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Twee open verticale pijlen die linksom draaien"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbool voor lage helderheid"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbool voor hoge helderheid"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Luidspreker met doorstrepingsteken"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Luidspreker"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Luidspreker met één geluidsgolf"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Luidspreker met drie geluidsgolven"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batterij"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektrische stekker"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Vergrootglas naar links gericht"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Vergrootglas naar rechts gericht"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Slot met vulpen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Gesloten slot met sleutel"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Sleutel"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Slot"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Open slot"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Bel"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Bel met doorstrepingsteken"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bladwijzer"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Koppelingsteken"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Keuzerondje"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"BACK met pijl naar links daarboven"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"END met pijl naar links daarboven"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ON met uitroepteken met pijl naar links en rechts daarboven"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"SOON met pijl naar rechts daarboven"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"TOP met pijl-omhoog daarboven"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbool voor niemand onder de achttien"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Cijfertoets tien"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Invoersymbool voor Latijnse hoofdletters"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Invoersymbool voor Latijnse kleine letters"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Invoersymbool voor cijfers"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Invoersymbool voor symbolen"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Invoersymbool voor Latijnse letters"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Vuur"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Zaklamp"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Moersleutel"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hamer"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Bout en moer"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Keukenmes"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistool"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscoop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescoop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristallen bol"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Zespuntige ster met stip in het midden"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japans symbool voor beginner"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Drietand-symbool"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Zwarte vierkant"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Witte vierkant"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Grote rode cirkel"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Grote blauwe cirkel"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Grote oranje ruit"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Grote blauwe ruit"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Kleine oranje ruit"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Kleine blauwe ruit"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Rode driehoek omhoog"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Rode driehoek omlaag"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Kleine rode driehoek omhoog"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Kleine rode driehoek omlaag"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Eén uur op de klok"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Twee uur op de klok"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Drie uur op de klok"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Vier uur op de klok"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Vijf uur op de klok"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Zes uur op de klok"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Zeven uur op de klok"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Acht uur op de klok"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Negen uur op de klok"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Tien uur op de klok"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Elf uur op de klok"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Twaalf uur op de klok"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Half twee op de klok"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Half drie op de klok"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Half vier op de klok"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Half vijf op de klok"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Half zes op de klok"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Half zeven op de klok"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Half acht op de klok"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Half negen op de klok"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Half tien op de klok"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Half elf op de klok"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Half twaalf op de klok"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Half één op de klok"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Berg Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokiotoren"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Vrijheidsbeeld"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhouet van Japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai-standbeeld"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Grijnzend gezicht"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Grijnzend gezicht met lachende ogen"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Gezicht met tranen van geluk"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Lachend gezicht met open mond"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Lachend gezicht met open mond en lachende ogen"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Lachend gezicht met open mond en angstzweet"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Lachend gezicht met open mond en ogen dicht"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Lachend gezicht met halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Lachend gezicht met hoorns"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Knipogend gezicht"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Lachend gezicht met lachende ogen"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Gezicht dat geniet van heerlijk eten"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Opgelucht gezicht"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Lachend gezicht met hartvormige ogen"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Lachend gezicht met zonnebril"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Gezicht met grote grijns"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Uitgestreken gezicht"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Uitdrukkingsloos gezicht"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Chagrijnig gezicht"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Gezicht met angstzweet"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Peinzend gezicht"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Verward gezicht"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Onthutst gezicht"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kussend gezicht"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Gezicht dat een kus uitdeelt"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kussend gezicht met lachende ogen"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kussend gezicht met dichte ogen"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Gezicht met uitgestoken tong"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Gezicht met uitgestoken tong en knipoog"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Gezicht met uitgestoken tong en dichte ogen"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Teleurgesteld gezicht"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Bezorgd gezicht"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Boos gezicht"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Pruilend gezicht"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Huilend gezicht"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Volhardend gezicht"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Gezicht met triomfantelijke blik"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Teleurgesteld maar opgelucht gezicht"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Fronsend gezicht met open mond"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Gekweld gezicht"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Angstig gezicht"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Vermoeid gezicht"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Slaperig gezicht"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Moe gezicht"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Gezicht met grimas"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Hard huilend gezicht"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Gezicht met open mond"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Verstomd gezicht"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Gezicht met open mond en angstzweet"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Gezicht dat schreeuwt van angst"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Geschokt gezicht"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Blozend gezicht"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Slapend gezicht"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Duizelig gezicht"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Gezicht zonder mond"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Gezicht met medisch masker"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Grijnzend kattengezicht met lachende ogen"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Kattengezicht met tranen van geluk"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Lachend kattengezicht met open mond"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Lachend kattengezicht met hartvormige ogen"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Kattengezicht met ironische lach"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kussend kattengezicht met dichte ogen"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Pruilend kattengezicht"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Huilend kattengezicht"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Vermoeid kattengezicht"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Gezicht met \'niet goed\'-gebaar"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Gezicht met \'OK\'-gebaar"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Persoon die diep buigt"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"\'Geen kwaad zien\'-aapje"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"\'Geen kwaad horen\'-aapje"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"\'Geen kwaad spreken\'-aapje"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Vrolijk persoon met één hand in de lucht"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Persoon die beide handen omhoog steekt om iets te vieren"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Fronsend persoon"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Persoon met pruilend gezicht"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Persoon met gevouwen handen"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Stoomlocomotief"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Treinwagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Hogesnelheidstrein"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Hogesnelheidstrein met kogelneus"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Trein"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Lightrail"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Station"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tram"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tramwagon"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Naderende bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleybus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bushalte"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulance"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Brandweerauto"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Politieauto"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Naderende politieauto"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Naderende taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Auto"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Naderende auto"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Camper"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Bestelbus"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Vrachtwagen met oplegger"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Tractor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Bergspoor"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Zweeftrein"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Bergkabelbaan"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Luchtkabelbaan"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Schip"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Roeiboot"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedboot"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horizontale verkeerslichten"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Verticale verkeerslichten"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Werk in uitvoering"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Zwaailicht"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Driehoekige vlag op paal"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Deur"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"\'Verboden toegang\'-bord"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Roken toegestaan"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Symbool voor niet roken"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Symbool voor afval in prullenbak gooien"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Symbool voor geen afval weggooien"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbool voor drinkwater"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbool voor geen drinkwater"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Fiets"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Geen fietsen"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Fietser"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountainbiker"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Voetganger"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Geen voetgangers"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Kinderoversteek"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbool voor herentoilet"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbool voor damestoilet"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toiletsymbool"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Babysymbool"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toilet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Wc"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Douche"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Bad"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badkuip"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Paspoortcontrole"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Douane"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagage ophalen"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Achtergelaten bagage"</string>
+</resources>
diff --git a/java/res/values-nl/strings-talkback-descriptions.xml b/java/res/values-nl/strings-talkback-descriptions.xml
index c59f3f2..884cf21 100644
--- a/java/res/values-nl/strings-talkback-descriptions.xml
+++ b/java/res/values-nl/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Geen tekst ingevoerd"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Met <xliff:g id="KEY_NAME">%1$s</xliff:g> wordt <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> gecorrigeerd naar <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Met <xliff:g id="KEY_NAME">%1$s</xliff:g> voert u automatische correctie uit"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Geen suggestie"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Onbekend teken"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Meer symbolen"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Hoofdletter I, punt erboven"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Onbekend symbool"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Onbekende emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Verveeld gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Beschaamd gezicht"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Gezicht met zonnebril"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Verbaasd gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kussend gezicht"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Fronsend gezicht"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatieve tekens zijn beschikbaar"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatieve tekens worden verwijderd"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatieve suggesties zijn beschikbaar"</string>
diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml
index 33350b1..807a1a3 100644
--- a/java/res/values-nl/strings.xml
+++ b/java/res/values-nl/strings.xml
@@ -26,25 +26,30 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Trillen bij toetsaanslag"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Geluid bij toetsaanslag"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up bij toetsaanslag"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Voorkeuren"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Accounts en privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Uiterlijk en indelingen"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Invoer met bewegingen"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Tekstcorrectie"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Geavanceerd"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Thema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Gesplitst toetsenbord inschakelen"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google-toetsenbordsynchronisatie"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synchronisatie is ingeschakeld"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Uw persoonlijke woordenboek synchroniseren op meerdere apparaten"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Nu synchroniseren"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Cloudgegevens verwijderen"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Hiermee worden uw gesynchroniseerde gegevens verwijderd van Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Wilt u gesynchroniseerde gegevens echt verwijderen uit de cloud?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Verwijderen"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Annuleren"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Uw persoonlijke woordenboek wordt gesynchroniseerd en er wordt een back-up gemaakt op servers van Google. De statistische gegevens voor woordfrequentie kunnen worden verzameld om onze producten te verbeteren. Het verzamelen en gebruik van alle gegevens is in overeenstemming met het "<a href="https://www.google.com/policies/privacy">"Privacybeleid van Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Voeg een Google-account toe om deze functie in te schakelen"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Invoermeth. overschakelen"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Schakelknop voor taal ook van toepassing op andere invoermethoden"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Schakelknop voor taal"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Weergeven wanneer meerdere invoertalen zijn geselecteerd"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Schuifaanduiding weergeven"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Zichtbare aanduiding weergeven wanneer wordt geschoven met Shift- of symbooltoetsen"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Afwijz.vertr. toetspop-up"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Vertr.sluiten toetspop-up"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Geen vertraging"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standaard"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> ms"</string>
@@ -62,10 +67,7 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Algemeen woordenboek"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Correctievoorstellen weergeven"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Voorgestelde woorden weergeven tijdens typen"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Altijd weergeven"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Weergeven in staande modus"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Altijd verbergen"</string>
-    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Aanstootgevende woorden blokk."</string>
+    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Grof taalgebruik blokkeren"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Geen potentieel aanstootgevende woorden voorstellen"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autocorrectie"</string>
     <string name="auto_correction_summary" msgid="5625751551134658006">"Met spatiebalk en interpunctie worden verkeerd gespelde woorden automatisch gecorrigeerd"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Toets voor spraakinvoer"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Geen spraakinvoermethoden ingeschakeld. Ga naar \'Instellingen voor taal en invoer\'."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Feedback verzenden"</string>
-    <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string>
-    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Talen"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Help en feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Talen"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tik nogmaals om op te slaan"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tik hier om op te slaan"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Toetsenbordthema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Schakelen tussen accounts"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Geen accounts geselecteerd"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> wordt momenteel gebruikt"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Annuleren"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Uitloggen"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecteer een account om te gebruiken"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engels (GB)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engels (VS)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spaans (VS)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi-Engels"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Servisch (Latijns)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engels (VK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engels (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaans (VS) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi-Engels (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Servisch (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditioneel)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillisch)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latijns)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Geen taal (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (pc)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Toetsenbordthema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Aangep. invoerstijlen"</string>
     <string name="add_style" msgid="6163126614514489951">"Stijl toev."</string>
     <string name="add" msgid="8299699805688017798">"Toevoegen"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Inschakelen"</string>
     <string name="not_now" msgid="6172462888202790482">"Niet nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Dezelfde invoerstijl bestaat al: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Vertraging toets lang indrukkn"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Trilingsduur bij toetsgebruik"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Geluidsvolume bij toetsgebruik"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Extern woordenboekbestand lezen"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Geen woordenboekbestanden in de map \'Downloads\'"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecteer een woordenboekbestand om te installeren"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Wilt u dit bestand voor het <xliff:g id="LANGUAGE_NAME">%s</xliff:g> echt installeren?"</string>
-    <string name="error" msgid="8940763624668513648">"Er is een fout opgetreden"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Vertraging toets lang indrukkn"</string>
     <string name="button_default" msgid="3988017840431881491">"Standaard"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Welkom bij <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"met Invoer met bewegingen"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"U kunt nu in al uw favoriete apps typen met <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Extra talen configureren"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Voltooid"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"App-pictogram weergeven"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"App-pictogram weergeven in het opstartprogramma"</string>
     <string name="app_name" msgid="6320102637491234792">"Woordenboekleverancier"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Woordenboekleverancier"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Woordenboekservice"</string>
diff --git a/java/res/values-pl/strings-emoji-descriptions.xml b/java/res/values-pl/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..27a7966
--- /dev/null
+++ b/java/res/values-pl/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Znak praw autorskich"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Zarejestrowany znak towarowy"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Podwójny wykrzyknik"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Wykrzyknik i pytajnik"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Zastrzeżony znak towarowy"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Źródło informacji"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Strzałka w lewo i w prawo"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Strzałka w górę i w dół"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Strzałka w kierunku północno-zachodnim"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Strzałka w kierunku północno-wschodnim"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Strzałka w kierunku południowo-wschodnim"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Strzałka w kierunku południowo-zachodnim"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Strzałka w lewo z hakiem"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Strzałka w prawo z hakiem"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Zegarek"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Klepsydra"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Czarna podwójna strzałka trójkątna w prawo"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Czarna podwójna strzałka trójkątna w lewo"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Czarna podwójna strzałka trójkątna w górę"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Czarna podwójna strzałka trójkątna w dół"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Budzik"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Klepsydra z przesypującym się piaskiem"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Wielka litera M w kole"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Mały czarny kwadrat"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Mały biały kwadrat"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Czarny trójkąt w prawo"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Czarny trójkąt w lewo"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Biały średni kwadrat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Czarny średni kwadrat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Biały niewielki kwadrat"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Czarny niewielki kwadrat"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Czarne słońce z promieniami"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Chmura"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Czarny telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Zaznaczona kratka"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Parasol z kroplami deszczu"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Gorący napój"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Biały palec wskazujący w górę"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Biała uśmiechnięta buźka"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Baran"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Byk"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Bliźnięta"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rak"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lew"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Panna"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Waga"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpion"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Strzelec"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Koziorożec"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Wodnik"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ryby"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Pik"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Trefl"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Kier"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Karo"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Gorące źródła"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Czarny uniwersalny znak recyclingu"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Znak wózka inwalidzkiego"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Kotwica"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Znak ostrzegawczy"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Znak wysokiego napięcia"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Średnie białe koło"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Średnie czarne koło"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Piłka nożna"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Piłka baseballowa"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Bałwanek"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Słońce za chmurą"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Wężownik"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Zakaz wstępu"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kościół"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontanna"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Pole golfowe"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Żaglówka"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Namiot"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Dystrybutor paliwa"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Czarne nożyczki"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Znak zaznaczenia"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Samolot"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Koperta"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Uniesiona pięść"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Uniesiona ręka"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Gest zwycięstwa"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Ołówek"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Czarna stalówka"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Znak zaznaczenia"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Znak mnożenia x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Iskry"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Gwiazdka ośmioramienna"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Gwiazda ośmioramienna"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Płatek śniegu"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Iskra"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Krzyżyk"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Znak X kwadracie oznaczający zaprzeczenie"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Czarny ozdobny znak zapytania"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Biały ozdobny znak zapytania"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Biały ozdobny wykrzyknik"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Czarny ozdobny wykrzyknik"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Czarne serce"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Znak plusa"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Znak minusa"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Znak dzielenia"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Czarna strzałka w prawo"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Pętla"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Podwójna pętla"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Strzałka w prawo skręcająca w górę"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Strzałka w prawo skręcająca w dół"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Czarna strzałka w lewo"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Czarna strzałka w górę"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Czarna strzałka w dół"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Duży czarny kwadrat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Duży biały kwadrat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Biała średnia gwiazda"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Duże koło"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Fala"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Znak rozpoczęcia partii wokalisty"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Okrągły symbol gratulacji"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Okrągły symbol tajemnicy"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Kafelek mahjong czerwony smok"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Karta Joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Grupa krwi A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Grupa krwi B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Grupa krwi 0"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parking"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Grupa krwi AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Kwadratowy znak CL, czyli Czyste"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Kwadratowy znak Cool czyli Świetnie"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Kwadratowy znak Free, czyli Bezpłatne"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Kwadratowy znak ID, czyli Identyfikator"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Kwadratowy znak New, czyli Nowy"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Kwadratowy znak NG, czyli Niedobrze"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Kwadratowy znak OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Kwadratowy znak SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Kwadratowy znak UP, czyli W górę, z wykrzyknikiem"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Kwadratowy znak VS, czyli Kontra"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Kwadratowy znak Tutaj w zapisie katakana"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Kwadratowy znak Usługa w zapisie katakana"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Kwadratowy symbol Bezpłatne"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Kwadratowy symbol Zarezerwowane"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Kwadratowy symbol zakazu"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Kwadratowy symbol wolnego miejsca"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Kwadratowy symbol akceptacji"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Kwadratowy symbol Wszystkie miejsca zajęte"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Kwadratowy symbol Zapłacone"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Kwadratowy symbol Miesięcznie"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Kwadratowy symbol aplikacji"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Kwadratowy symbol rabatu"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Kwadratowy symbol Otwarte"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Okrągły symbol korzyści"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Okrągły symbol akceptacji"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Mgła"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Zamknięty parasol"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Rozgwieżdżone niebo"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Wschód słońca nad górami"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Wschód słońca"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Miasto o zmierzchu"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Zachód słońca nad budynkami"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Tęcza"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Most w nocy"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Fala"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Wulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Droga Mleczna"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Kula ziemska: Europa i Afryka"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Kula ziemska: Ameryki"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Kula ziemska: Azja i Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Kula ziemska z południkami i równoleżnikami"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbol nowiu"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbol wzrastającego sierpa Księżyca"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbol pierwszej kwadry"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbol poszerzonego Księżyca"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbol Księżyca w pełni"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbol malejącego Księżyca"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbol ostatniej kwadry"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbol ubywającego sierpa Księżyca"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Sierp Księżyca"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Księżyc w nowiu z twarzą"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Pierwsza kwadra Księżyca z twarzą"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Ostatnia kwadra Księżyca z twarzą"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Pełnia Księżyca z twarzą"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Słońce z twarzą"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Świecąca gwiazdka"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Spadająca gwiazda"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Orzech"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Roślinka"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Choinka"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Drzewo liściaste"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kwitnąca wiśnia"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Róża"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Ketmia"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Słonecznik"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Kwiat"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kolba kukurydzy"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Ryż"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Zioło"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Czterolistna koniczynka"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Liść klonowy"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Spadające liście"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Liście na wietrze"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Grzyb"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Pomidor"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Bakłażan"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Winogrona"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Arbuz"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarynka"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Cytryna"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Czerwone jabłko"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zielone jabłko"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Gruszka"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Brzoskwinia"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Wiśnie"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Truskawka"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Kawałek pizzy"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Mięso z kością"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Udko drobiowe"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Krakers ryżowy"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Kulka ryżowa"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Miseczka z ryżem"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Ryż z curry"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Parująca miska"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Chleb"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Frytki"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pieczony ziemniak"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Smażona krewetka"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Ciastko rybne ze spiralą"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Lody włoskie"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Lody kulkowe"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Lody"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Pączek"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Ciastko"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Tabliczka czekolady"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Cukierek"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lizak"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Ciastko kremowe"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Garnek z miodem"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Kawałek tortu"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Pudełko bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Miska z jedzeniem"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Patelnia"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Nóż i widelec"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Filiżanka bez uszka"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Butelka sake i czarka"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Kieliszek na wino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kieliszek koktajlowy"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Kufel z piwem"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Kufle z piwem"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Butelka ze smoczkiem"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Wstążka"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Prezent"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Tort urodzinowy"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Lampa z dyni"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Choinka bożonarodzeniowa"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Święty Mikołaj"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fajerwerki"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Sztuczne ognie"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balonik"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Tuba strzelająca"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfetti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Drzewo życzeń"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Japońskie flagi"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Stroiki świąteczne"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japońskie lalki"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Flaga w kształcie karpi"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Dzwonki wietrzne"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Święto podziwiania Księżyca"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Tornister"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Czapka akademicka"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Konik z karuzeli"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Diabelski młyn"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Kolejka górska w wesołym miasteczku"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Wędka z rybą"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Kamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Słuchawka"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cylinder"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cyrk"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Bilet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klaps"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Maski"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Gra wideo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Strzał w 10"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Automat do gier"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Kula bilardowa"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Kostka do gry"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Kręgle"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Karta"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nuta"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Nuty"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klawisze fortepianowe"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trąbka"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Skrzypce"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Klucz wiolinowy na pięciolinii"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Koszulka na ramiona"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Rakieta i piłka tenisowa"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Narta z butem narciarskim"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Piłka wpadająca do kosza"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Flaga w kratkę"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboardzista"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Biegacz"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Puchar"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Jazda konna"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Piłka do futbolu amerykańskiego"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Piłka do rugby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Pływak"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Dom"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Dom z ogrodem"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Biurowiec"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japoński budynek poczty"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europejski budynek poczty"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Szpital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel miłości"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Sklep"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Szkoła"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Dom towarowy"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabryka"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Czerwony lampion"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Pagoda"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Zamek"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Szczur"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mysz"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Wół"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Bawół wodny"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Krowa"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Lampart"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Królik"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kot"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Smok"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodyl"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Wieloryb"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Ślimak"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Wąż"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Koń"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Baran"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Koza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Owca"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Małpa"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Kogut"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kurczak"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Pies"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Świnia"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Dzik"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Słoń"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Ośmiornica"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Muszla"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Gąsienica"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mrówka"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Pszczoła"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Żuk"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Ryba"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Ryba tropikalna"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Ryba rozdymka"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Żółw"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Pisklę"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pisklak"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kurczaczek widziany z przodu"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ptak"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingwin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromader"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Wielbłąd"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Pysk myszy"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Pysk krowy"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Pysk tygrysa"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Pyszczek królika"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Pyszczek kota"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Paszcza smoka"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Wieloryb z fontanną"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Pysk konia"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Głowa małpy"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Pysk psa"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Głowa świnki"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Głowa żaby"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Pyszczek chomika"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Pysk wilka"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Głowa misia"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Głowa pandy"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Ryj"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Ślady łap"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oczy"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ucho"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nos"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Usta"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Język"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Palec wskazujący skierowany w górę"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Palec wskazujący skierowany w dół"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Palec wskazujący skierowany w lewo"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Palec wskazujący skierowany w prawo"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Znak pięści"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Znak machającej ręki"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Znak gestu dłonią oznaczającego OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Znak kciuka w górę"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Znak kciuka w dół"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Znak klaszczących dłoni"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Znak otwartych dłoni"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Korona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Damski kapelusz"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Okulary"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Krawat"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeansy"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Sukienka"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Bluzka"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Portmonetka"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Torebka"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Portmonetka damska"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"But męski"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"But sportowy"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"But na wysokim obcasie"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandałek damski"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Kozak"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Odciski stóp"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Sylwetka"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Sylwetki"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Chłopiec"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Dziewczynka"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mężczyzna"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Kobieta"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Rodzina"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Para trzymająca się za ręce"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Męska para trzymająca się za ręce"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Kobieca para trzymająca się za ręce"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policjant"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Kobiety z uszami królika"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Panna młoda w welonie"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Osoba jasnowłosa"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Człowiek w chińskiej czapce"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Mężczyzna w turbanie"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Staruszek"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Staruszka"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Niemowlę"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Robotnik"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Księżniczka"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogr japoński"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Goblin japoński"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Duch"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Aniołek"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Ufoludek"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Kosmita"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Diablik"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Czaszka"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Pracownik informacji"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Wartownik"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Tancerka"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Szminka"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Lakier do paznokci"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masaż twarzy"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Fryzura"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Szpulka"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Strzykawka"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Tabletka"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Odcisk ust"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"List miłosny"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Pierścionek"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Diament"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Pocałunek"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bukiet kwiatów"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Para z sercem"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Ślub"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Bijące serce"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Złamane serce"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dwa serca"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Błyszczące serce"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Rosnące serce"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Serce przebite strzałą"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Niebieskie serce"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zielone serce"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Żółte serce"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Różowe serce"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Serce ze wstążką"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Obracające się serca"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Serce"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Romb z kropką w środku"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Żarówka"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbol gniewu"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbol snu"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbol zderzenia"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Znak siódmych potów"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Kropla"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Wiatr"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kupa"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Skołowany"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Rozmowa (dymek)"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Myśl (dymek)"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Biały kwiat"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbol stu punktów"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Worek z pieniędzmi"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Wymiana waluty"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Dolar"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Karta kredytowa"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Banknot ze znakiem jena"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Banknot ze znakiem dolara"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Banknot ze znakiem euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Banknot ze znakiem funta"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Pieniądze ze skrzydłami"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Wykres rosnący ze znakiem jena"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Fotel"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Komputer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Teczka"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidysk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Dyskietka"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Dysk optyczny"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Folder"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Otwarty folder"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Strona z zawinięciem"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Strona z zagięciem w rogu"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendarz"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Zdzierany kalendarz"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Wizytownik"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Wykres rosnący"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Wykres malejący"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Wykres słupkowy"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Podkładka do pisania"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pinezka"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Szpilka"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Spinacz"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Linijka"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Ekierka"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Zakładki"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Skoroszyt"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Notes"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Ozdobny notes"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Zamknięta książka"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Otwarta książka"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zielona książka"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Niebieska książka"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Pomarańczowa książka"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Książki"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Plakietka"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Zwój"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Notatka"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Słuchawka telefoniczna"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faks"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena satelitarna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Megafon"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Tuba nagłaśniająca"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Skrzynka nadawcza"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Skrzynka odbiorcza"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paczka"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-mail"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Przychodząca koperta"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Koperta z umieszczoną nad nią strzałką w dół"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Zamknięta skrzynka pocztowa z opuszczoną flagą"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Zamknięta skrzynka pocztowa z podniesioną flagą"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Otwarta skrzynka pocztowa z podniesioną flagą"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Otwarta skrzynka pocztowa z opuszczoną flagą"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Skrzynka na listy"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Trąbka pocztyliona"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Gazeta"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Telefon komórkowy"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Telefon komórkowy ze strzałką w prawo po lewej stronie"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Tryb wibracji"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Wyłączenie telefonu komórkowego"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Zakaz używania telefonów komórkowych"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena ze słupkami zasięgu"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Aparat"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Kamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Telewizor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Kaseta wideo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Przecinające się strzałki w prawo"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Strzałki w prawo i w lewo wskazujące kierunek obrotu zgodny z ruchem wskazówek zegara"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Strzałki w prawo i w lewo wskazujące kierunek obrotu zgodny z ruchem wskazówek zegara z cyfrą 1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Strzałki w dół i w górę wskazujące kierunek obrotu zgodny z ruchem wskazówek zegara"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Strzałki w dół i w górę wskazujące kierunek obrotu przeciwny do ruchu wskazówek zegara"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol małej jasności"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol dużej jasności"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Przekreślony głośnik"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Głośnik"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Głośnik z jedną falą dźwiękową"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Głośnik z trzema falami dźwiękowymi"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Bateria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Wtyczka"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa skierowana w lewo"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa skierowana w prawo"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Kłódka z wiecznym piórem"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Zamknięta kłódka z kluczem"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Klucz"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Kłódka"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Otwarta kłódka"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Dzwonek"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Przekreślony dzwonek"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Zakładka"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Ogniwo"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Przycisk radiowy"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Napis Back, czyli Wstecz, z umieszczoną nad nim strzałką w lewo"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Napis End, czyli Koniec, z umieszczoną nad nim strzałką w lewo"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Napis On, czyli Włączone, z umieszczoną nad nim strzałką dwukierunkową w lewo i prawo"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Napis Soon, czyli Wkrótce, z umieszczoną nad nim strzałką w prawo"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Napis Top, czyli Góra, z umieszczoną nad nim strzałką w górę"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbol Zakazane poniżej 18 lat"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Klawisz 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Symbol wpisywania wielkich liter"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Symbol wpisywania małych liter"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Symbol wpisywania cyfr"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Symbol wpisywania symboli"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Symbol wpisywania liter"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Ogień"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Latarka"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Klucz"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Młotek"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Śruba i nakrętka"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Nóż kuchenny"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistolet"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kryształowa kula"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sześcioramienna gwiazda z kropką w środku"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japoński symbol początkującego"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trójząb"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Przycisk – biały kwadrat w czarnej ramce"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Przycisk – czarny kwadrat w białej ramce"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Duże czerwone koło"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Duże niebieskie koło"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Duży pomarańczowy romb"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Duży niebieski romb"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Mały pomarańczowy romb"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Mały niebieski romb"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Czerwona strzałka trójkątna w górę"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Czerwona strzałka trójkątna w dół"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Mała czerwona strzałka trójkątna w górę"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Mała czerwona strzałka trójkątna w dół"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Tarcza zegara z godziną 1:00"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Tarcza zegara z godziną 2:00"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Tarcza zegara z godziną 3:00"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Tarcza zegara z godziną 4:00"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Tarcza zegara z godziną 5:00"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Tarcza zegara z godziną 6:00"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Tarcza zegara z godziną 7:00"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Tarcza zegara z godziną 8:00"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Tarcza zegara z godziną 9:00"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Tarcza zegara z godziną 10:00"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Tarcza zegara z godziną 11:00"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Tarcza zegara z godziną 12:00"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Tarcza zegara z godziną 1:30"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Tarcza zegara z godziną 2:30"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Tarcza zegara z godziną 3:30"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Tarcza zegara z godziną 4:30"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Tarcza zegara z godziną 5:30"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Tarcza zegara z godziną 6:30"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Tarcza zegara z godziną 7:30"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Tarcza zegara z godziną 8:30"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Tarcza zegara z godziną 9:30"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Tarcza zegara z godziną 10:30"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Tarcza zegara z godziną 11:30"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Tarcza zegara z godziną 12:30"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Góra Fudżi"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo Tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statua Wolności"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Mapa Japonii"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Posąg z Wyspy Wielkanocnej"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Szeroki uśmiech"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Szeroko uśmiechnięta buźka z roześmianymi oczami"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Łzy radości"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Szeroko uśmiechnięta buźka"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Roześmiana buźka ze śmiejącymi się oczami"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Roześmiana buźka ze śmiejącymi się oczami i kroplą potu"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Roześmiana buźka z zaciśniętymi oczami"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Uśmiechnięta buźka z aureolą"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Uśmiechnięta buźka z różkami"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Puszczenie oka"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Uśmiechnięta buźka z roześmianymi oczami"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Oblizująca się buźka"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Odprężona buźka"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Uśmiechnięta buźka z oczami w kształcie serc"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Uśmiechnięta buźka w ciemnych okularach"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Półuśmieszek"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Buźka obojętna"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Buźka bez wyrazu"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Niezadowolona buźka"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Buźka z kroplą potu"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Zamyślona buźka"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zakłopotana buźka"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Zirytowana buźka"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Buźka całująca"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Buźka przesyłająca całusa"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Całująca buźka z roześmianymi oczami"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Całująca buźka z zamkniętymi oczami"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Buźka pokazująca język"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Buźka pokazująca język i puszczająca oko"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Buźka z zamkniętymi oczami pokazująca język"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Rozczarowana buźka"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Zmartwiona buźka"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Rozgniewana buźka"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Nadąsana mina"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Płacząca buźka"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Zacięta twarz"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Dumna buźka"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Buźka z wyrazem rozczarowania połączonego z ulgą"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Niezadowolona buźka z otwartymi ustami"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Przerażona buźka"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Wystraszona buźka"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Zmęczona buźka"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Śpiąca buźka"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Zmęczona buźka"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grymaśna buźka"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Zapłakana buźka"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Buźka z otwartymi ustami"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Zaskoczona buźka"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Zziajana buźka"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Buźka krzycząca ze strachu"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Zdziwiona buźka"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Buźka z wypiekami"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Śpiąca buźka"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Buźka oszołomiona"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Buźka bez ust"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Buźka w masce chirurgicznej"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Roześmiany koci pyszczek"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Koci pyszczek płaczący ze śmiechu"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Szeroko uśmiechnięty koci pyszczek"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Uśmiechnięty koci pyszczek z oczami w kształcie serc"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Pyszczek kota ze skrzywionym uśmiechem"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Koci pyszczek całujący z zamkniętymi oczami"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Obrażony koci pyszczek"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Płaczący koci pyszczek"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Zmęczony koci pyszczek"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Buźka z gestem dezaprobaty"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Buźka z gestem aprobaty"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Osoba kłaniająca się"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Małpka zasłaniająca sobie oczy"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Małpka zasłaniająca sobie uszy"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Małpka zakrywająca sobie usta"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Zadowolona osoba z ręką w górze"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Osoba unosząca ręce w geście zwycięstwa"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Osoba niezadowolona"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Osoba z grymasem niezadowolenia"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Złożone ręce"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rakieta"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parowóz"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Wagon kolejowy"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Szybki pociąg"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Szybki pociąg z zaokrąglonym przodem"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Pociąg"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Kolej miejska"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stacja kolejowa"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramwaj"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Wagon tramwajowy"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Nadjeżdżający autobus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Przystanek autobusowy"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Mikrobus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Karetka pogotowia"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Wóz strażacki"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Samochód policyjny"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Nadjeżdżający samochód policyjny"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksówka"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Nadjeżdżająca taksówka"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Samochód"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Nadjeżdżający samochód"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Samochód rekreacyjny"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Samochód dostawczy"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Ciągnik z naczepą"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Ciągnik"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Kolej jednoszynowa"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Kolej górska"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Kolej podwieszana"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Kolejka górska"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Kolejka wisząca"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Statek"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Łódka z wiosłami"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Motorówka"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Poziome światła drogowe"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Pionowe światła drogowe"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Znak sygnalizujący prace drogowe"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Kogut policyjny"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trójkątna flaga na maszcie"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Drzwi"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Znak zakazu wejścia"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Znak Dla palących"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Znak zakazu palenia"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Znak Wyrzuć śmieci do kosza"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Znak Nie śmiecić"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Znak Woda pitna"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Znak Woda niezdatna do picia"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Rower"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Zakaz ruchu rowerów"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Rowerzysta"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Kolarz górski"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pieszy"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Zakaz ruchu pieszych"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Przejście dla dzieci"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Znak Dla panów"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Znak Dla pań"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toaleta"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Znak Dziecko"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toaleta"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Prysznic"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Kąpiel"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Wanna"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kontrola paszportowa"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Kontrola celna"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Odbiór bagażu"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Pozostawiony bagaż"</string>
+</resources>
diff --git a/java/res/values-pl/strings-talkback-descriptions.xml b/java/res/values-pl/strings-talkback-descriptions.xml
index 43fca5f..f43beed 100644
--- a/java/res/values-pl/strings-talkback-descriptions.xml
+++ b/java/res/values-pl/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nie wpisano tekstu"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> poprawia <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> wykonuje autokorektę"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Brak sugestii"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Nieznany znak"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Więcej symboli"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Wielka litera I z kropką"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Nieznany symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Nieznany emotikon"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Buźka znudzona"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Buźka zawstydzona"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Buźka w ciemnych okularach"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Buźka zdziwiona"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Buźka całująca"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Buźka marszcząca czoło"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatywne znaki są dostępne"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatywne znaki zostały zamknięte"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatywne propozycje są dostępne"</string>
diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml
index af1d2ce..9300775 100644
--- a/java/res/values-pl/strings.xml
+++ b/java/res/values-pl/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Wibracja przy naciśnięciu"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Dźwięk przy naciśnięciu"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Powiększ po naciśnięciu"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Ustawienia"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Konta i prywatność"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Wygląd i układy"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Pisanie gestami"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Korekta tekstu"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Zaawansowane"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Motyw"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Włącz podzieloną klawiaturę"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synchronizacja klawiatury Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synchronizacja jest włączona"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synchronizuj słownik osobisty na swoich urządzeniach"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synchronizuj teraz"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Usuń dane z chmury"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Usuwa zsynchronizowane dane z Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Twoje zsynchronizowane dane zostaną usunięte z chmury. Na pewno?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Usuń"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Anuluj"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Twój słownik osobisty będzie synchronizowany z serwerami Google i zostanie na nich utworzona jego kopia zapasowa. Aby ulepszać nasze usługi, możemy gromadzić informacje statystyczne dotyczące częstości występowania słów. Zbieranie i wykorzystywanie wszelkich informacji będzie się odbywać zgodnie z "<a href="https://www.google.com/policies/privacy">"Polityką prywatności Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Aby włączyć tę funkcję, dodaj konto Google do tego urządzenia"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Inne metody wprowadzania"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klawisz zmiany języka obejmuje też inne metody wprowadzania"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Klawisz zmiany języka"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Pokaż, gdy włączonych jest kilka języków wprowadzania"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Pokaż wskaźnik przesuwania"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Wyświetl ślad przesuwania od klawiszy Shift lub Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Opóźnienie znikania klawiszy"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez opóźnienia"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Wartość domyślna"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Słownik główny"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokazuj propozycje poprawek"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Wyświetl proponowane słowa podczas wpisywania"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Zawsze pokazuj"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Pokaż w trybie pionowym"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Zawsze ukrywaj"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokuj obraźliwe słowa"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Nie proponuj słów potencjalnie obraźliwych"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autokorekta"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Klawisz rozpoznawania mowy"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nie włączono żadnych metod wprowadzania głosowego. Sprawdź ustawienia języka i wprowadzania."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Prześlij opinię"</string>
-    <string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Języki"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pomoc i opinie"</string>
+    <string name="select_language" msgid="5709487854987078367">"Języki"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotknij ponownie, aby zapisać"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Kliknij tutaj, by zapisać"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motyw klawiatury"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Przełącz konta"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nie wybrałeś żadnych kont"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Teraz używasz konta <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Anuluj"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Wyloguj się"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Wybierz konto, którego chcesz używać"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angielski (Wielka Brytania)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angielski (Stany Zjednoczone)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"hiszpański (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"serbski (alfabet łaciński)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Angielski (Wielka Brytania) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Angielski (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Hiszpański (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"serbski (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradycyjny)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrylica)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (alfabet łaciński)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktowa)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Bez języka (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emotikony"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Motyw klawiatury"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Style niestandardowe"</string>
     <string name="add_style" msgid="6163126614514489951">"Dodaj styl"</string>
     <string name="add" msgid="8299699805688017798">"Dodaj"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Włącz"</string>
     <string name="not_now" msgid="6172462888202790482">"Nie teraz"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Taki styl wprowadzania już istnieje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Opóźnienie przy długim naciśnięciu"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Wibracja przy naciśniętym klawiszu"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Głośność przy naciśniętym klawiszu"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Odczyt zewnętrznego pliku słownika"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Brak plików słownika w folderze Pobrane pliki"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Wybierz plik słownika do zainstalowania"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Czy na pewno zainstalować ten plik dla języka: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Wystąpił błąd"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Opóźnienie przy długim naciśnięciu"</string>
     <string name="button_default" msgid="3988017840431881491">"Domyślne"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Witamy w aplikacji <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"z pisaniem gestami"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Teraz możesz pisać we wszystkich swoich ulubionych aplikacjach, używając aplikacji <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Skonfiguruj dodatkowe języki"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Zakończone"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Pokaż ikonę aplikacji"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Wyświetl ikonę aplikacji w programie uruchamiającym"</string>
     <string name="app_name" msgid="6320102637491234792">"Dostawca słownika"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dostawca słownika"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Usługa słownika"</string>
diff --git a/java/res/values-pt-rPT/strings-emoji-descriptions.xml b/java/res/values-pt-rPT/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..3231d9e
--- /dev/null
+++ b/java/res/values-pt-rPT/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Símbolo de direitos de autor"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Símbolo de marca registada"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Duplo ponto de exclamação"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Pontos de exclamação e de interrogação"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Símbolo de marca comercial"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Fonte de informação"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Seta para a direita e para a esquerda"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Seta para cima e para baixo"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Seta para noroeste"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Seta para nordeste"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Seta para sudeste"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Seta para sudoeste"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Seta para a esquerda em U"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Seta para a direita em U"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Relógio"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Ampulheta"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Triângulo duplo preto a apontar para a direita"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Triângulo duplo preto a apontar para a esquerda"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Triângulo duplo preto a apontar para cima"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Triângulo duplo preto a apontar para baixo"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Despertador"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Ampulheta com areia a cair"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"M latino maiúsculo redondo"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Quadrado preto pequeno"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Quadrado branco pequeno"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Triângulo preto a apontar para a direita"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Triângulo preto a apontar para a esquerda"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Quadrado branco médio"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Quadrado preto médio"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Quadrado branco pequeno/médio"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Quadrado preto pequeno/médio"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Sol preto com raios"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Nuvem"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Telefone preto"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Caixa com marca de visto"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Chapéu de chuva com gotas de chuva"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Bebida quente"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Dedo indicador branco a apontar para cima"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Cara branca sorridente"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Carneiro"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Touro"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gémeos"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Caranguejo"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leão"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgem"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Balança"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Escorpião"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagitário"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricórnio"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquário"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Peixes"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Carta de espadas"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Carta de paus"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Carta de copas"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Carta de ouros"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"A escaldar"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Símbolo de reciclagem universal preto"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Sinal de cadeira de rodas"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Âncora"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Sinal de aviso"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Sinal de alta voltagem"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Círculo branco médio"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Círculo preto médio"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Bola de futebol"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Basebol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Boneco de neve sem neve"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol encoberto"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Serpentário"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Sinal de entrada proibida"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Igreja"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fonte"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandeira no buraco"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Barco à vela"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tenda"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bomba de gasolina"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Tesoura preta"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Marca de visto branca sólida"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Avião"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Envelope"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Punho erguido"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Mão erguida"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Mão em V de vitória"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Lápis"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Ponteira de caneta preta"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Marca de visto sólida"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Sinal de multiplicação sólido"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Centelhas"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisco"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Estrela preta de oito pontas"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Floco de neve"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Centelha"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Marca de visto"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Marca de visto negativo quadrada"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Decoração de ponto de interrogação preto"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Decoração de ponto de interrogação branco"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Decoração de ponto de exclamação branco"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Símbolo de ponto de exclamação sólido"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Coração preto sólido"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Sinal de mais sólido"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Sinal de menos sólido"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Sinal de dividir sólido"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Seta preta para a direita"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Laço encaracolado"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Laço encaracolado duplo"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Seta curvada para cima"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Seta curvada para baixo"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Sete preta para a esquerda"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Seta preta para cima"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Seta preta para baixo"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Quadrado preto grande"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Quadrado preto grande"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Estrela branca média"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Círculo sólido grande"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Traço ondulado"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Símbolo de entrada na música"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograma circular de felicitações"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograma circular de segredo"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mosaico de Mahjong dragão vermelho"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Joker preto de baralho de cartas"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Tipo sanguíneo A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Tipo sanguíneo B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Tipo sanguíneo O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parque de Estacionamento"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Tipo sanguíneo AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL quadrado"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"\"Cool\" quadrado"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"\"Free\" quadrado"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"\"ID\" quadrado"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"\"New\" quadrado"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"\"NG\" quadrado"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"\"OK\" quadrado"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"\"SOS\" quadrado"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"\"Up\" quadrado com ponto de exclamação"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"\"vs\" quadrado"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"\"Katakana here\" quadrado"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"\"katakana service\" quadrado"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideograma quadrado gratuito"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideograma quadrado com reserva"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideograma quadrado de proibição"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideograma quadrado de vaga"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideograma quadrado de aceitação"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideograma quadrado de ocupação total"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideograma quadrado pago"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideograma quadrado mensal"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideograma quadrado de aplicação"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideograma quadrado de desconto"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideograma quadrado de negócios"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideograma circular de vantagem"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideograma circular de aceitação"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciclone"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Enevoado"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Chapéu de chuva fechado"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Noite estrelada"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Nascer do sol na montanha"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Nascer do sol"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Silhueta de cidade ao anoitecer"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Pôr do sol atrás dos prédios"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Arco-íris"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Ponte à noite"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Onda"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulcão"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Via Láctea"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globo terrestre Europa-África"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globo terrestre Américas"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globo terrestre Ásia-Austrália"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo com os meridianos"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Símbolo de lua nova"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Símbolo de lua crescente"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Símbolo de lua em quarto crescente"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Lua crescente convexa"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Símbolo de lua cheia"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Símbolo de lua minguante convexa"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Símbolo de lua em quarto minguante"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Símbolo de lua em quarto minguante"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Lua crescente"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Lua nova com cara"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Lua em quarto crescente com cara"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Lua em quarto minguante com cara"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Lua cheia com cara"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol com cara"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Estrela brilhante"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Estrela cadente"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Castanha"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Plântula"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Árvore de folha persistente"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Árvore de folha caduca"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmeira"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cato"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Túlipa"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Cerejeira em flor"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosa"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibisco"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Girassol"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Margarida"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Milho"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Planta de arroz"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Ervas"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Trevo-de-quatro-folhas"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Folha de ácer"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Folha a cair"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Folha a esvoaçar ao vento"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Cogumelo"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomate"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Beringela"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uvas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melão"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Melancia"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tangerina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limão"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananás"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Maçã vermelha"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Maçã verde"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pera"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pêssego"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Cerejas"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Morango"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hambúrguer"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Fatia de piza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Osso com carne"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Perna de frango"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Biscoito de arroz"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Bolinho de arroz"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Arroz cozinhado"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Arroz e caril"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Caçarola"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Esparguete"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Pão"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Batatas fritas"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Batata doce assada"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Camarão frito"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Pastel de peixe em turbilhão"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Gelado cremoso"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Gelado \"shaved ice\""</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Gelado"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biscoito"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Barra de chocolate"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Guloseima"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Chupa-chupa"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Pudim"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Pote de mel"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Bolacha amanteigada"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Caixa de refeições"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Tacho com comida"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Culinária"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Garfo e faca"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Chávena de chá sem pega"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Garrafa e chávena de saké"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Copo de vinho"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Copo de cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Bebida tropical"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Caneca de cerveja"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Brinde com canecas de cerveja"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberão"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Fita"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Presente embrulhado"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Bolo de aniversário"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Abóbora iluminada"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Árvore de Natal"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Pai Natal"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fogo-de-artifício"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Fogo-de-artifício"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balão"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Bombinhas de Carnaval"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Bola de confetti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Árvore do Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bandeiras cruzadas"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Decoração em pinho"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Bonecas japonesas"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Bandeirola de carpas"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Espanta espíritos"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Cerimónia de contemplação da lua"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Pasta da escola"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Chapéu de formatura"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Cavalo de carrossel"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Roda panorâmica"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Montanha-russa"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Cana de pesca e peixe"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Microfone"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Câmara de filmar"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Auricular"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Paleta de artista"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Chapéu de cartola"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Tenda de circo"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Bilhete"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Claquete"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Artes de palco"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videojogo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Em cheio no alvo"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Slot machine"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Bilhar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Dado de jogo"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Baralho de cartas com desenho de flores"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota de música"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Muitas notas de música"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitarra"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Teclado de música"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompete"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violino"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Pauta de música"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"T-shirt de corrida com faixa"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raquete e bola de ténis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Esqui e bota de esqui"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Bola e cesto de basquetebol"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Bandeira axadrezada"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Esquiador"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Corredor"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfista"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Troféu"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Corrida de cavalos"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Futebol americano"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Bola de râguebi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Nadador"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Construção de casas"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Casa com jardim"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Edifício de escritórios"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Estação de correios japonesa"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Estação de correios europeia"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banco"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Máquina de multibanco"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel romântico"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Loja de conveniência"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Escola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Centro comercial"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fábrica"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lanterna Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Castelo japonês"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Castelo europeu"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Ratazana"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Rato"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Boi"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Búfalo-asiático"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Vaca"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopardo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Coelho"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Gato"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragão"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Crocodilo"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Baleia"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Caracol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Cobra"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Cavalo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Carneiro"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Cabra"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovelha"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Macaco"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Galo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Galinha"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Cão"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Porco"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Javali"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Polvo"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Búzio"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Inseto"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Formiga"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Abelha"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Joaninha"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Peixe"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Peixe tropical"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Peixe-balão"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Tartaruga"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Galinha a chocar"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pintainho"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pintainho a olhar para a frente"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Pássaro"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pinguim"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Coala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Caniche"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedário"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Camelo bactriano"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Golfinho"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Focinho de rato"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Focinho de vaca"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Focinho de tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Focinho de coelho"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Focinho de gato"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Focinho de dragão"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Baleia a expelir água"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Focinho de cavalo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Focinho de macaco"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Focinho de cão"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Focinho de porco"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Focinho de sapo"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Focinho de hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Focinho de lobo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Focinho de urso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Focinho de urso-panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nariz de porco"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pegadas de garras"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Olhos"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Orelha"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nariz"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Boca"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Língua"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Dedo indicador a apontar para cima"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Dedo indicador a apontar para baixo"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Dedo indicador a apontar para a esquerda"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Dedo indicador a apontar para a direita"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Símbolo de punho fechado"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Símbolo de mão a acenar"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Símbolo de ok com a mão"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Símbolo de polegar para cima"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Símbolo de polegar para baixo"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Símbolo de mãos a bater palmas"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Símbolo de mãos abertas"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Coroa"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Chapéu de mulher"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Óculos"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Gravata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Calças de ganga"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Vestido"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Quimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Biquíni"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Roupas de mulher"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Carteira"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Mala"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Bolsa"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Sapato de homem"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Ténis de corrida"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Sapato de salto alto"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandália de mulher"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Botas de mulher"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Pegadas"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhueta de busto"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhueta de bustos"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Rapaz"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Rapariga"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Homem"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Mulher"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Família"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Homem e mulher de mãos dadas"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dois homens de mão dada"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Duas mulheres de mão dada"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Agente da polícia"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Mulher com orelhas de coelho"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Noiva com véu"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Pessoa loira"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Homem com gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Homem com turbante"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Homem mais velho"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Mulher mais velha"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bebé"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Trabalhador da construção civil"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Ogre japonês"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Duende japonês"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Fantasma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Anjo bebé"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Ser extraterrestre"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Monstro extraterrestre"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Imp."</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Caveira"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Assistente do balcão de informações"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guarda"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Bailarino"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Batom"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Verniz para as unhas"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Massagem facial"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Cortar o cabelo"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Símbolo de barbearia"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Seringa"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Comprimido"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Marca de beijo"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Carta de amor"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Anel"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Diamante"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Beijo"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Casal com coração"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Casamento"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Coração a bater"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Coração partido"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dois corações"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Coração reluzente"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Coração a crescer"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Coração com seta"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Coração azul"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Coração verde"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Coração amarelo"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Coração roxo"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Coração com laço"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Corações a dançar"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Coração decorativo"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Forma de diamante com ponto no interior"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Lâmpada elétrica"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Símbolo de raiva"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Símbolo de sono"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Símbolo de colisão"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Símbolo de transpiração"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Gota"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Símbolo de pressa"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Monte de cocó"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bíceps fletidos"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Símbolo de zonzear"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Balão de diálogo"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Balão de pensamento"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Flor branca"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Símbolo de cem pontos"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Saco de dinheiro"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Câmbio"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Símbolo de dólar sólido"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Cartão de crédito"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Nota com símbolo do yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Nota com símbolo de dólar norte-americano"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Nota com símbolo do euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Nota com símbolo da libra"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Notas com asas"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Gráfico com tendência altista e símbolo do yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Lugar"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Computador pessoal"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Pasta de trabalho"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisco"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disquete"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Disco ótico"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Pasta de ficheiros"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Pasta de ficheiro aberto"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Página com dobra"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Página virada para cima"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Calendário"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Calendário de mesa"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Porta-cartões de visita"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Gráfico com tendência altista"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Gráfico com tendência baixista"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Gráfico de barras"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Área de transferência"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Alfinete"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Alfinete redondo"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Clip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Régua"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Esquadro"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Marcadores de folhas"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Livro razão"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Bloco de notas"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Bloco de notas com capa decorada"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Livro fechado"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Livro aberto"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Livro verde"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Livro azul"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Livro cor de laranja"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Livros"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Etiqueta de nome"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Rolo"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Nota"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Auscultador de telefone"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Antena parabólica"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Sistema sonoro"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafone"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Bandeja de correio a enviar"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Bandeja de correio recebido"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Pacote"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Símbolo de email"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Envelope a chegar"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Envelope com seta para baixo em cima"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Caixa de correio fechada com bandeirola para baixo"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Caixa de correio com bandeirola para cima"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Caixa de correio aberta com bandeirola para cima"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Caixa de correio aberta com bandeirola para baixo"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Caixa de correio"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Aviso sonoro de correio"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Jornal"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Telemóvel"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Telemóvel com seta para a direita à esquerda"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Modo de vibração"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Telemóvel desligado"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Proibido usar o telemóvel"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Sinal de barras"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Câmara"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Câmara de filmar"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televisão"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Rádio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Cassete de vídeo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Setas cruzadas para a direita"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Setas abertas em círculo para a esquerda e para a direita no sentido dos ponteiros do relógio"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Setas abertas em círculo para a esquerda e para a direita no sentido dos ponteiros do relógio com o algarismo 1 sobreposto"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Setas abertas em círculo para baixo e para cima no sentido dos ponteiros do relógio"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Setas abertas em círculo para baixo e para cima no sentido contrário ao dos ponteiros do relógio"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Símbolo de pouco brilho"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Símbolo de brilho intenso"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Altifalante com barra de cancelamento"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Altifalante"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Altifalante com uma onda de som"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Altifalante com três ondas de som"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Bateria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Ficha elétrica"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa inclinada para a esquerda"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa inclinada para a direita"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Cadeado com caneta de tinta permanente"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Cadeado fechado com chave"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Chave"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Cadeado"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Cadeado aberto"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Sino"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Sino com faixa de cancelamento"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Marcador"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Corrente"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Botão de opção"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"\"Back\" com seta para a esquerda em cima"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"\"End\" com seta para a esquerda em cima"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"\"On\" com ponto de exclamação e seta para os dois lados em cima"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"\"Soon\" com seta para a direita em cima"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"\"Top\" com seta para cima no topo"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Símbolo de proibida a presença de menores de idade"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tecla do algarismo dez"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Símbolo de introdução de letras maiúsculas latinas"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Símbolo de introdução de letras minúsculas latinas"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Símbolo de introdução de números"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Símbolo de introdução para símbolos"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Símbolo de introdução de letras latinas"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Fogo"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Lanterna"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Chave de bocas"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martelo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Parafuso e porca"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Faca de cozinha japonesa"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscópio"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescópio"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Bola de cristal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Estrela de seis pontas com ponto no meio"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Símbolo japonês para principiante"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Símbolo de tridente"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Botão quadrado preto"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Botão quadrado branco"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Círculo grande vermelho"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Círculo grande azul"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Diamante grande cor de laranja"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Diamante grande azul"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Diamante pequeno cor de laranja"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Diamante pequeno azul"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Triângulo vermelho a apontar para cima"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Triângulo vermelho a apontar para baixo"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Triângulo pequeno vermelho a apontar para cima"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Triângulo pequeno vermelho a apontar para baixo"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Mostrador de relógio à 1h00"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Mostrador de relógio às 2h00"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Mostrador de relógio às 3h00"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Mostrador de relógio às 4h00"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Mostrador de relógio às 5h00"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Mostrador de relógio às 6h00"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Mostrador de relógio às 7h00"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Mostrador de relógio às 8h00"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Mostrador de relógio às 9h00"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Mostrador de relógio às 10h00"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Mostrador de relógio às 11h00"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Mostrador de relógio às 12h00"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Mostrador de relógio à 1h30"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Mostrador de relógio às 2h30"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Mostrador de relógio às 3h30"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Mostrador de relógio às 4h30"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Mostrador de relógio às 5h30"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Mostrador de relógio às 6h30"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Mostrador de relógio às 7h30"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Mostrador de relógio às 8h30"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Mostrador de relógio às 9h30"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Mostrador de relógio às 10h30"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Mostrador de relógio às 11h30"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Mostrador de relógio às 12h30"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Monte Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Torre de Tóquio"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Estátua da Liberdade"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhueta do Japão"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Cara sorridente"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Gargalhada"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Cara a chorar de alegria"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Cara a sorrir com boca aberta"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Cara a sorrir com boca aberta e olhos curvados"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Cara a sorrir com boca aberta e suor frio"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Cara a sorrir com boca aberta e olhos semicerrados"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Cara a sorrir com auréola"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Cara sorridente endiabrada"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Cara a piscar o olho"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Cara a sorrir com olhos curvados"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Cara a saborear uma refeição deliciosa"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Cara aliviada"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Cara a sorrir com olhos em forma de coração"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Cara a sorrir com óculos de sol"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Cara presunçosa"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Cara neutra"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Cara sem expressão"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Cara de desagrado"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Cara com suor frio"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Cara pensativa"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Cara baralhada"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Cara completamente baralhada"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Cara a dar um beijo"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Cara a atirar um beijo"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Cara a beijar com olhos sorridentes"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Cara a beijar com olhos fechados"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Cara com língua de fora"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Cara com língua de fora e a piscar o olho"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Cara com língua de fora e os olhos semicerrados"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Cara desapontada"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Cara preocupada"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Cara irritada"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Cara mal-humorada"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Cara a chorar"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Cara perseverante"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Cara com ar triunfante"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Cara desapontada, mas aliviada"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Cara franzida com boca aberta"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Cara preocupada"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Cara cheia de medo"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Cara desgastada"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Cara sonolenta"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Cara cansada"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Cara a fazer caretas"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Cara a chorar perdidamente"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Cara com boca aberta"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Cara expectante"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Cara com boca aberta e suor frio"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Cara a gritar de medo"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Cara de espanto"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Cara corada"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Cara a dormir"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Cara atordoada"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Cara sem boca"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Cara com máscara de médico"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Focinho de gato sorridente com olhos curvados"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Focinho de gato a chorar de alegria"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Focinho de gato sorridente com boca aberta"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Focinho de gato sorridente com olhos em forma de coração"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Focinho de gato com sorriso de través"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Focinho de gato a beijar com olhos fechados"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Focinho de gato mal-humorado"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Focinho de gato a chorar"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Focinho de gato desgastado"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Cara com gesto de desaprovação"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Cara com gesto de aprovação"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Pessoa profundamente arrependida"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Macaco \"não olhar para o mal\""</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Macaco \"não ouvir o mal\""</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Macaco \"não falar no mal\""</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Pessoa contente a levantar a mão"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Pessoa a erguer as duas mãos e a festejar"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Pessoa entristecida"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Pessoa com cara mal-humorada"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Pessoa com mãos juntas"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Foguetão"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicóptero"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Locomotiva a vapor"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Elétrico"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Comboio de alta velocidade"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Comboio de alta velocidade com cabeça aerodinâmica"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Comboio"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Metro de superfície"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Estação"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Elétrico"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Carruagem de elétrico"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autocarro"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Autocarro a aproximar-se"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Troleicarro"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Paragem de autocarro"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"\"Minibus\""</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulância"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Viatura de incêndio"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Carro da polícia"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Carro da polícia a aproximar-se"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Táxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Táxi a aproximar-se"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automóvel"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Automóvel a aproximar-se"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Veículo utilitário recreativo"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Camião de entregas"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Camião articulado"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Trator"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monocarril"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Linha férrea na montanha"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Via-férrea suspensa"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Teleférico"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Funicular aéreo"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Navio"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Barco a remos"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Barco a motor"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Semáforo na horizontal"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Semáforo vertical"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Sinal de obras"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Sirene de carro da polícia"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Bandeira triangular na haste"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Porta"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Sinal de entrada proibida"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Sinal de fumar"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Sinal de proibido fumar"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Sinal para colocar o lixo no seu devido lugar"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Sinal para não deixar lixo para o chão"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Sinal de água potável"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Sinal de água não potável"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicicleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Proibido andar de bicicleta"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Ciclista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Ciclista de montanha"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pedestre"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Proibido andar a pé"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Crianças a atravessar"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Sinal de entrada para homens"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Sinal de entrada para mulheres"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Lavabo"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Sinal de bebé"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Casa-de-banho"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"\"Water closet\""</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Chuveiro"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Banho"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Banheira"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Controlo de passaportes"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Alfândega"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Recolha de bagagem"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Perdidos e achados"</string>
+</resources>
diff --git a/java/res/values-pt-rPT/strings-talkback-descriptions.xml b/java/res/values-pt-rPT/strings-talkback-descriptions.xml
index 30bbd3f..c3744ef 100644
--- a/java/res/values-pt-rPT/strings-talkback-descriptions.xml
+++ b/java/res/values-pt-rPT/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nenhum texto digitado"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> para <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> executa a correção automática"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nenhuma sugestão"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caráter desconhecido"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Mais símbolos"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiúsculo, ponto sobreposto"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconhecido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconhecido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Cara aborrecida"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Cara envergonhada"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Cara com óculos de sol"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Cara surpreendida"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Cara a dar um beijo"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Cara franzida"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Os carateres alternativos estão disponíveis"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Os carateres alternativos são ignorados"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"As sugestões alternativas estão disponíveis"</string>
diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml
index 4c7f486..a9f2be8 100644
--- a/java/res/values-pt-rPT/strings.xml
+++ b/java/res/values-pt-rPT/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao primir as teclas"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Som ao premir as teclas"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Mostrar popup ao premir tecla"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferências"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Contas e privacidade"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aspeto e esquemas"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escrita com gestos"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Correção de texto"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avançadas"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Ativar teclado dividido"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronização do Teclado Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"A sincronização está ativada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronizar o seu dicionário pessoal entre dispositivos"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizar agora"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Eliminar dados da nuvem"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Elimina os seus dados sincronizados do Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Os seus dados sincr. serão eliminados da nuvem. Tem a certeza?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Eliminar"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancelar"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"O seu dicionário pessoal será sincronizado e será criada uma cópia de segurança do mesmo nos servidores da Google. As informações estatísticas de frequência das palavras podem ser recolhidas para ajudar a melhorar os nossos produtos. A recolha e a utilização de todas as informações são efetuadas em conformidade com a "<a href="https://www.google.com/policies/privacy">"Política de Privacidade da Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Adicione uma Conta Google a este disp. para ativar esta func."</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Mudar p/ outros mét. ent."</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla de mudança de idioma abrange outros métodos de entrada"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla alterar idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostrar quando estão ativados vários idiomas de entrada"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador de deslize"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar pista visual ao deslizar das teclas Shift ou Símbolo"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Atraso p/ ignorar pop-up"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predefinido"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugestões de correcção"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Apresentar sugestões de palavras ao escrever"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar em modo retrato"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ocultar sempre"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palavras ofensivas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Não sugerir palavras potencialmente ofensivas"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correção automática"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Chave de entrada de voz"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nenhum método de entrada de texto por voz ativado. Verifique as definições de Idioma e introdução."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda e comentários"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toque aqui para guardar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Alternar entre contas"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nenhuma conta selecionada"</string>
+    <string name="account_selected" msgid="2846876462199625974">"A utilizar atualmente <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancelar"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Terminar sessão"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecionar uma conta a utilizar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Inglês (RU)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Inglês (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Espanhol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Sérvio (latim)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglês (RU) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglês (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanhol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sérvio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cirílico)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latim)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Sem idioma (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema do teclado"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos entrada pers."</string>
     <string name="add_style" msgid="6163126614514489951">"Adic. estilo"</string>
     <string name="add" msgid="8299699805688017798">"Adicionar"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Ativar"</string>
     <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Já existe o mesmo estilo de introdução: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Atraso ao manter tecla premida"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duração vibr. ao premir teclas"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume do som ao premir teclas"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ler ficheiro de dicionário externo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Não há ficheiros de dicionário na pasta Transferências"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um ficheiro de dicionário para instalar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Instalar mesmo este ficheiro para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Atraso ao manter tecla premida"</string>
     <string name="button_default" msgid="3988017840431881491">"Predefinido"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Bem-vindo(a) a <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"com a Escrita com Gestos"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Agora pode escrever em todas as suas aplicações favoritas com <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurar idiomas adicionais"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Concluído"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostrar ícone da aplicação"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostrar ícone da aplicação no iniciador"</string>
     <string name="app_name" msgid="6320102637491234792">"Fornecedor de Dicionário"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Fornecedor de Dicionário"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Serviço de Dicionário"</string>
diff --git a/java/res/values-pt/strings-talkback-descriptions.xml b/java/res/values-pt/strings-talkback-descriptions.xml
index f4e28fc..7500e6a 100644
--- a/java/res/values-pt/strings-talkback-descriptions.xml
+++ b/java/res/values-pt/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nenhum texto digitado"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corrige <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> para <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> realiza correção automática"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Sem sugestões"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caractere desconhecido"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Mais símbolos"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I maiúscula, ponto acima"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Símbolo desconhecido"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji desconhecido"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Rosto entediado"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Rosto envergonhado"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Rosto com óculos"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Rosto de surpresa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Rosto beijando"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Rosto franzido"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Caracteres alternativos estão disponíveis"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Caracteres alternativos foram descartados"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sugestões alternativas estão disponíveis"</string>
diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml
index c819ff3..589ca78 100644
--- a/java/res/values-pt/strings.xml
+++ b/java/res/values-pt/strings.xml
@@ -26,18 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrar ao tocar a tecla"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Som ao tocar a tecla"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Exibir pop-up ao digitar"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Preferências de entrada"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Aparência"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Opções multilíngues"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Pref. da entr. por gestos"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferências"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Contas e privacidade"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aparência e layouts"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Escrita com gestos"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"Correção de texto"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Avançadas"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Ativar teclado dividido"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronização Teclado do Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"A sincronização está ativada"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronizar seu dicionário pessoal nos dispositivos"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizar agora"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Excluir dados na nuvem"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Exclui seus dados sincronizados do Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Seus dados sincronizados serão excluídos da nuvem. Tem certeza?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Excluir"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Cancelar"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Seu dicionário pessoal será sincronizado, e será feito backup dele nos servidores do Google. As informações estatísticas de frequência de palavras podem ser coletadas para ajudar a melhorar nossos produtos. A coleta e o uso de todas as informações cumprirão a "<a href="https://www.google.com/policies/privacy">"Política de Privacidade do Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Adicione uma Conta do Google ao dispositivo para ativar recurso"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Outros métodos de entrada"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla p/ mudar o idioma também cobre outros métodos de entrada"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tecla de seleção de idioma"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Mostrar quando vários idiomas de entrada estiverem ativados"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Mostrar indicador de deslize"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Mostrar indicação visual ao deslizar teclas Shift ou de símbolos"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Duração de popup da tecla"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Sem atraso"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Padrão"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dicionário principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Mostrar sugestões de correção"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Exibir sugestões de palavras durante a digitação"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Mostrar sempre"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Mostrar em modo retrato"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Não mostrar"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Bloquear palavras ofensivas"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Não sugerir palavras potencialmente ofensivas"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Correção automática"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tecla p/ inserir texto por voz"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nenhum método de entrada de texto por voz ativado. Verifique as configurações \"Idioma e entrada\"."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Enviar comentários"</string>
-    <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Idiomas"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ajuda e feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Idiomas"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Toque aqui para salvar"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema do teclado"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Alternar contas"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nenhuma conta selecionada"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Atualmente usando <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Cancelar"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Sair"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selecionar uma conta para usar"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"inglês (Reino Unido)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"inglês (EUA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"espanhol (EUA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Híndi-inglês"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Sérvio (Latino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Inglês (Reino Unido) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Inglês (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Espanhol (EUA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Híndi-inglês (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sérvio (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirílico)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latino)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (compacto)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nenhum idioma (alfabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeto (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Tema do teclado"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Holo branco"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Holo azul"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Material escuro"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Material claro"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Estilos personalizados"</string>
     <string name="add_style" msgid="6163126614514489951">"Adic. estilo"</string>
     <string name="add" msgid="8299699805688017798">"Adicionar"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Ativar"</string>
     <string name="not_now" msgid="6172462888202790482">"Agora não"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"O estilo de entrada já existe: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Atraso ao pressionar teclas"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Duração da vibração ao tocar"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume ao tocar na tela"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Ler arquivo de dicionário externo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nenhum arquivo de dicionário na pasta Downloads"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selecione um arquivo de dicionário para instalar"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Deseja instalar este arquivo para <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Ocorreu um erro"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Atraso ao pressionar teclas"</string>
     <string name="button_default" msgid="3988017840431881491">"Padrão"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Bem-vindo ao <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"com entrada por gestos"</string>
@@ -140,11 +150,9 @@
     <string name="setup_step2_instruction" msgid="9141481964870023336">"Em seguida, selecione \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\" como o método de entrada de texto ativo."</string>
     <string name="setup_step2_action" msgid="1660330307159824337">"Alternar métodos de entrada"</string>
     <string name="setup_step3_title" msgid="3154757183631490281">"Parabéns, você terminou!"</string>
-    <string name="setup_step3_instruction" msgid="8025981829605426000">"Agora você pode digitar em todos os seus aplicativos favoritos com o <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
+    <string name="setup_step3_instruction" msgid="8025981829605426000">"Agora você pode digitar em todos os seus apps favoritos com o <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurar idiomas adicionais"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Concluído"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Mostrar ícone do aplicativo"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Mostrar ícone do aplicativo no iniciador"</string>
     <string name="app_name" msgid="6320102637491234792">"Provedor de dicionário"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Provedor de dicionário"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Serviço de dicionário"</string>
@@ -155,7 +163,7 @@
     <string name="user_dictionaries" msgid="3582332055892252845">"Dicionários do usuário"</string>
     <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Dicionário do usuário"</string>
     <string name="dictionary_available" msgid="4728975345815214218">"Dicionário disponível"</string>
-    <string name="dictionary_downloading" msgid="2982650524622620983">"Download em andamento"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Fazendo download..."</string>
     <string name="dictionary_installed" msgid="8081558343559342962">"Instalado"</string>
     <string name="dictionary_disabled" msgid="8950383219564621762">"Instalado, desativado"</string>
     <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Prob. conexão dic."</string>
@@ -175,7 +183,7 @@
     <string name="do_not_download_over_metered" msgid="2176209579313941583">"Fazer o download por Wi-Fi"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"Há um dicionário disponível para <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"Pressione para consultar e fazer o download"</string>
-    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Download em andamento: as sugestões para <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> estarão disponíveis em breve."</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Fazendo download...: as sugestões para <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> estarão disponíveis em breve."</string>
     <string name="version_text" msgid="2715354215568469385">"Versão <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
     <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Adicionar"</string>
     <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Adicionar ao dicionário"</string>
diff --git a/java/res/values-ro/strings-emoji-descriptions.xml b/java/res/values-ro/strings-emoji-descriptions.xml
index f44a0b9..2ac84e5 100644
--- a/java/res/values-ro/strings-emoji-descriptions.xml
+++ b/java/res/values-ro/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biscuit"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Ciocolată"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bomboane"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Acadea"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Budincă"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Oală de miere"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Prăjitură"</string>
diff --git a/java/res/values-ro/strings-talkback-descriptions.xml b/java/res/values-ro/strings-talkback-descriptions.xml
index 7a90162..7d2e49f 100644
--- a/java/res/values-ro/strings-talkback-descriptions.xml
+++ b/java/res/values-ro/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nu a fost introdus text"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> corectează <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> cu <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> efectuează corectare automată"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Nicio sugestie"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Caracter necunoscut"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Mai multe simboluri"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I mare, punct deasupra"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Simbol necunoscut"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji necunoscut"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Față plictisită"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Față jenată"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Față cu ochelari de soare"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Față surprinsă"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Față care sărută"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Față încruntată"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Sunt disponibile caractere alternative"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"S-au închis caracterele alternative"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Sunt disponibile sugestii alternative"</string>
diff --git a/java/res/values-ro/strings.xml b/java/res/values-ro/strings.xml
index 985a81e..ffcc68b 100644
--- a/java/res/values-ro/strings.xml
+++ b/java/res/values-ro/strings.xml
@@ -26,25 +26,36 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrare la apăsarea tastei"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Sunet la apăsarea tastei"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Pop-up la apăsarea tastei"</string>
-    <string name="settings_screen_input" msgid="2808654300248306866">"Preferințe pentru intrare"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"Aspect"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"Opțiuni pt. diverse limbi"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"Prefer. tastare gestuală"</string>
-    <string name="settings_screen_correction" msgid="1616818407747682955">"Corectare text"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Preferinţe"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Conturi și confidențialitate"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Aspect"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Tastare gestuală"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Corectarea textului"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"Setări avansate"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Temă"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Activați tastatura divizată"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sincronizare Tastatură Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sincronizarea este activată"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sincronizați dicționarul personal pe dispozitive"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sincronizați acum"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Ștergeți datele din cloud"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Șterge datele sincronizate de pe Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Datele sincronizate vor fi șterse din cloud. Sunteți sigur(ă)?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Ștergeți"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Anulați"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Dicționarul personal va fi sincronizat și i se va face backup pe serverele Google. Informațiile statistice privind frecvența cuvintelor pot fi culese pentru a îmbunătăți produsele noastre. Culegerea și folosirea informațiilor vor respecta "<a href="https://www.google.com/policies/privacy">"Politica de confidențialitate Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Pentru a activa funcția, adăugați un cont Google pe dispozitiv"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Comut. alte metode de introd."</string>
-    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasta de comutare între limbi include şi alte metode de introd."</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasta de comutare între limbi include și alte metode de introd."</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tastă comutare limbi"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Afişaţi când sunt activate mai multe limbi de intrare"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Afișați indicator glisare"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Afișați un indicator în timpul glisării de la Shift sau tasta de simboluri"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Închidere pop-up taste"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fără întârziere"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Prestabilit"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> msec."</string>
     <string name="settings_system_default" msgid="6268225104743331821">"Valoare prestabilită"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sugeraţi nume din Agendă"</string>
-    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaţi numele din Agendă pentru sugestii şi corecţii"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Utilizaţi numele din Agendă pentru sugestii și corecţii"</string>
     <string name="use_personalized_dicts" msgid="5167396352105467626">"Sugestii personalizate"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"Îmbunătățiți <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"Inserează punct spațiu"</string>
@@ -56,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Dicţionar principal"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Afişaţi sugestii de corectare"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Afişaţi sugestii de cuvinte în timpul introducerii textului"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Afişaţi întotdeauna"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Afişaţi în modul Portret"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ascundeţi întotdeauna"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blocați cuvintele jignitoare"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Nu se sugerează cuvinte potențial jignitoare"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autocorectare"</string>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tastă pentru intrarea vocală"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nicio metodă de intrare vocală activată. Verificați setările pentru limbă și introducere de text."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Trimiteți feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Limbi de introducere de text"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Limbi"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Ajutor și feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Limbi"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Atingeţi din nou pentru a salva"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Atingeți aici pentru a salva"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Temă pentru tastatură"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Comutați între conturi"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Niciun cont selectat"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Acum utilizați <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Anulați"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Deconectați-vă"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Selectați un cont de utilizat"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"engleză (Regatul Unit)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"engleză (S.U.A.)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spaniolă (S.U.A.)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Sârbă (caractere latine)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engleză (Regatul Unit) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engleză (S.U.A.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spaniolă (S.U.A.) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sârbă (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradițională)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Chirilică)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latină)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Nicio limbă (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"Temă pentru tastatură"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"Holo White"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"Holo Blue"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"Material Dark"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"Material Light"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Stiluri personalizate"</string>
     <string name="add_style" msgid="6163126614514489951">"Stil"</string>
     <string name="add" msgid="8299699805688017798">"Adăugaţi"</string>
@@ -118,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Activaţi"</string>
     <string name="not_now" msgid="6172462888202790482">"Nu acum"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Acelaşi stil de introducere există deja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Timpul apăsării lungi a tastei"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrare după apăsarea tastei"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Sunet la apăsarea tastelor"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Citiți fișierul de dicționar extern"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Nu există fișiere dicționar în dosarul Descărcări"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Selectați un fișier dicționar de instalat"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Doriți să instalați acest fișier pentru <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"A apărut o eroare"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Timpul apăsării lungi a tastei"</string>
     <string name="button_default" msgid="3988017840431881491">"Prestabilit"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Bun venit la <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"cu Tastarea gestuală"</string>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Acum, puteți introduce text în toate aplicațiile preferate, utilizând <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Configurați limbi suplimentare"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Finalizat"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Afișați pictograma aplicației"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Afișați pictograma aplicației în lansator"</string>
     <string name="app_name" msgid="6320102637491234792">"Furnizor dicționar"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Furnizor dicționar"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Serviciu dicționar"</string>
@@ -165,7 +173,7 @@
     <string name="message_updating" msgid="4457761393932375219">"Se verifică existența actualizărilor"</string>
     <string name="message_loading" msgid="5638680861387748936">"Se încarcă..."</string>
     <string name="main_dict_description" msgid="3072821352793492143">"Dicționar principal"</string>
-    <string name="cancel" msgid="6830980399865683324">"Anulaţi"</string>
+    <string name="cancel" msgid="6830980399865683324">"Anulați"</string>
     <string name="go_to_settings" msgid="3876892339342569259">"Setări"</string>
     <string name="install_dict" msgid="180852772562189365">"Instalați"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"Anulați"</string>
diff --git a/java/res/values-ru/strings-emoji-descriptions.xml b/java/res/values-ru/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..91fe95e
--- /dev/null
+++ b/java/res/values-ru/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Знак охраны авторского права."</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Символ охраны товарного знака."</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Два восклицательных знака."</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Восклицательный и вопросительный знаки."</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Символ торгового знака."</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Информация."</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Стрелка влево и вправо."</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Стрелка вверх и вниз."</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Стрелка северо-запад."</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Стрелка северо-восток."</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Стрелка юго-восток."</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Стрелка юго-запад."</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Стрелка влево с закруглением."</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Стрелка вправо с закруглением."</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Часы."</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Песочные часы."</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Два черных треугольника, указывающие вправо."</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Два черных треугольника, указывающие влево."</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Два черных треугольника, указывающие вверх."</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Два черных треугольника, указывающие вниз."</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Будильник."</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Песочные часы с сыплющимся песком."</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Заглавная буква М в круге."</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Маленький черный квадрат."</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Маленький белый квадрат."</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Черный треугольник, указывающий вправо."</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Черный треугольник, указывающий влево."</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Белый квадрат средних размеров."</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Черный квадрат средних размеров."</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Небольшой белый квадрат."</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Небольшой черный квадрат."</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Черное солнце с лучами."</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Облако."</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Черный телефон."</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Галочка в квадрате."</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Зонт и капли дождя."</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Горячий напиток."</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Белая рука с указательным пальцем вверх."</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Белый смайлик."</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Овен."</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Телец."</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Близнецы."</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Рак."</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Лев."</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Дева."</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Весы."</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Скорпион."</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Стрелец."</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Козерог."</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Водолей."</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Рыбы."</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Черные пики."</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Черные трефы."</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Черные червы."</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Черные бубны."</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Термальные источники."</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Черный универсальный знак повторной переработки."</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Инвалидная коляска."</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Якорь."</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Знак предупреждения."</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Знак высокого напряжения."</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Белый круг средних размеров."</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Черный круг средних размеров."</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Футбольный мяч."</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бейсбольный мяч."</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Снеговик."</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Солнце за облаком."</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Змееносец."</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Входа нет."</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Церковь."</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтан."</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Флаг в лунке."</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Парусник."</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Палатка."</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Бензоколонка."</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Черные ножницы."</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Жирная белая галочка."</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Самолет."</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Конверт."</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Поднятый кулак."</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Поднятая ладонь."</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Знак победы."</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Карандаш."</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Черное перо."</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Жирная галочка."</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Жирный знак умножения."</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Мерцание."</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Звездочка с восемью лучами."</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Черная звездочка с восемью лучами."</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Снежинка."</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Искра."</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Крест."</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Белый крест на черном фоне."</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Фигурный черный вопросительный знак."</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Фигурный белый вопросительный знак."</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Фигурный белый восклицательный знак."</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Жирный восклицательный знак."</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Черное сердце."</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Жирный знак плюса."</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Жирный знак минуса."</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Жирный знак деления."</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Черная стрелка вправо."</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Петля."</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Двойная петля."</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Стрелка, указывающая вправо, затем вверх."</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Стрелка, указывающая вправо, затем вниз."</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Черная стрелка влево."</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Черная стрелка вверх."</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Черная стрелка вниз."</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Большой черный квадрат."</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Большой белый квадрат."</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Белая звезда средних размеров."</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Большой жирный круг."</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Волнистое тире."</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Начало вокальной партии."</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Иероглиф поздравления, обведенный кругом."</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Иероглиф Секрет, обведенный кругом."</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Кость для маджонга Красный дракон."</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Игральная карта Черный джокер."</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Вторая группа крови."</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Третья группа крови."</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Первая группа крови."</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Автомобильная стоянка."</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Четвертая группа крови."</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Квадратный значок очистки."</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Квадратный значок Классно."</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Квадратный значок Бесплатно."</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Квадратный значок идентификатора."</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Квадратный значок Новый."</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Квадратный значок Нехорошо."</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Квадратный значок О\'кей."</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Квадратный значок СОС."</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Квадратный значок обновления с восклицательным знаком."</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Квадратный значок Против."</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Квадратный значок Здесь, катакана."</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Квадратный значок сервиса, катакана."</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Иероглиф отсутствия."</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Иероглиф забронированного места."</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Иероглиф Запрещено."</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Иероглиф Свободно."</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Иероглиф Принято."</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Иероглиф Заполнено."</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Иероглиф обладания."</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Иероглиф Ежемесячно."</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Иероглиф заявления."</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Иероглиф скидки."</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Иероглиф Открыто."</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Иероглиф выгодного предложения."</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Иероглиф Принять."</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ураган."</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Туман."</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Сложенный зонт."</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Звездная ночь."</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Восход солнца над горами."</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Восход."</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Городской пейзаж на закате."</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Закат над зданиями."</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Радуга."</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Ночной пейзаж с мостом."</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Волна."</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан."</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Млечный путь."</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Европа и Африка на глобусе."</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Америка на глобусе."</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Азия и Австралия на глобусе."</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Глобус с меридианами."</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Новолуние."</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Растущий полумесяц."</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Луна в первой четверти."</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Растущая луна."</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Полнолуние."</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Убывающая Луна."</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Луна в последней четверти."</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Убывающий полумесяц."</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Месяц."</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Новолуние с лицом."</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Луна в первой четверти с лицом."</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Луна в последней четверти с лицом."</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Полная луна с лицом."</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Солнце с лицом."</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Светящаяся звезда."</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Падающая звезда."</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Каштан."</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Росток."</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Хвойное дерево."</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Лиственное дерево."</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Пальма."</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус."</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Тюльпан."</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Цветок вишни."</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Роза."</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Гибискус."</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Подсолнечник."</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Цветок."</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Кукурузный початок."</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Колосья риса."</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Растение."</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Четырехлистный клевер."</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Кленовый лист."</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Опавший лист."</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Лист, кружащийся на ветру."</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Гриб."</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Помидор."</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Баклажан."</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Виноград."</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Дыня."</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Арбуз."</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарин."</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон."</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банан."</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас."</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Красное яблоко."</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Зеленое яблоко."</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Груша."</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Персик."</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Вишни."</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Клубника."</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Гамбургер."</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Кусок пиццы."</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Мясо на кости."</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Куриная ножка."</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Рисовое печенье."</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Рисовый шарик."</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Миска с рисом."</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Карри с рисом."</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Миска с лапшой."</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Спагетти."</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Хлеб."</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Картофель фри."</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Печеный батат."</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго."</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Одэн."</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши."</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Жареная креветка."</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Рыбная котлета со спиральным рисунком."</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Мягкое мороженое."</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Ледяная стружка."</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Мороженое."</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Пончик."</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Печенье."</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Шоколадная плитка."</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Конфета."</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Леденец."</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Заварной крем."</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Горшок с медом."</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Кусок торта."</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Упаковка бэнто."</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Еда в миске."</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Приготовление пищи."</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Вилка и нож."</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Чайная чашка без ручки."</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Бутылка саке и чашка."</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Бокал вина."</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Коктейль в бокале."</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропический коктейль."</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Пивная кружка."</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Чокающиеся пивные кружки."</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Детская бутылочка."</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Лента."</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Завернутый подарок."</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Торт на день рождения."</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Светильник-тыква."</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Наряженная елка."</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Санта-Клаус."</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Фейерверк."</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Бенгальский огонь."</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Воздушный шар."</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Хлопушка."</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Шар с конфетти."</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Танабата, ветка с тандзаку."</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Скрещенные флаги."</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Японское новогоднее украшение."</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Японские куклы."</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Вымпелы в виде карпов."</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Японский колокольчик фурин."</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Церемония созерцания луны."</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Школьный ранец."</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Шапочка выпускника."</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Карусель с лошадьми."</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Колесо обозрения."</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Американские горки."</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Удочка с пойманной рыбой."</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон."</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Кинокамера."</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кино."</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Наушники."</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Палитра."</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Цилиндр."</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Цирковой шатер."</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Билет."</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Нумератор с хлопушкой."</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Театральные маски."</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Видеоигра."</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Прямое попадание."</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Игровой автомат."</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Бильярд."</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Игровые кости."</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Боулинг."</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Ханафуда."</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музыкальная нота."</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Несколько музыкальных нот."</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон."</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гитара."</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Клавишный инструмент."</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Труба."</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Скрипка."</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Скрипичный ключ на нотном стане."</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Майка бегуна."</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Теннисная ракетка и мяч."</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Лыжа с ботинком."</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскетбольный мяч и кольцо."</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Клетчатый флаг."</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордист."</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Бегун."</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Серфер."</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Кубок."</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Конный спорт."</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Американский футбол."</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Регби."</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Пловец."</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Дом."</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Дом с садом."</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Офисное здание."</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Японский почтамт."</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Европейский почтамт."</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Больница."</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банк."</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат."</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Отель."</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Отель для встреч."</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Круглосуточный магазин."</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Школа."</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Супермаркет."</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Фабрика."</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Японский фонарь."</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Японский замок."</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Европейский замок."</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Крыса."</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Мышь."</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Бык."</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Буйвол."</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Корова."</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард."</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Кролик."</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Кошка."</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Дракон."</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил."</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит."</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Улитка."</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Змея."</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Лошадь."</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Баран."</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Коза."</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Овца."</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Обезьяна."</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Петух."</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Курица."</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Собака."</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Свинья."</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Кабан."</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Слон."</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Осьминог."</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Ракушка."</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Сороконожка."</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Муравей."</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Пчела."</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Божья коровка."</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Рыба."</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропическая рыбка."</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Иглобрюх."</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Черепаха."</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Вылупившийся цыпленок."</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Цыпленок."</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Цыпленок анфас."</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Птица."</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин."</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала."</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудель."</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Одногорбый верблюд."</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Двугорбый верблюд."</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Дельфин."</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Голова мыши."</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Голова коровы."</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Голова тигра."</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Голова кролика."</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Голова кошки."</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Голова дракона."</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Кит, пускающий фонтан."</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Голова лошади."</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Голова обезьяны."</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Голова собаки."</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Голова свиньи."</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Голова лягушки."</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Голова хомяка."</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Голова волка."</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Голова медведя."</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Голова панды."</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Свиной пятачок."</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Отпечатки лап."</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Глаза."</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ухо."</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Нос."</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Рот."</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Язык."</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Белая рука с указательным пальцем вверх с тыльной стороны."</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Белая рука с указательным пальцем вниз с тыльной стороны."</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Белая рука с указательным пальцем влево с тыльной стороны."</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Белая рука с указательным пальцем вправо с тыльной стороны."</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Кулак."</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Машущая раскрытая ладонь."</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Пальцы, сложенные знаком О\'кей."</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Большой палец вверх."</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Большой палец вниз."</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Аплодисменты."</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Раскрытые ладони."</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Корона."</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Женская шляпа."</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Очки."</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Галстук."</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Футболка."</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Джинсы."</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Платье."</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно."</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини."</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Блузка."</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Кошелек."</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Женская сумка."</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Чехол."</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Мужская туфля."</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Кроссовка."</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Туфля на каблуке."</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Женская сандалия."</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Женские сапоги."</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Отпечатки босых ног."</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Силуэт головы и плеч."</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Силуэты голов и плеч."</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Мальчик."</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Девочка."</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Мужчина."</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Женщина."</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Семья."</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Мужчина и женщина, держащиеся за руки."</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Двое мужчин, держащихся за руки."</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Две женщины, держащиеся за руки."</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полицейский."</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Женщина с кроличьими ушами."</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Невеста с фатой."</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Человек со светлыми волосами."</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Мужчина в традиционной китайской шапочке."</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Мужчина в тюрбане."</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Пожилой мужчина."</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Пожилая женщина."</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Младенец."</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Строитель."</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцесса."</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Японский демон они."</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Японский демон тэнгу."</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Привидение."</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Младенец ангел."</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Гуманоид."</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Инопланетный монстр."</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Имп."</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Череп."</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Сотрудник бюро информации."</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Часовой."</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Танцор."</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Помада."</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Лак для ногтей."</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Массаж лица."</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Стрижка."</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Указатель парикмахерской."</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц."</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Таблетка."</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Отпечаток губ."</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Любовное письмо."</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Кольцо."</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Драгоценный камень."</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Поцелуй."</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет."</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Влюбленная пара."</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Свадьба."</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Бьющееся сердце."</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Разбитое сердце."</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Два сердца."</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Мерцающее сердце."</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Трепещущее сердце."</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Сердце, пронзенное стрелой."</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Голубое сердце."</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Зеленое сердце."</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Желтое сердце."</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Фиолетовое сердце."</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Сердце с лентой."</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Вращающиеся сердца."</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Украшение в виде сердца."</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Ромб с точкой в центре."</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Горящая лампочка."</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Сердится."</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба."</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Сонный."</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Столкновение."</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Капли пота."</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Капля."</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Стремительное движение."</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Кучка экскрементов."</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Бицепс."</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Головокружение."</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Облачко реплики."</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Облачко мыслей."</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Белый цветок."</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Сто баллов."</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Мешок с деньгами."</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Обмен валюты."</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Широкий знак доллара."</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Кредитная карта."</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Банкнота со знаком иены."</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Купюра со знаком доллара."</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Банкнота со знаком евро."</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Банкнота со знаком фунта стерлингов."</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Пачка банкнот с крыльями."</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"График, идущий вверх, и знак иены."</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Кресло."</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Компьютер."</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Портфель."</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Мини-диск."</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета."</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптический диск."</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD."</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Папка."</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Открытая папка."</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Страница, скрученная снизу."</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Страница с загнутым углом."</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Календарь."</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Отрывной календарь."</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Картотека."</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"График, идущий вверх."</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"График, идущий вниз."</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Столбчатая диаграмма."</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Папка-планшет."</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Канцелярская кнопка."</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Канцелярская кнопка с круглой головкой."</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Скрепка."</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Линейка."</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Линейка треугольник."</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Закладки на страницах."</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Бухгалтерская книга."</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Блокнот."</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Блокнот с декоративной обложкой."</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Закрытая книга."</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Открытая книга."</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Зеленая книга."</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Синяя книга."</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Оранжевая книга."</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Книги."</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Нагрудная визитка."</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Свиток."</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Заметка."</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефонная трубка."</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пейджер."</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факсимильный аппарат."</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Спутниковая антенна."</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Громкоговоритель."</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ручной мегафон."</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Лоток для исходящей почты."</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Лоток для входящей почты."</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Посылка."</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Значок электронной почты."</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Входящее письмо."</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Конверт со стрелкой вниз над ним."</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Закрытый почтовый ящик с опущенным флажком."</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Закрытый почтовый ящик с поднятым флажком."</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Открытый почтовый ящик с поднятым флажком."</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Открытый почтовый ящик с опущенным флажком."</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Почтовый ящик."</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Рожок, значок почтовой службы."</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Газета."</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобильный телефон."</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Мобильный телефон со стрелкой, указывающей на него."</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Режим вибрации."</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Отключенный мобильный телефон."</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Запрет на использование мобильного телефона."</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Значок антенны с индикатором уровня сигнала."</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Фотоаппарат."</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Видеокамера."</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Телевизор."</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио."</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Видеокассета."</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Перекрещенные стрелки вправо."</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Круговые стрелки, указывающие по часовой."</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Круговые стрелки, указывающие по часовой, и цифра один поверх них."</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Круговые стрелки, указывающие вверх и вниз по часовой."</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Круговые стрелки, указывающие вверх и вниз против часовой."</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Значок уменьшения яркости."</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Значок увеличения яркости."</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Перечеркнутый динамик."</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Динамик."</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Динамик с одной линией звука."</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Динамик с тремя линиями звука."</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батарея."</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Штепсельная вилка."</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Увеличительное стекло, направленное влево."</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Увеличительное стекло, направленное вправо."</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Замок и перьевая ручка."</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Закрытый замок с ключом."</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ключ."</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Замок."</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Открытый замок."</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Колокольчик."</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Перечеркнутый колокольчик."</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Закладка."</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Значок ссылки."</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Переключатель."</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Надпись Назад и стрелка влево над ней."</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Надпись Конец и стрелка влево над ней."</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Надпись Включено с восклицательным знаком и стрелки, указывающие вправо и влево, над ней."</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Надпись Скоро и стрелка вправо над ней."</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Надпись Вверх и стрелка вверх над ней."</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Значок Только после восемнадцати лет."</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Клавиша десять."</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Значок ввода латинских заглавных букв."</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Значок ввода латинских строчных букв."</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Значок ввода цифр."</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Знак ввода символов."</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Значок ввода латинских букв."</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Огонь."</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Электрический фонарь."</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Гаечный ключ."</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Молоток."</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Гайка и болт."</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Нож."</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пистолет."</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп."</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп."</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Магический шар."</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Шестиконечная звезда с точкой в центре."</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Японский символ новичка."</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Трезубец."</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Черная квадратная кнопка."</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Белая квадратная кнопка."</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Большой красный круг."</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Большой синий круг."</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Большой оранжевый ромб."</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Большой синий ромб."</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Маленький оранжевый ромб."</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Маленький синий ромб."</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Красный треугольник вершиной вверх."</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Красный треугольник вершиной вниз."</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Маленький красный треугольник вершиной вверх."</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Маленький красный треугольник вершиной вниз."</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Один час на циферблате."</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Два часа на циферблате."</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Три часа на циферблате."</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Четыре часа на циферблате."</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Пять часов на циферблате."</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Шесть часов на циферблате."</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Семь часов на циферблате."</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Восемь часов на циферблате."</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Девять часов на циферблате."</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Десять часов на циферблате."</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Одиннадцать часов на циферблате."</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Двенадцать часов на циферблате."</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Полвторого на циферблате."</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Полтретьего на циферблате."</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Полчетвертого на циферблате."</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Полпятого на циферблате."</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Полшестого на циферблате."</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Полседьмого на циферблате."</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Полвосьмого на циферблате."</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Полдевятого на циферблате."</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Полдесятого на циферблате."</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Пол-одиннадцатого на циферблате."</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Полдвенадцатого на циферблате."</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Полпервого на циферблате."</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Гора Фудзи."</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токийская телебашня."</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Статуя Свободы."</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Очертания Японии."</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Моаи."</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Широкая улыбка."</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Широкая улыбка, глаза прищурены."</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Слезы радости."</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Улыбка, рот открыт."</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Улыбка, рот открыт, глаза прищурены."</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Открытая улыбка и испарина."</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Открытая улыбка, зажмуренные глаза."</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Улыбка, нимб над головой."</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Улыбающееся лицо, рога на голове."</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Подмигивание."</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Улыбка, глаза прищурены."</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Высунутый язык, один глаз прищурен."</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Облегчение."</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Улыбка, глаза в форме сердец."</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Улыбка, солнцезащитные очки."</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Самодовольная усмешка."</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Без эмоций."</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Лицо без выражения."</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Не впечатлен."</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Испарина."</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Глубокая печаль."</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Смущение."</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Готов расплакаться."</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Поцелуй."</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Воздушный поцелуй."</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Поцелуй, глаза прищурены."</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Поцелуй, глаза закрыты."</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Высунутый язык."</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Высунутый язык, подмигивание."</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Высунутый язык, зажмуренные глаза."</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Разочарование."</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Беспокойство."</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Сердитое лицо."</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Сердитое лицо с надутыми щеками."</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Плач."</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Упорство."</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Ликование."</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Разочарование, смешанное с чувством облегчения."</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Нахмуренное лицо, рот открыт."</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Страдающее лицо."</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Страх."</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Усталость."</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Сонное лицо."</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Утомление."</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Гримаса."</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Громкий плач."</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Открытый рот."</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Молчание."</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Открытый рот, испарина."</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Крик ужаса."</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Изумление."</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Смущение, красные щеки."</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Спящее лицо."</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Головокружение."</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Лицо безо рта."</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Лицо в медицинской маске."</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Улыбающийся кот с прищуренными глазами."</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Кот со слезами радости."</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Улыбающийся кот, рот открыт."</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Улыбающийся кот, глаза в форме сердец."</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Кот с кривой ухмылкой."</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Целующий кот, глаза закрыты."</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Сердитый кот с надутыми щеками."</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Плачущий кот."</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Усталый кот."</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Запрет."</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Разрешение."</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Низкий поклон."</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Обезьяна с закрытыми глазами."</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Обезьяна с закрытыми ушами."</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Обезьяна с закрытым ртом."</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Радость, одна рука поднята."</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Торжествующий человек с поднятыми руками."</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Огорчение."</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Сердитый человек."</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Сложенные руки."</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета."</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Вертолет."</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Паровоз."</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Вагон."</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Скоростной поезд."</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Скоростной поезд-пуля."</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Поезд."</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро."</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Электричка."</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станция."</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвай."</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Вагон трамвая."</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус."</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Приближающийся автобус."</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Троллейбус."</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобусная остановка."</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Микроавтобус."</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Скорая помощь."</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Пожарная машина."</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полицейская машина."</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Приближающаяся полицейская машина."</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси."</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Приближающееся такси."</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автомобиль."</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Приближающийся автомобиль."</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Жилой автофургон."</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Малотоннажный грузовик."</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Грузовик с прицепом."</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор."</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Монорельс."</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Горная железная дорога."</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Подвесная железная дорога."</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Горная канатная дорога."</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Фуникулер."</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Корабль."</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Лодка с веслами."</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Быстроходный катер."</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Горизонтальный светофор."</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Вертикальный светофор."</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Ограждение дорожных работ."</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Маячок полицейской машины."</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Треугольный флаг на шесте."</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Дверь."</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Знак Входа нет."</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Знак Курение разрешено."</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Знак Не курить."</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Знак мусорной корзины."</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Знак Не сорить."</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Знак Питьевая вода."</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Знак Непитьевая вода."</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед."</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Велосипедам проезд запрещен."</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Велосипедист."</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Горный велосипед."</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Пешеход."</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Знак Проход воспрещен."</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Дети, переходящие дорогу."</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Мужской туалет."</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Женский туалет."</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Туалет."</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Младенец."</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Туалет."</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Туалет."</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Душ."</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Ванная."</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Ванна."</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Паспортный контроль."</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Таможня."</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Выдача багажа."</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Камера хранения."</string>
+</resources>
diff --git a/java/res/values-ru/strings-talkback-descriptions.xml b/java/res/values-ru/strings-talkback-descriptions.xml
index b23d40d..43c5394 100644
--- a/java/res/values-ru/strings-talkback-descriptions.xml
+++ b/java/res/values-ru/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Текст не введен."</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"При нажатии клавиши <xliff:g id="KEY_NAME">%1$s</xliff:g> слово <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> будет исправлено на <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>."</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Клавиша <xliff:g id="KEY_NAME">%1$s</xliff:g> выполняет автоисправление."</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Подсказки не найдены"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Неизвестный символ."</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Клавиша верхнего регистра."</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Дополнительные символы."</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Заглавная латинская I с точкой сверху."</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Неизвестный символ."</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Неизвестный смайлик."</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Скука."</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Смущение."</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Солнцезащитные очки."</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Удивление."</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Поцелуй."</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Хмурый взгляд."</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступны дополнительные символы."</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Дополнительные символы скрыты."</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступны дополнительные подсказки."</string>
diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml
index cac1865..a064a45 100644
--- a/java/res/values-ru/strings.xml
+++ b/java/res/values-ru/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Виброотклик клавиш"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Звук клавиш"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Увеличение нажатых"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Настройки"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Аккаунты"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Вид и раскладки"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Непрерывный ввод"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Исправление текста"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Дополнительные настройки"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Включить разделенную клавиатуру"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Синхронизировать Клавиатуру"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхронизация включена"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Синхронизировать пользовательский словарь со всеми устройствами"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Синхронизировать"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Удалить данные с серверов Google"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Удаление синхронизированных данных из Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Синхронизированные данные будут удалены из облака. Продолжить?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Удалить"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Отменить"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Словарь будет сохраняться на серверах Google и синхронизироваться. Чтобы повысить качество наших сервисов, мы можем отслеживать статистику использования тех или иных слов. Вся информация обрабатывается в соответствии с "<a href="https://www.google.com/policies/privacy">"Политикой конфиденциальности"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Чтобы включить функцию, добавьте аккаунт Google на устройство"</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">"Клавиша переключения языков также служит для смены способа ввода"</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">"След от переключателя режима"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Показывать след при проведении пальцем от кнопок Shift и \"Символы\""</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Кнопка голосового ввода"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Голосовой способ ввода не включен. Проверьте раздел настроек \"Язык и ввод\"."</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="language_selection_title" msgid="3666971864764478269">"Выберите язык"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Справка/отзыв"</string>
+    <string name="select_language" msgid="5709487854987078367">"Язык"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Нажмите, чтобы сохранить"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Нажмите, чтобы сохранить"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавиатуры"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Сменить аккаунт"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Аккаунт не выбран"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Используется аккаунт <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ОК"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Отмена"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Выйти"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Выберите аккаунт"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"английский (Великобритания)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"английский (США)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Испанский (США)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хинглиш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Сербский (латиница)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Английский (Великобритания, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Английский (США, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Испанский (США, <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хинглиш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Сербский (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (классическая)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кириллица)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (компактная раскладка)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Язык не определен (латиница)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиница (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиница (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Латиница (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Латиница (ПК)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Эмодзи"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Тема клавиатуры"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Персонализированные стили"</string>
     <string name="add_style" msgid="6163126614514489951">"Добавить стиль"</string>
     <string name="add" msgid="8299699805688017798">"Добавить"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"Установить этот файл для следующего языка: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Ошибка"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Долгое нажатие"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Теперь вы можете использовать приложение \"<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">"Отображать значок приложения на панели запуска"</string>
     <string name="app_name" msgid="6320102637491234792">"Поставщик словарей"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Поставщик словарей"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Служба словарей"</string>
diff --git a/java/res/values-si-rLK/strings-emoji-descriptions.xml b/java/res/values-si-rLK/strings-emoji-descriptions.xml
index 14187a6..ae341dc 100644
--- a/java/res/values-si-rLK/strings-emoji-descriptions.xml
+++ b/java/res/values-si-rLK/strings-emoji-descriptions.xml
@@ -267,7 +267,7 @@
     <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"කුකීය"</string>
     <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"චොකලට් බාරය"</string>
     <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"පැණිරස"</string>
-    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"ලොලිපොප්"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
     <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"කස්ටට්"</string>
     <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"මී පැණි මුට්ටිය"</string>
     <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ෂොට් කේක්"</string>
diff --git a/java/res/values-si-rLK/strings-talkback-descriptions.xml b/java/res/values-si-rLK/strings-talkback-descriptions.xml
index 85cb5f6..25398e4 100644
--- a/java/res/values-si-rLK/strings-talkback-descriptions.xml
+++ b/java/res/values-si-rLK/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"පෙළ ඇතුළු කර නැත"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> සිට <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> වෙත නිවැරදි කරයි"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ස්වයං-නිවැරදි කිරීම සිදු කරයි"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"යෝජනා නොමැත"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"නොදන්නා අකුර"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"ෂිෆ්ට්"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"තව සංකේත"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"ලොකු I, ඉහළින් තිත"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"නොදන්නා සංකේතය"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"නොදන්නා ඉමොජි"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"කම්මැලි මුහුණ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"අපහසුවට පත් කළ මුහුණ"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"අව් කණ්නාඩි පැළදි මුහුණ"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"පුදුමයට පත් වුණු මුහුණ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"සිපගන්නා මුහුණ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"රවන මුහුණ"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"විකල්ප අකුරු තිබේ"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"විකල්ප අකුරු අස් කරන ලදි"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"විකල්ප යෝජනා තිබේ"</string>
diff --git a/java/res/values-si-rLK/strings.xml b/java/res/values-si-rLK/strings.xml
index e4e0b8e..0d51439 100644
--- a/java/res/values-si-rLK/strings.xml
+++ b/java/res/values-si-rLK/strings.xml
@@ -26,18 +26,29 @@
     <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="settings_screen_input" msgid="2808654300248306866">"ආදාන මනාපය"</string>
-    <string name="settings_screen_appearances" msgid="3611951947835553700">"පෙනුම"</string>
-    <string name="settings_screen_multi_lingual" msgid="6829970893413937235">"බහු මූර්ධජ අක්ෂර විකල්ප"</string>
-    <string name="settings_screen_gesture" msgid="9113437621722871665">"ඉංගිතයෙන් ටයිප් කිරීමේ මනාපය"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"අභිරුචි"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"ගිණුම් සහ රහස්‍යතාව"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"පෙනුම සහ පිරිසැලසුම්"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"ඉංගිත ටයිප් කිරීම"</string>
     <string name="settings_screen_correction" msgid="1616818407747682955">"පෙළ නිවැරදි කිරීම"</string>
     <string name="settings_screen_advanced" msgid="7472408607625972994">"උසස්"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"තේමාව"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"බෙදු යතුරු පුවරුව සබල කරන්න"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google යතුරු පුවරුව සමමුහුර්ත කිරීම"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"සමමුහුර්ත කිරීම් ක්‍රියාත්මකයි"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ඔබේ පෞද්ගලික ශබ්දකෝෂය ඔබේ උපකරණ සමඟ සමමුහුර්ත කරන්න"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"දැන් සමමුහුර්ත කරන්න"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"වලාකුළු දත්ත මකන්න"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"ඔබගේ සමමුහුර්ත කළ දත්ත Google වෙතින් මකා දමයි"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ඔබගේ සමමුහුර්ත දත්ත සියල්ල ක්ලවුඩ් එකෙන් ඉවත් කරනු ඇත. ඔබට විශ්වාසද?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"මකන්න"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"අවලංගු කරන්න"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"ඔබගේ පෞද්ගලික ශබ්දකෝෂය Google සේවාදායකයන් වෙත සමමුහුර්ත කර උපස්ථය කෙරෙනු ඇත. අපගේ නිෂ්පාදන වැඩි දියුණු කිරීමට උදවු වනු පිණිස වචන භාවිතා වන වාර ගණන පිළිබඳ සංඛ්‍යාත්මක තොරතුරු සමුච්චය කිරීමට ඉඩ ඇත. සියලු දත්ත සමුච්චය කිරීම සහ භාවිතා කිරීම "<a href="https://www.google.com/policies/privacy">"Google හි රහස්‍යතා ප්‍රතිපත්තිය"</a>"අනුව සිදු කරනු ඇත."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"මෙම විශේෂාංගය සබල කිරීමට කරුණාකර Google ගිණුමක් එක් කරන්න"</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">"භාෂා මාරු යතුර වෙනත් ආදාන ක්‍රමද ආවරණය කරයි"</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">"සර්පණ දර්ශකය පෙන්වන්න"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"ෂිෆ්ට් හෝ සංකේත යතුරු වෙතින් සර්පණය කරන අතරතුර දෘෂ්‍ය ඉඟි දර්ශනය කරන්න"</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>
@@ -56,9 +67,6 @@
     <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>
@@ -79,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"හඬ ආදාන යතුර"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"හඬ ආදාන සබල කර නැත. භාෂාව සහ ආදාන සැකසීම් පරීක්ෂා කරන්න."</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="language_selection_title" msgid="3666971864764478269">"භාෂා"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"උදවු සහ ප්‍රතිපෝෂණ"</string>
+    <string name="select_language" msgid="5709487854987078367">"භාෂා"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"සුරැකීමට නැවත ස්පර්ශ කරන්න"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"සුරැකීමට මෙතැන ස්පර්ෂ කරන්න"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"ශබ්ද කෝෂය ලබාගත හැක"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"යතුරු පුවරු තේමාව"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ගිණුම් මාරු කරන්න"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ගිණුම් තෝරා නැත"</string>
+    <string name="account_selected" msgid="2846876462199625974">"<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> දැනට භාවිතා කරමින්"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"හරි"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"අවලංගු කරන්න"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"වරනය වන්න"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"භාවිතා කිරීමට ගිණුමක් තෝරන්න"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ඉංග්‍රීසි (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ඉංග්‍රීසි (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ස්පාඤ්ඤ (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"හින්ග්ලිෂ්"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"සර්බියානු (ලතින්)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ඉංග්‍රීසි (එ.රා) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ඉංග්‍රීසි (එ.ජ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ස්පාඤ්ඤ (එ.ජ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"හින්ග්ලිෂ් (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"සර්බියානු (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සාම්ප්‍රදායික)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සිරිලික්)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ලතින්)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (සංයුක්ත)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"භාෂාවක් නැත (අකාරාදිය)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"අකාරාදිය (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"අකාරාදිය (QWERTZ)"</string>
@@ -103,10 +122,6 @@
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"අකාරාදිය (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ඉමොජි"</string>
     <string name="keyboard_theme" msgid="4909551808526178852">"යතුරු පුවරු තේමාව"</string>
-    <string name="keyboard_theme_holo_white" msgid="8506588144096428751">"හොලෝ සුදු"</string>
-    <string name="keyboard_theme_holo_blue" msgid="192400518003397418">"හොලෝ නිල්"</string>
-    <string name="keyboard_theme_material_dark" msgid="2701178578784760596">"ද්‍රව්‍යමය අඳුරු"</string>
-    <string name="keyboard_theme_material_light" msgid="3479400901818790331">"ද්‍රව්‍යමය ළා"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"අභිරුචි ආදාන විලාස"</string>
     <string name="add_style" msgid="6163126614514489951">"විලාසය එක් කරන්න"</string>
     <string name="add" msgid="8299699805688017798">"එක් කරන්න"</string>
@@ -118,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> සඳහා ඇත්තටම මෙම ගොනුව ස්ථාපනය කරන්නද?"</string>
-    <string name="error" msgid="8940763624668513648">"දෝෂයක් ඇති විය"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"යතුරු දිගු එබීම් ප්‍රමාදය"</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>
@@ -143,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"දැන් ඔබට <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">"දියත්කරනය තුළ යෙදුම් නිරූපකය දර්ශනය කරන්න"</string>
     <string name="app_name" msgid="6320102637491234792">"ශබ්දකෝෂ සැපයුම්කරු"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ශබ්දකෝෂ සැපයුම්කරු"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"ශබ්ද කෝෂ සේවාව"</string>
diff --git a/java/res/values-sk/strings-emoji-descriptions.xml b/java/res/values-sk/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..094403b
--- /dev/null
+++ b/java/res/values-sk/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Znak copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Znak registrovanej ochrannej známky"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dvojitý výkričník"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Výkričník s otáznikom"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Znak ochrannej známky"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Zdroj informácií"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Dvojsmerná šípka doľava a doprava"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Dvojsmerná šípka nahor a nadol"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Šípka na severozápad"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Šípka na severovýchod"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Šípka na juhovýchod"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Šípka na juhozápad"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Šípka doľava s hákom"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Šípka doprava s hákom"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Náramkové hodinky"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Presýpacie hodiny"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Čierny dvojitý trojuholník smerujúci doprava"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Čierny dvojitý trojuholník smerujúci doľava"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Čierny dvojitý trojuholník smerujúci nahor"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Čierny dvojitý trojuholník smerujúci nadol"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Budík"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Presýpacie hodiny s pieskom"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Zakrúžkované veľké písmeno M v latinke"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Malý čierny štvorec"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Malý biely štvorec"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Čierny trojuholník smerujúci doprava"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Čierny trojuholník smerujúci doľava"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Stredný biely štvorec"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Stredný čierny štvorec"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Biely stredne malý štvorec"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Čierny stredne malý štvorec"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Čierne slnko s lúčmi"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Oblak"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Čierny telefón"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Začiarknuté políčko"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Dáždnik s dažďovými kvapkami"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Horúci nápoj"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Biely ukazovák ukazujúci smerom nahor"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Biela usmievajúca sa tvár"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Baran"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Býk"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Blíženci"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rak"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lev"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Panna"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Váhy"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Škorpión"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Strelec"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Kozorožec"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vodnár"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ryby"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Čierna pika"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Čierny kríž"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Čierne srdce"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Čierny kosoštvorec"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Horúce pramene"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Čierny univerzálny symbol recyklácie"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Symbol invalidného vozíka"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Kotva"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Výstražná značka"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Značka vysokého napätia"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Stredný biely kruh"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Stredný čierny kruh"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futbalová lopta"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bejzbalová loptička"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snehuliak bez snehu"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Slnko za oblakom"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Hadonos"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Zákaz vstupu"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kostol"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontána"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Vlajka v jamke"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Plachetnica"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Stan"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Čerpacia stanica"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Čierne nožnice"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Biely tučný znak začiarknutia"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Lietadlo"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Obálka"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Zdvihnutá päsť"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Zdvihnutá ruka"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Ruka s víťazným gestom"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Ceruzka"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Čierny hrot pera"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Tučný znak začiarknutia"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Tučný znak násobenia x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Iskry"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Hviezdička s ôsmymi ramenami"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Čierna hviezda s ôsmymi cípmi"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snehová vločka"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Iskra"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Krížik"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negatív krížika v štvorci"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Ozdoba s čiernym otáznikom"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ozdoba s bielym otáznikom"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ozdoba s bielym výkričníkom"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Symbol tučného výkričníka"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Čierne srdce"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Tučné znamienko plus"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Tučné znamienko mínus"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Tučné znamienko delenia"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Čierna šípka doprava"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Vlnitá slučka"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dvojitá vlnitá slučka"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Šípka doprava s následným zatočením nahor"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Šípka doprava s následným zatočením nadol"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Čierna šípka doľava"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Čierna šípka nahor"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Čierna šípka nadol"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Veľký čierny štvorec"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Veľký biely štvorec"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Biela stredná hviezda"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Tučný veľký kruh"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Vlnovka"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Znak zmeny časti"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Zakrúžkovaný ideogram gratulácie"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Zakrúžkovaný ideogram tajomstva"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Kameň hry Mahjong – červený drak"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Hracia karta – čierny žolík"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Krvná skupina A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Krvná skupina B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Krvná skupina 0"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkovisko"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Krvná skupina AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Štvorcový znak CL (vymazať)"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Štvorcový znak Cool (super)"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Štvorcový znak Free (zadarmo)"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Štvorcový znak ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Štvorcový znak New (nové)"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Štvorcový znak N G (nejde to)"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Štvorcový znak OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Štvorcový znak SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Štvorcový znak UP (hore) s výkričníkom"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Štvorcový znak VS (verzus)"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Štvorcový znak katakany – tu"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Štvorcový znak katakany – služba"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Štvorcový ideogram – bez poplatku"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Štvorcový ideogram – rezervované miesto"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Štvorcový ideogram – zákaz"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Štvorcový ideogram – voľná izba"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Štvorcový ideogram – akceptovanie"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Štvorcový ideogram – úplne obsadené"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Štvorcový ideogram – zaplatené"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Štvorcový ideogram – mesačné"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Štvorcový ideogram – žiadosť"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Štvorcový ideogram – zľava"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Štvorcový ideogram – v prevádzke"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Kruhový ideogram – výhoda"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Kruhový ideogram – prijať"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyklón"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Hmla"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Zložený dáždnik"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Noc s hviezdami"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Východ slnka nad horami"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Východ slnka"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Panoráma mesta pri stmievaní"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Západ slnka nad budovami"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Dúha"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Most v noci"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vodná vlna"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Sopka"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Mliečna dráha"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Zemeguľa – Európa a Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Zemeguľa – Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Zemeguľa – Ázia a Austrália"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Zemeguľa s poludníkmi"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbol novy mesiaca"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbol dorastajúceho kosáčika mesiaca"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbol prvej štvrte mesiaca"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbol druhej štvrte mesiaca"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbol splnu mesiaca"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbol tretej štvrte mesiaca"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbol poslednej štvrte mesiaca"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbol ubúdajúceho kosáčika mesiaca"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Dorastajúci mesiac"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nov mesiaca s tvárou"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Prvá štvrť mesiaca s tvárou"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Posledná štvrť mesiaca s tvárou"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Spln s tvárou"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Slnko s tvárou"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Žiarivá hviezda"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Padajúca hviezda"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Gaštan"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Sadenica"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Ihličnatý strom"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Strom s každoročným opadávaním lístia"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipán"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Čerešňový kvet"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Ruža"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Ibištek"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Slnečnica"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Kvet"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Kukuričný klas"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Ryžový klas"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Bylinka"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Štvorlístok"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Javorový list"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Spadnutý list"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Padajúci list vo vetre"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Hríb"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Paradajka"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Baklažán"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Hrozno"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Dyňa"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Červený melón"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarínka"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citrón"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banán"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananás"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Červené jablko"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zelené jablko"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Hruška"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Broskyňa"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Čerešne"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jahoda"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Kúsok pizze"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Mäso na kosti"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Hydinové stehno"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Ryžový kreker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Ryžová guľka"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Varená ryža"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Kari a ryža"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Rezancová polievka"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Špagety"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Chlieb"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Hranolčeky"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pečený sladký zemiak"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Pražená kreveta"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Vírový rybací koláč"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Točená zmrzlina"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Havajská zmrzlina"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Zmrzlina"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Šiška"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Keks"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Čokoládová tyčinka"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Cukrík"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lízatko"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vaječný krém"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Nádoba s medom"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Koláč s čerstvým ovocím"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Obedový balík Bentó"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Nádoba s jedlom"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Varenie"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Vidlička a nôž"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Čajový hrnček bez uška"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Šálka a fľaša so Saké"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vínový pohár"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Koktejlový pohár"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropický nápoj"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Pivový pohár"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Štrngajúce pivové poháre"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Detská fľaša"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Stuha"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Zabalený darček"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Narodeninová torta"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Tekvicový lampáš so sviečkou"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Vianočný stromček"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Dedo Mráz"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Ohňostroj"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Prskavka"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balón"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfety"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Guľa s konfetami"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Strom Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Prekrížené vlajky"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Okrasa z čečiny"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japonské bábiky"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Japonské šarkany"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Veterný gong"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Ceremónia sledovania splnu"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Školská aktovka"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Promočný klobúk"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Kolotočový koník"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ruské koleso"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Horská dráha"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Udica a ryba"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofón"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmová kamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Slúchadlá"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Maliarska paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cylinder"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkusový stan"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Lístok"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klapka"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Múzické umenie"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videohra"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Priamy zásah"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Herný automat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Hracia kocka"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Hracie karty s kvetmi"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Hudobná nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Hudobné noty"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofón"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Hudobné klávesy"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trúbka"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Husle"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Hudobný zápis"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Bežecké tričko so šerpou"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tenisová raketa a loptička"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Lyža s lyžiarkou"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbalová lopta a kôš"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Cieľová vlajka"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snoubordista"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Bežec"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfista"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Víťazný pohár"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Konské dostihy"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Americký futbal"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragby"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Plavec"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Stavanie domov"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Dom so záhradou"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Administratívna budova"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japonská pošta"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Európska pošta"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Nemocnica"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel lásky"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Obchod so zmiešaným tovarom"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Škola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Obchodný dom"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Továreň"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Lampáš Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japonský hrad"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Európsky hrad"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Potkan"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Myš"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Vôl"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Byvol vodný"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Krava"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Králik"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Mačka"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drak"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodíl"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Veľryba"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Slimák"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Had"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Kôň"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Cap"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Koza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovca"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Opica"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Kohút"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kurča"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Pes"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Prasa"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Diviak"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Slon"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Chobotnica"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Špirálová ulita"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Chrobák"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mravec"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Včela medonosná"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Lienka"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Ryba"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropická ryba"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Štvorzubec"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Korytnačka"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Liahnuce sa kuriatko"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kuriatko"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kuriatko z prednej strany"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Vták"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Tučniak"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudlík"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedár"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Ťava dvojhrbá"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfín"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Tvár myši"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Tvár kravy"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tvár tigra"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Tvár králika"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Tvár mačky"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Tvár draka"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Striekajúca veľryba"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Tvár koňa"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Tvár opice"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Tvár psa"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Tvár prasaťa"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Tvár žaby"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Tvár škrečka"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Tvár vlka"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Tvár medveďa"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Tvár pandy"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Nos prasaťa"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Stopy prasaťa"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oči"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Ucho"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nos"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ústa"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Jazyk"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Nahor ukazujúci biely ukazovák z pohľadu zadnej strany ruky"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Nadol ukazujúci biely ukazovák z pohľadu zadnej strany ruky"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Doľava ukazujúci biely ukazovák z pohľadu zadnej strany ruky"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Doprava ukazujúci biely ukazovák z pohľadu zadnej strany ruky"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Znak zovretej päste"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Znak mávajúcej ruky"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Znak gesta OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Znak gesta palec hore"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Znak gesta palec dole"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Znak tlieskajúcich rúk"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Znak otvorených rúk"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Koruna"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Dámsky klobúk"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Okuliare"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kravata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Tričko"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Rifle"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Šaty"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Dámske oblečenie"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Dámska peňaženka"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Kabelka"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Kapsička"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Pánska topánka"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Atletická topánka"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Topánka na vysokom podpätku"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Dámsky sandál"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Dámske čižmy"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Stopy"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silueta busty"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Siluety búst"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Chlapec"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Dievča"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Muž"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Žena"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Rodina"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Muž a žena držiaci sa za ruky"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dvaja muži držiaci sa za ruky"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dve ženy držiace sa za ruky"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policajt"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Žena so zajačími ušami"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Nevesta so závojom"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Osoba s blond vlasmi"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Muž s pokrývkou hlavy Gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Muž s turbanom"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Starší muž"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Staršia žena"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bábätko"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Stavbár"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princezná"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japonský obor"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japonský škriatok"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Duch"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Anjelik"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Mimozemšťan"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Mimozemská príšera"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Čertík"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Lebka"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Informátor"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Strážnik"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Tanečník"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rúž"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Lak na nechty"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Masáž tváre"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Účes"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Značka holičstva"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Striekačka"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilulka"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Odtlačok bozku"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Ľúbostný list"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Prsteň"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Drahokam"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bozk"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Kytica"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Pár so srdcom"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Svadba"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Bijúce srdce"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Zlomené srdce"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dve srdcia"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Trblietajúce sa srdce"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Rastúce srdce"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Srdce so šípom"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Modré srdce"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zelené srdce"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Žlté srdce"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Fialové srdce"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Srdce so stuhou"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Otáčajúce sa srdcia"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Ozdoba so srdcom"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Diamantový tvar s bodkou uprostred"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Elektrická žiarovka"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbol hnevu"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbol spánku"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbol kolízie"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Kvapky potu"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Kvapka"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbol rýchleho behu"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kôpka stolice"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Flektovaný biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbol závratu"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bublina s rečou"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bublina s myšlienkou"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Biely kvet"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Symbol 100 bodov"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Vrece s peniazmi"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Prevod mien"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Zvýraznený znak dolára"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditná karta"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bankovka so znakom jenu"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Dolárová bankovka"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bankovka so znakom eura"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bankovka so znakom britskej libry"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Peniaze s krídlami"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Graf so vzostupujúcim trendom a znakom jenu"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sedadlo"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Osobný počítač"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Kufrík"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketa"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optický disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Priečinok so súbormi"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Otvorený priečinok so súbormi"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Strana so skrúteným okrajom"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Strana otočená nahor"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendár"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Trhací kalendár"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Otočný vizitkár"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Graf so vzostupujúcim trendom"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Graf so zostupujúcim trendom"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Stĺpcový graf"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Podložka na písanie s klipom"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pripináčik"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Guľatý pripináčik"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Papierová sponka"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Rovné pravítko"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Trojuholníkové pravítko"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Záložkové karty"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Účtovná kniha"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Zápisník"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Zápisník s okrasným obalom"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Zavretá kniha"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Otvorená kniha"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zelená kniha"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Modrá kniha"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranžová kniha"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Knihy"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Menovka"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Zvitok"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Oznam"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefónne slúchadlo"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelitná anténa"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Reproduktor verejného rozhlasu"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafón na povzbudzovanie"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Priehradka na odchádzajúcu poštu"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Priehradka na doručenú poštu"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Balík"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Symbol e-mailu"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Prichádzajúca obálka"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Obálka so šípkou smerujúcou nadol umiestnenou nad obálkou"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Zavretá poštová schránka so spustenou vlajkou"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Zavretá poštová schránka so zdvihnutou vlajkou"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Otvorená poštová schránka so zdvihnutou vlajkou"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Otvorená poštová schránka so spustenou vlajkou"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Poštová schránka"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Poštový lesný roh"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Noviny"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobilný telefón"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobilný telefón so šípkou smerujúcou doprava umiestnenou vľavo od telefónu"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Režim vibrovania"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Vypnutý mobilný telefón"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Zákaz mobilných telefónov"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Anténa s indikátorom sily signálu"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoaparát"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televízor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Rádio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokazeta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Pokrivené šípky doprava"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Doprava a doľava smerujúce šípky v otvorenom kruhu v smere hodinových ručičiek"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Doprava a doľava smerujúce šípky v otvorenom kruhu s prekrytím zakrúžkovanej jednotky"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Nadol a nahor smerujúce šípky v otvorenom kruhu v smere hodinových ručičiek"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Nadol a nahor smerujúce šípky v otvorenom kruhu proti smeru hodinových ručičiek"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol nízkeho jasu"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol vysokého jasu"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Preškrtnutý symbol reproduktora"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Reproduktor"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Reproduktor s jednou zvukovou vlnou"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Reproduktor s troma zvukovými vlnami"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batéria"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektrická zásuvka"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa naklonená doľava"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa naklonená doprava"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Zámka s atramentovým perom"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Zavretá zámka s kľúčom"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Kľúč"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Zámka"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Otvorená zámka"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zvonček"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Preškrtnutý symbol zvončeka"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Záložka"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Symbol odkazu"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Prepínač"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Nápis Back so šípkou doľava umiestnenou nad nápisom"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Nápis End so šípkou doľava umiestnenou nad nápisom"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Nápis On s výkričníkom s obojsmernou šípkou umiestnenou nad nápisom"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Nápis Soon so šípkou doprava umiestnenou nad nápisom"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Nápis Top so šípkou nahor umiestnenou nad nápisom"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbol zákazu osobám mladším ako 18 rokov"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Kláves s číslom 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Symbol vstupu pre veľké písmená v latinke"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Symbol vstupu pre malé písmená v latinke"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Symbol vstupu pre čísla"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Symbol vstupu pre symboly"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Symbol vstupu pre písmená v latinke"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Oheň"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elektrický lampáš"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Kľúč"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Kladivo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Skrutka s maticou"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Japonský nôž"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pištoľ"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Krištáľová guľa"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Šesťcípa hviezda s bodkou uprostred"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japonský symbol pre začiatočníka"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblém s trojzubcom"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Čierne štvorcové tlačidlo"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Biele štvorcové tlačidlo"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Veľký červený kruh"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Veľký modrý kruh"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Veľký oranžový diamant"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Veľký modrý diamant"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Malý oranžový diamant"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Malý modrý diamant"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Červený trojuholník smerujúci nahor"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Červený trojuholník smerujúci nadol"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Malý červený trojuholník smerujúci nahor"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Malý červený trojuholník smerujúci nadol"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Hodiny ukazujúce jednu hodinu"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Hodiny ukazujúce dve hodiny"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Hodiny ukazujúce tri hodiny"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Hodiny ukazujúce štyri hodiny"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Hodiny ukazujúce päť hodín"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Hodiny ukazujúce šesť hodín"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Hodiny ukazujúce sedem hodín"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Hodiny ukazujúce osem hodín"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Hodiny ukazujúce deväť hodín"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Hodiny ukazujúce desať hodín"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Hodiny ukazujúce jedenásť hodín"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Hodiny ukazujúce dvanásť hodín"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Hodiny ukazujúce pol druhej"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Hodiny ukazujúce pol tretej"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Hodiny ukazujúce pol štvrtej"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Hodiny ukazujúce pol piatej"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Hodiny ukazujúce pol šiestej"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Hodiny ukazujúce pol siedmej"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Hodiny ukazujúce pol ôsmej"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Hodiny ukazujúce pol deviatej"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Hodiny ukazujúce pol desiatej"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Hodiny ukazujúce pol jedenástej"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Hodiny ukazujúce pol dvanástej"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Hodiny ukazujúce pol jednej"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Hora Fudži"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokijská veža"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Socha slobody"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silueta Japonska"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Tvár s úškrnom"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Tvár s úškľabom a smejúcimi sa očami"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Tvár so slzami šťastia"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Usmievajúca sa tvár s otvorenými ústami"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Usmievajúca sa tvár s otvorenými ústami a usmiatymi očami"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Usmievajúca sa tvár s otvorenými ústami a studeným potom"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Usmievajúca sa tvár s otvorenými ústami a pevne zavretými očami"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Usmievajúca sa tvár so svätožiarou"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Usmievajúca sa tvár s rohmi"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Žmurkajúca tvár"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Usmievajúca sa tvár s usmiatymi očami"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Tvár pochutnávajúca si na lahodnom jedle"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Uvoľnená tvár"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Usmievajúca sa tvár so srdiečkovými očami"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Usmievajúca sa tvár so slnečnými okuliarmi"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Škeriaca sa tvár"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutrálna tvár"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Tvár bez výrazu"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Nudná tvár"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Tvár so studeným potom"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Zamyslená tvár"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zmätená tvár"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Čertovská tvár"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Bozkávajúca sa tvár"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Tvár posielajúca bozk"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Bozkávajúca tvár s usmiatymi očami"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Bozkávajúca tvár so zavretými očami"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Tvár s vyplazeným jazykom"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Tvár s vyplazeným jazykom a prižmúreným okom"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Tvár s vyplazeným jazykom a pevne zavretými očami"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Sklamaná tvár"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Znepokojená tvár"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Nahnevaná tvár"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Tvár s našpúleným výrazom"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Plačúca tvár"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Urputná tvár"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Tvár z výrazom víťazstva"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Sklamaná, ale uvoľnená tvár"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Zamračená tvár s otvorenými ústami"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Úzkostná tvár"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Ustrašená tvár"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Ustatá tvár"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Ospalá tvár"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Unavená tvár"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Tvár s grimasou"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Jačiaca tvár"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Tvár s otvorenými ústami"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Utíšená tvár"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Tvár s otvorenými ústami a studeným potom"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Tvár jačiaca od strachu"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Udivená tvár"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Začervenaná tvár"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Spiaca tvár"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Tvár so závratom"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Tvár bez úst"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Tvár s lekárskou maskou"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Tvár mačky s úškľabom a smejúcimi sa očami"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Tvár mačky so slzami šťastia"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Usmievajúca sa tvár mačky s otvorenými ústami"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Usmievajúca sa tvár mačky so srdiečkovými očami"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Tvár mačky s krivým úsmevom"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Bozkávajúca tvár mačky so zavretými očami"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Tvár mačky s našpúleným výrazom"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Plačúca tvár mačky"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Ustatá tvár mačky"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Tvár s gestom Nie"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Tvár s gestom OK"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Hlboko sa klaňajúca osoba"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Opica zakrývajúca si oči pred zlom"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Opica zakrývajúca si uši pred zlom"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Opica zakrývajúca si oči pred zlom"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Šťastná osoba zdvíhajúca jednu ruku"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Oslavujúca osoba so zdvihnutými rukami"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Zamračená osoba"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Osoba s našpúleným výrazom"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Osoba so zloženými rukami"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikoptéra"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parná lokomotíva"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Železničný vozeň"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Vysokorýchlostný vlak"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Vysokorýchlostný vlak s prednou časťou v tvare projektilu"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vlak"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Ľahká železnica"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Stanica"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Električka"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vozeň električky"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Autobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Prichádzajúci autobus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Autobusová zastávka"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Sanitka"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Hasičské auto"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policajné auto"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Prichádzajúce policajné auto"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxík"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Prichádzajúci taxík"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Automobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Prichádzajúci automobil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Rekreačné vozidlo"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Prepravné nákladné auto"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Nákladné auto s prívesom"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Jednokoľajová železnica"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Horská železnica"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Závesná železnica"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Horská lanovka"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Kabínková lanovka"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Loď"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Veslica"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Pretekársky čln"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vodorovný semafor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Zvislý semafor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Značka stavby"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Maják policajného auta"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trojuholníková vlajka na tyči"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Dvere"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Značka zákazu vstupu"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Symbol fajčenia"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Symbol zákazu fajčenia"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Symbol zahadzovania odpadkov do koša"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Symbol zákazu vyhadzovania odpadkov"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Symbol pitnej vody"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Symbol nepitnej vody"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bicykel"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Zákaz bicyklov"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cyklista"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Horský cyklista"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Chodec"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Zákaz chodcov"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Prechod pre deti"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Symbol muža"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Symbol ženy"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Záchody"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Symbol bábätka"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Záchod"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Sprcha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Kúpeľ"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Vaňa"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasová kontrola"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Clo"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Výdaj batožiny"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Úschova batožiny"</string>
+</resources>
diff --git a/java/res/values-sk/strings-talkback-descriptions.xml b/java/res/values-sk/strings-talkback-descriptions.xml
index 2cd094e..aa38fde 100644
--- a/java/res/values-sk/strings-talkback-descriptions.xml
+++ b/java/res/values-sk/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Nie je zadaný žiadny text"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Klávesom <xliff:g id="KEY_NAME">%1$s</xliff:g> opravíte slovo <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> na <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Klávesom <xliff:g id="KEY_NAME">%1$s</xliff:g> spustíte automatické opravy"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Žiaden návrh"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Neznámy znak"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Ďalšie symboly"</string>
@@ -63,7 +64,7 @@
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"telefón"</string>
     <string name="keyboard_mode_text" msgid="9138789594969187494">"text"</string>
     <string name="keyboard_mode_time" msgid="8558297845514402675">"čas"</string>
-    <string name="keyboard_mode_url" msgid="8072011652949962550">"Adresa URL"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"Webová adresa"</string>
     <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"Nedávne"</string>
     <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Ľudia"</string>
     <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Predmety"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Veľké I s bodkou nad písmenom"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznámy symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznámy symbol Emodži"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Znudená tvár"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Rozpačitá tvár"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Tvár so slnečnými okuliarmi"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Prekvapená tvár"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bozkávajúca sa tvár"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Zamračená tvár"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatívne znaky sú dostupné"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatívne znaky boli zrušené"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatívne návrhy sú dostupné"</string>
diff --git a/java/res/values-sk/strings.xml b/java/res/values-sk/strings.xml
index 40e1db4..f75e01d 100644
--- a/java/res/values-sk/strings.xml
+++ b/java/res/values-sk/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Pri stlačení klávesu vibrovať"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Zvuk pri stlačení klávesu"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Zobraziť znaky pri stlačení klávesu"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Predvoľby"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Účty a ochrana osobných údajov"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Vzhľad a rozloženia"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Písanie gestami"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Oprava textu"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Rozšírené"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Motív"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Povoliť rozdelenie klávesnice"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synchronizácia klávesnice Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synchronizácia je zapnutá"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synchronizovať osobný slovník na zariadeniach"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synchronizovať"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Odstrániť údaje v cloude"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Odstráni vaše synchronizované údaje zo serverov Googlu"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Vaše synchronizované údaje budú odstránené z cloudu. Pokračovať?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Odstrániť"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Zrušiť"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Váš osobný slovník sa synchronizuje a zálohuje na servery Google. S cieľom zlepšiť naše služby môžeme zhromažďovať štatistické informácie o frekvencii slov. Zhromažďovanie informácií a ich použitie bude v súlade s "<a href="https://www.google.com/policies/privacy">"pravidlami ochrany osobných údajov spoločnosti Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Povoľte túto funkciu tak, že do zariadenia pridáte účet Google"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prepnúť na iné metódy vstupu"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kláves na prepnutie jazyka pokrýva aj ďalšie metódy vstupu"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Kľúč na prepínanie jazyka"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Zobraziť, keď je povolených viac jazykov vstupu"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Zobraziť posuvný indikátor"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Zobraziť vizuálny signál pri prejdení z klávesov Shift alebo Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Onesk. zrušenia kľúč. kon. okna"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Bez oneskorenia"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Predvolená"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Hlavný slovník"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Zobraziť návrhy opráv"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Zobrazovať navrhované slová počas písania"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vždy zobrazovať"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Zobraziť v režime na výšku"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vždy skrývať"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokovať urážlivé slová"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Nenavrhovať potenciálne urážlivé slová"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Automatické opravy"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Kľúč hlasového vstupu"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Nie sú povolené žiadne metódy hlasového vstupu. Skontrolujte nastavenia položky Jazyk a vstup."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Odoslať spätnú väzbu"</string>
-    <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Jazyky"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pomocník a spätná väzba"</string>
+    <string name="select_language" msgid="5709487854987078367">"Jazyky"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Opätovným dotykom uložíte"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Klepnutím tu uložíte"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Motív klávesnice"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Prepnúť účty"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Nie sú vybrané žiadne účty"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Momentálne sa používa účet <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Zrušiť"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Odhlásiť sa"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Výber účtu, ktorý chcete použiť"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Anglická klávesnica (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Anglická klávesnica (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španielčina (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"srbčina (latinka)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angličtina (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angličtina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španielčina (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"srbčina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradičná)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cyrilika)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinka)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktná)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Žiadny jazyk (latinka)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinka (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinka (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Latinka (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Latinka (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Motív klávesnice"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Vlastné štýly vstupu"</string>
     <string name="add_style" msgid="6163126614514489951">"Pridať štýl"</string>
     <string name="add" msgid="8299699805688017798">"Pridať"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Povoliť"</string>
     <string name="not_now" msgid="6172462888202790482">"Teraz nie"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Rovnaký štýl vstupu už existuje: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Oneskor. pri stlač. a podržaní"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Trvanie vibrov. pri stlač. kl."</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Hlasitosť pri stlačení klávesu"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Čítať súbor externého slovníka"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"V priečinku Sťahovanie nie sú žiadne súbory slovníka"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Vyberte súbor slovníka, ktorý chcete nainštalovať"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Chcete nainštalovať tento súbor pre jazyk <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Vyskytla sa chyba"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Oneskor. pri stlač. a podržaní"</string>
     <string name="button_default" msgid="3988017840431881491">"Predvolené"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Vitajte v aplikácii <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"s funkciou Písanie gestami"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Pomocou aplikácie <xliff:g id="APPLICATION_NAME">%s</xliff:g> teraz môžete zadávať text vo všetkých obľúbených aplikáciách."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Nakonfigurujte ďalšie jazyky"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Hotovo"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Zobraziť ikonu aplikácie"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Zobrazenie ikony aplikácie v spúšťači"</string>
     <string name="app_name" msgid="6320102637491234792">"Poskytovateľ slovníka"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Poskytovateľ slovníka"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Služba slovníka"</string>
diff --git a/java/res/values-sl/strings-emoji-descriptions.xml b/java/res/values-sl/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..964b2b8
--- /dev/null
+++ b/java/res/values-sl/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Znak za avtorsko zaščito"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Znak za registriranost"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dvojni klicaj"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Klicaj vprašaj"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Znak za registrirano blagovno znamko"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Vir informacij"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Puščica levo desno"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Puščica navzgor navzdol"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Puščica, ki kaže proti severozahodu"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Puščica, ki kaže proti severovzhodu"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Puščica, ki kaže proti jugovzhodu"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Puščica, ki kaže proti jugozahodu"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Puščica levo z zanko"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Puščica desno z zanko"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Ura"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Peščena ura"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Črn dvojni trikotnik, ki kaže desno"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Črn dvojni trikotnik, ki kaže levo"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Črn dvojni trikotnik, ki kaže navzgor"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Črn dvojni trikotnik, ki kaže navzdol"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Budilka"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Peščena ura s pretakajočim se peskom"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Obkrožena velika latinska črka m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Črn majhen kvadrat"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Bel majhen kvadrat"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Črn trikotnik, ki kaže desno"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Črn trikotnik, ki kaže levo"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Bel srednji kvadrat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Črn srednji kvadrat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Bel srednje majhen kvadrat"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Črn srednje majhen kvadrat"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Črno sonce z žarki"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Oblak"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Črn telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Polje na glasovnici s kljukico"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Dežnik z dežnimi kapljami"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Topel napitek"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Bel kazalec, ki kaže navzgor"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Bel nasmejan obraz"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Oven"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Bik"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Dvojčka"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Rak"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lev"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Devica"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Tehtnica"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Škorpijon"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Strelec"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Kozorog"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vodnar"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Ribi"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Črna barva pika"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Črna barva križa"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Črna barva srca"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Črna barva kare"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Termalni vrelci"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Črn univerzalni simbol za recikliranje"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Simbol za invalidski voziček"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Sidro"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Opozorilni znak"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Znak za visoko napetost"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Srednji bel krog"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Srednji črn krog"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Nogometna žoga"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bejzbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snežak brez snega"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sonce za oblakom"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Kačenosec"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Ni vstopa"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Cerkev"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Izvir"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Zastavica v luknji"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Jadrnica"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Šotor"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bencinska črpalka"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Črne škarje"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Bela poudarjena kljukica"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Letalo"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Kuverta"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Dvignjena pest"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Dvignjena dlan"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Dlan z znakom za zmago"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Svinčnik"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Črna konica"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Poudarjena kljukica"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Poudarjen znak za množenje"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Iskrice"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Zvezdica z osmimi paličicami"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Osmerokraka črna zvezda"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snežinka"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Iskrica"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Križec"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negativ križca v kvadratu"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Črn okrasni vprašaj"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Bel okrasni vprašaj"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Bel okrasni klicaj"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Poudarjen simbol klicaja"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Poudarjeno črno srce"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Poudarjen znak za seštevanje"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Poudarjen znak za odštevanje"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Poudarjen znak za deljenje"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Črna puščica desno"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Zavita zanka"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dvojno zavita zanka"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Puščica, ki kaže desno, nato zavije navzgor"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Puščica, ki kaže desno, nato zavije navzdol"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Črna puščica levo"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Črna puščica navzgor"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Črna puščica navzdol"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Črn velik kvadrat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Bel velik kvadrat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Bela srednja zvezda"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Poudarjen velik krog"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Valovit pomišljaj"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Znak za začetek skladbe"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Obkrožen ideogram za čestitke"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Obkrožen ideogram za skrivnost"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Ploščica za mahjong rdeči zmaj"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Igralna karta črni joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Krvna skupina A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Krvna skupina B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Krvna skupina O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkirišče"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Krvna skupina AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL v kvadratu"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cool v kvadratu"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Free v kvadratu"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID v kvadratu"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"New v kvadratu"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG v kvadratu"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK v kvadratu"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS v kvadratu"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Up s klicajem v kvadratu"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Vs v kvadratu"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Tukaj v katakani v kvadratu"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Storitev v katakani v kvadratu"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideogram za brezplačno v kvadratu"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideogram za rezerviran sedež v kvadratu"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideogram za prepoved v kvadratu"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideogram za nezasedeno v kvadratu"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideogram za sprejem v kvadratu"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ideogram za polno zasedenost v kvadratu"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ideogram za plačano v kvadratu"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideogram za mesečno v kvadratu"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideogram za prijavo v kvadratu"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideogram za popust v kvadratu"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideogram za poslovanje v kvadratu"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideogram za prednost v krogu"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideogram za sprejem v krogu"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Ciklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Megleno"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Zaprt dežnik"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Zvezdna noč"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Sončni vzhod nad planinami"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Sončni vzhod"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Mestna veduta ob polmraku"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Sončni zahod nad stavbami"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Mavrica"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Most ponoči"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vodni val"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Rimska cesta"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globus Evropa–Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Globus Ameriki"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globus Azija–Avstralija"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globus s poldnevniki"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbol za mlado luno"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbol za prvi krajec"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbol za polovično osvetljeno luno v prvem krajcu"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbol za več kot polovično osvetljen prvi krajec"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbol za polno luno"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbol za več kot polovično osvetljen zadnji krajec"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbol za polovično osvetljeno luno v zadnjem krajcu"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbol za zadnji krajec"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Lunin srp"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Mlada luna z obrazom"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Polovično osvetljena luna v prvem krajcu z obrazom"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Polovično osvetljena luna v zadnjem krajcu z obrazom"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Polna luna z obrazom"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sonce z obrazom"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Žareča zvezda"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Utrinek"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kostanj"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Sadika"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Zimzeleno drevo"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Listnato drevo"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulipan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Japonska češnja"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Vrtnica"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sončnica"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Cvet"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Koruzno klasje"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Riževo klasje"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Zelišče"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Štiriperesna deteljica"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Javorjev list"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Odpadli list"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"V vetru plahutajoč list"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Goba"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Paradižnik"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Jajčevec"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Grozdje"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melona"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Lubenica"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limona"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rdeče jabolko"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Zeleno jabolko"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Hruška"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Breskev"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Češnje"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jagoda"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Kos pice"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Meso s kostjo"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Piščančja krača"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rižev kreker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Kepica riža"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kuhan riž"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Kari z rižem"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Vroča skleda"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Špageti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Kruh"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Ocvrt krompirček"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Pečena batata"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Suši"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Ocvrti rakci"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Ribji kolač s spiralastim vzorcem"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Točen sladoled"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Granita"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Sladoled"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Krof"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Piškot"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Čokoladka"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Bombon"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lizika"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vaniljev puding"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Kozarec za med"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Sladica s sadnim prelivom in smetano"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Škatla za malico bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Posoda s hrano"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Kuhanje"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Vilice in nož"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Skodelica za čaj brez ročaja"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Steklenica sakeja in skodelica"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Kozarec za vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kozarec za koktajl"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropska pijača"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Vrček za pivo"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Trkajoča vrčka za pivo"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Steklenička za dojenčka"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Pentlja"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Zavito darilo"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Torta za rojstni dan"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Izrezljana buča s svečo"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Božični drevešček"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Božiček"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Ognjemet"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Pirotehnična iskrica"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Pokalica za zabave"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Krogla s konfeti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Drevo želja tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Prekrižani zastavi"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Borov novoletni okrasek"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japonski lutki"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Japonski barvni trakovi v obliki ribe"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vetrni zvončki"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Opazovanje jesenske polne lune"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Usnjena šolska torba s poklopcem"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Maturantska kapa"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Konjiček na vrtiljaku"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Panoramsko kolo"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Vlak smrti"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Ribiška palica in riba"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmska kamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kino"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Slušalka"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Slikarska paleta"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cilinder"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkuški šotor"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Vstopnica"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klapa"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Odrske umetnosti"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Videoigra"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Zadetek v polno"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Igralni avtomat"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Igralna kocka"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Kegljanje"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Igralne karte hanafuda"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Več not"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Kitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klaviatura"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trobenta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violina"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partitura"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Majica za tek z lento"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Teniški lopar in žogica"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Smučke in smučarski čevelj"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Košarkarska žoga in obroč"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Karirasta zastava"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Deskar na snegu"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Tekač"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Deskar"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Pokal"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Konjske dirke"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Ameriški nogomet"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Plavalec"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Gradnja hiše"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Hiša z vrtom"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Pisarniški blok"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japonski poštni urad"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Evropski poštni urad"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Bolnišnica"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Hotel za zaljubljene"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Trgovina z mešanim blagom"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Šola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Veleblagovnica"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Tovarna"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Laterna izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japonski grad"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Evropski grad"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Podgana"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Miš"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Vol"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Indijski bivol"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Krava"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Zajec"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Mačka"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Zmaj"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Kit"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Polž"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Kača"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Konj"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Oven"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Koza"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Ovca"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Opica"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Petelin"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Piščanec"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Pes"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Prašič"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Divji prašič"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Slon"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Hobotnica"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiralasta školjka"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Žužek"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Mravlja"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Domača čebela"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Pikapolonica"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Riba"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropska riba"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Napihovalka"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Želva"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Valeče se pišče"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Pišče"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Pišče od spredaj"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ptica"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Koder"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Enogrba kamela"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Dvogrba kamela"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mišji obraz"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Kravji obraz"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigrov obraz"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Zajčji obraz"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Mačji obraz"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Zmajev obraz"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Kit, ki brizga vodo"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Konjski obraz"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Opičji obraz"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Pasji obraz"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Prašičji obraz"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Žabji obraz"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hrčkov obraz"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Volčji obraz"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Medvedji obraz"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandin obraz"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Prašičji rilec"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Odtisi šap"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Oči"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Uho"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Nos"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Usta"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Jezik"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Bel kazalec, ki kaže navzgor (s hrbtom dlani)"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Bel kazalec, ki kaže navzdol (s hrbtom dlani)"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Bel kazalec, ki kaže levo (s hrbtom dlani)"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Bel kazalec, ki kaže desno (s hrbtom dlani)"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Znak za stisnjeno pest"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Znak za mahajočo roko"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Znak z roko za odobravanje"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Znak za palec navzgor"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Znak za palec navzdol"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Znak za ploskanje"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Znak za razprte dlani"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Krona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Ženski klobuk"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Očala"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kravata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Majica"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Kavbojke"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Obleka"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Ženska oblačila"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Denarnica"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Torbica"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Mošnja"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Moški čevelj"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Športni copat"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Čevelj z visoko peto"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Ženski sandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Ženski škornji"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Stopinje"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhueta doprsne podobe"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhueta doprsnih podob"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Fant"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Dekle"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Moški"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Ženska"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Družina"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Moški in ženska, ki se držita za roke"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Moška, ki se držita za roke"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Ženski, ki se držita za roke"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Policist"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Ženska z zajčjimi ušesi"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Nevesta s tančico"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Oseba svetlih las"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Moški s čepico gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Moški s turbanom"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Starejši moški"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Starejša ženska"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Dojenček"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Gradbeni delavec"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Princesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japonski velikan"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japonski škratelj"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Duh"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Angelček"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Zunajzemeljsko bitje"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Vesoljska pošast"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Škrat"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Lobanja"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Uslužbenka na informacijah"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Gardist"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Plesalka"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rdečilo za ustnice"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Lak za nohte"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Obrazna masaža"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Striženje las"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Brivski izvesek"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Brizga"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pilula"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Sledi ustnic po poljubu"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Ljubezensko pismo"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Prstan"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Dragulj"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Poljub"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Šopek"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Par s srcem"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Poroka"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Utripajoče srce"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Počeno srce"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dve srci"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Svetlikajoče se srce"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Rastoče srce"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Srce s puščico"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Modro srce"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Zeleno srce"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Rumeno srce"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Vijolično srce"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Srce s pentljo"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Vrteči se srci"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Okrasek v obliki srca"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Rombasta podoba s piko na sredini"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Električna žarnica"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Simbol za jezo"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Simbol za spanje"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Simbol za trk"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Simbol za potne kaplje"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Kapljica"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Simbol za brzenje"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Kakec"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Napet biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Simbol za omotico"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Oblaček z govorom"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Oblaček z mislimi"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Bela roža"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbol za sto točk"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Vreča denarja"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Menjava valut"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Poudarjen znak za dolar"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditna kartica"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Bankovec z znakom za jen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Bankovec z dolarskim znakom"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Bankovec z znakom za evro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Bankovec z znakom za funt"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Denar s krili"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Graf z gibanjem navzgor in znakom za jen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Sedež"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Namizni računalnik"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Aktovka"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketa"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optični disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Datotečna mapa"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Odprta datotečna mapa"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Zavihana stran"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Prav obrnjena stran"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Koledar"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Koledar z listi, ki jih je mogoče odtrgati"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Organizator vizitk"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Graf z gibanjem navzgor"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Graf z gibanjem navzdol"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Grafikon s stolpci"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Odložišče"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Risalni žebljiček"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Okrogel risalni žebljiček"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Sponka"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Ravnilo"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Geotrikotnik"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Zavihki z zaznamki"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Glavna knjiga"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Beležnica"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Beležnica z okrasno platnico"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Zaprta knjiga"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Odprta knjiga"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Zelena knjiga"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Modra knjiga"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Oranžna knjiga"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Knjige"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Značka z imenom"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Zvitek"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Zabeležka"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonska slušalka"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pozivnik"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faksirna naprava"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satelitska antena"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Zvočnik za javne objave"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafon za spodbujanje"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Pladenj za poslana sporočila"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Pladenj za prejeta sporočila"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Simbol za e-pošto"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Dohodna kuverta"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Kuverta s puščico navzdol zgoraj"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Zaprt pisemski nabiralnik s spuščeno zastavico"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Zaprt pisemski nabiralnik z dvignjeno zastavico"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Odprt pisemski nabiralnik z dvignjeno zastavico"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Odprt pisemski nabiralnik s spuščeno zastavico"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Poštni nabiralnik"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Poštni rog"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Časopis"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobilni telefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobilni telefon s puščico, ki kaže desno, na levi"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Način vibriranja"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobilni telefon je izklopljen"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Ni mobilnih telefonov"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antena s črticami"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Fotoaparat"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokaseta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Prepleteni puščici, ki kažeta desno"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Puščici, ki kažeta desno in levo v smeri urinega kazalca ter tvorita nesklenjen krog"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Puščici, ki kažeta desno in levo v smeri urinega kazalca ter skupaj z enko v krogcu tvorita nesklenjen krog"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Puščici, ki kažeta dol in gor v smeri urinega kazalca ter tvorita nesklenjen krog"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Puščici, ki kažeta dol in gor v obratni smeri urinega kazalca ter tvorita nesklenjen krog"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbol za nizko vrednost svetlosti"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbol za visoko vrednost svetlosti"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Zvočnik s potezo za ukinitev"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Zvočnik"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Zvočnik z enim zvočnim valom"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Zvočnik s tremi zvočnimi valovi"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Akumulator"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Električni vtič"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Lupa, ki kaže levo"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Lupa, ki kaže desno"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Ključavnica z nalivnim peresom"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Zaprta ključavnica s ključem"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ključ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Ključavnica"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Odprta ključavnica"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zvonec"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Zvonec s potezo za ukinitev"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Zaznamek"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Simbol za verigo"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radijski gumb"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back s puščico levo zgoraj"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End s puščico levo zgoraj"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On s klicajem ter puščico levo desno zgoraj"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon s puščico desno zgoraj"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top s puščico navzgor zgoraj"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbol, da ni dovoljeno za mlajše od 18 let"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tipka deset"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Simbol vnosa za latinske velike črke"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Simbol vnosa za latinske majhne črke"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Simbol vnosa za številke"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbol vnosa za simbole"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Simbol vnosa za latinske črke"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Ogenj"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Električna svetilka"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Ključ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Kladivo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Vijak in matica"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Japonski nož hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pištola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristalna krogla"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Šesterokraka zvezda s piko na sredini"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japonski simbol za začetnika"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Simbol trizoba"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Črn kvadratni gumb"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Bel kvadratni gumb"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Velik rdeč krog"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Velik moder krog"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Velik oranžen romb"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Velik moder romb"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Majhen oranžen romb"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Majhen moder romb"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Rdeč trikotnik, ki kaže navzgor"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Rdeč trikotnik, ki kaže navzdol"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Majhen rdeč trikotnik, ki kaže navzgor"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Majhen rdeč trikotnik, ki kaže navzdol"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Številčnica ure ob enih"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Številčnica ure ob dveh"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Številčnica ure ob treh"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Številčnica ure ob štirih"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Številčnica ure ob petih"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Številčnica ure ob šestih"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Številčnica ure ob sedmih"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Številčnica ure ob osmih"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Številčnica ure ob devetih"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Številčnica ure ob desetih"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Številčnica ure ob enajstih"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Številčnica ure ob dvanajstih"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Številčnica ure ob pol dveh"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Številčnica ure ob pol treh"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Številčnica ure ob pol štirih"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Številčnica ure ob pol petih"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Številčnica ure ob pol šestih"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Številčnica ure ob pol sedmih"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Številčnica ure ob pol osmih"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Številčnica ure ob pol devetih"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Številčnica ure ob pol desetih"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Številčnica ure ob pol enajstih"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Številčnica ure ob pol dvanajstih"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Številčnica ure ob pol enih"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Gora Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo Tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Kip svobode"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhueta Japonske"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Režeč se obraz"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Režeč se obraz s smejočimi očmi"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Obraz s solzami sreče"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Nasmejan obraz z odprtimi usti"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Nasmejan obraz z odprtimi usti in smejočimi očmi"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Nasmejan obraz z odprtimi usti in mrzlim potom"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Nasmejan obraz z odprtimi usti in tesno zaprtimi očmi"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Nasmejan obraz s sijem"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Nasmejan obraz z rogovi"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Mežikajoč obraz"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Nasmejan obraz s smejočimi očmi"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Obraz, ki uživa v slastni hrani"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Olajšan obraz"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Nasmejan obraz z očmi oblike src"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Nasmejan obraz s sončnimi očali"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Obraz s privoščljivim nasmehom"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Ravnodušen obraz"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Brezizrazen obraz"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Hladen obraz"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Obraz z mrzlim potom"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Otožen obraz"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Zbegan obraz"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Zmeden obraz"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Obraz našobljenih ustnic za poljub"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Obraz, ki pošilja poljub"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Obraz našobljenih ustnic za poljub s smejočimi očmi"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Obraz našobljenih ustnic za poljub z zaprtimi očmi"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Obraz z molečim jezikom"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Mežikajoč obraz z molečim jezikom"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Obraz z molečim jezikom in tesno zaprtimi očmi"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Razočaran obraz"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Zaskrbljen obraz"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Jezen obraz"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Našobljen obraz"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Objokan obraz"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Nepopustljiv obraz"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Obraz z zmagovitim pogledom"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Razočaran, vendar olajšan obraz"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Namrščen obraz z odprtimi usti"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Trpeč obraz"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Prestrašen obraz"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Naveličan obraz"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Zaspan obraz"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Utrujen obraz"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Skremžen obraz"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Obraz, ki toči solze"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Obraz z odprtimi usti"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Pritajen obraz"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Obraz z odprtimi usti in mrzlim potom"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Obraz, ki kriči od strahu"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Začuden obraz"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Zardel obraz"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Speč obraz"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Omotičen obraz"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Obraz brez ust"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Obraz s higiensko masko"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Režeč se mačji obraz s smejočimi očmi"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Mačji obraz s solzami sreče"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Nasmejan mačji obraz z odprtimi usti"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Nasmejan mačji obraz z očmi oblike src"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Mačji obraz s porogljivim nasmeškom"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Mačji obraz našobljenih ustnic za poljub z zaprtimi očmi"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Našobljen mačji obraz"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Objokan mačji obraz"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Naveličan mačji obraz"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Obraz z gesto neodobravanja"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Obraz z gesto odobravanja"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Oseba z globokim priklonom"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Opica, ki ničesar ne vidi"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Opica, ki ničesar ne sliši"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Opica, ki ničesar ne pove"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Vesela oseba z dvignjeno roko"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Oseba, ki proslavlja z obema rokama v zraku"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Namrščena oseba"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Oseba z našobljenim obrazom"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Oseba s sklenjenimi rokami"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parna lokomotiva"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Železniški vagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Hitri vlak"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Hitri vlak s koničastim nosom"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Vlak"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Podzemna železnica"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Mestna železnica"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Postaja"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvaj"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Vagon tramvaja"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Avtobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Nasproti vozeč avtobus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolejbus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Avtobusno postajališče"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Reševalno vozilo"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Gasilski avtomobil"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Policijski avtomobil"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Nasproti vozeč policijski avtomobil"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Nasproti vozeč taksi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Avtomobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Nasproti vozeč avtomobil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Rekreativno vozilo"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Tovornjak za dostavo"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Polpriklopnik"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Enotirna železnica"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Gorska železnica"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Viseča železnica"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Gorska vzpenjača"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Nadzemna železnica"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Ladja"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Čoln na vesla"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Dirkalni čoln"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Vodoravni semafor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Navpični semafor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Znak za gradbena dela"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Rotacijska luč policijskega avtomobila"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Trikotna zastavica na drogu"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Vrata"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Znak, da ni vstopa"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Simbol za dovoljeno kajenje"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Simbol za prepovedano kajenje"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Simbol za odlaganje smeti v koš"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbol za prepovedano odlaganje smeti"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbol za pitno vodo"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbol za nepitno vodo"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Kolo"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Prepovedano za kolesa"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Kolesar"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Gorski kolesar"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Pešec"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Prepovedano za pešče"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Otroci na cesti"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Simbol za moške"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Simbol za ženske"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Javno stranišče"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Simbol za dojenčke"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Stranišče"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Toaleta"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Prha"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Kopel"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Banja"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kontrola potnih listov"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Carina"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Prevzem prtljage"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Zapuščena prtljaga"</string>
+</resources>
diff --git a/java/res/values-sl/strings-talkback-descriptions.xml b/java/res/values-sl/strings-talkback-descriptions.xml
index baef01f..0e1e187 100644
--- a/java/res/values-sl/strings-talkback-descriptions.xml
+++ b/java/res/values-sl/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Ni vnesenega besedila"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Tipka <xliff:g id="KEY_NAME">%1$s</xliff:g> popravi <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> v <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Tipka <xliff:g id="KEY_NAME">%1$s</xliff:g> izvede samopopravek"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Ni predlogov"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Neznan znak"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Več simbolov"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Velika črka I s piko zgoraj"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Neznan simbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Neznan znak »emoji«"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Zdolgočasen obraz"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Obraz v zadregi"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Obraz s sončnimi očali"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Presenečen obraz"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Obraz našobljenih ustnic za poljub"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Namrščen obraz"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Nadomestni znaki so na voljo"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Nadomestni znaki se ne upoštevajo"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Nadomestni predlogi so na voljo"</string>
diff --git a/java/res/values-sl/strings.xml b/java/res/values-sl/strings.xml
index 09392e5..cae331e 100644
--- a/java/res/values-sl/strings.xml
+++ b/java/res/values-sl/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibriranje ob pritisku tipke"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Zvok ob pritisku tipke"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Povečaj črko ob pritisku"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Nastavitve"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Računi in zasebnost"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Videz in postavitve"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Pisanje s kretnjami"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Popravki besedila"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Dodatno"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Omogoči razdeljeno tipkovnico"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Sinhroniz. Googlove tipkovnice"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinhronizacija je vklopljena"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sinhronizacija osebnega slovarja po napravah"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sinhroniziraj"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Izbris podatkov v oblaku"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Izbriše sinhronizirane podatke iz Googla"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Sinhronizirani podatki bodo izbrisani iz oblaka. Ste prepričani?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Izbriši"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Prekliči"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Osebni slovar bo sinhroniziran in varnostno kopiran v Googlove strežnike. Statistične podatke o pogostosti rabe besed bomo morda zbirali zaradi izboljšanja naših izdelkov. Zbiranje in uporaba vseh podatkov bo skladna z "<a href="https://www.google.com/policies/privacy">"Googlovim pravilnikom o zasebnosti"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"V napravi dodajte Google Račun, če želite omogočiti to funkcijo"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prekl. na drug nač. vnosa"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za preklop jezika, ki vključuje tudi druge načine vnosa"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Tipka za preklop med jeziki"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Pokaži, ko je omogočenih več jezikov vnosa"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Pokaži indikator drsenja"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Pokaži vizualni znak pri drsenju s tipk Shift ali Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Trajanje povečanja tipke"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Brez zakasnitve"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Privzeto"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Glavni slovar"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Pokaži predloge popravkov"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Pokaži predlagane besede med tipkanjem"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Vedno pokaži"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Prikaži v pokončnem načinu"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Vedno skrij"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blokiraj žaljive besede"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ne predlagaj potencialno žaljivih besed"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Samodejni popravek"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Tipka za glasovni vnos"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ni omogočenih glasovnih načinov vnosa. Preverite nastavitve v razdelku »Jezik in vnos«."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Pošljite povratne informacije"</string>
-    <string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Jeziki"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Pomoč in povratne informacije"</string>
+    <string name="select_language" msgid="5709487854987078367">"Jeziki"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se še enkrat, da shranite"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Če želite shraniti, se dotaknite tukaj"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema tipkovnice"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Preklop med računi"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Ni izbranih računov"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Trenutno uporabljate račun <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"V redu"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Prekliči"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Odjava"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Izbira računa za uporabo"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"angleščina (Združeno kraljestvo)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"angleščina (ZDA)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"španščina (ZDA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindujska angleščina"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Srbščina (latinica)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"angleščina (VB) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"angleščina (ZDA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"španščina (ZDA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindujska angleščina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Srbščina (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tradicionalna)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cirilica)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinica)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompaktna)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Brez jezika (latinice)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Latinica (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Latinica (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Latinica (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Latinica (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Znaki »emoji«"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema za tipkovnico"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Slogi vnosa po meri"</string>
     <string name="add_style" msgid="6163126614514489951">"Dodaj slog"</string>
     <string name="add" msgid="8299699805688017798">"Dodaj"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Omogoči"</string>
     <string name="not_now" msgid="6172462888202790482">"Ne zdaj"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isti slog vnosa že obstaja: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Zakasn. za dolg pritisk tipke"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Trajanje vibr. ob prit. tipke"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Glasn. zvoka ob pritisku tipke"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Branje zunanje datoteke slovarja"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"V mapi »Prenosi« ni nobene datoteke slovarja"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Izberite datoteko slovarja, ki jo želite namestiti"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Zares želite namestiti to datoteko za ta jezik: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Prišlo je do napake"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Zakasn. za dolg pritisk tipke"</string>
     <string name="button_default" msgid="3988017840431881491">"Privzeto"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Pozdravljeni v aplikaciji <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"s pisanjem s kretnjami"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Zdaj lahko z aplikacijo <xliff:g id="APPLICATION_NAME">%s</xliff:g> tipkate v vseh svojih priljubljenih aplikacijah."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfiguracija dodatnih jezikov"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Končano"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Pokaži ikono aplikacije"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Prikaz ikone aplikacije v zaganjalniku"</string>
     <string name="app_name" msgid="6320102637491234792">"Ponudnik slovarja"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Ponudnik slovarja"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Storitev slovarja"</string>
diff --git a/java/res/values-sr/strings-emoji-descriptions.xml b/java/res/values-sr/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..f1764c8
--- /dev/null
+++ b/java/res/values-sr/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Знак за ауторска права"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Знак за регистровани бренд"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Двоструки знак узвика"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Знак узвика и знак питања"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Знак жига"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Извор информација"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Стрелица налево и надесно"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Стрелица нагоре и надоле"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Стрелица северозапад"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Стрелица североисток"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Стрелица југоисток"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Стрелица југозапад"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Закривљена стрелица налево"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Закривљена стрелица надесно"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Ручни сат"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Пешчани сат"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Црни двоструки троугао усмерен надесно"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Црни двоструки троугао усмерен налево"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Црни двоструки троугао усмерен нагоре"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Црни двоструки троугао усмерен надоле"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Аларм"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Пешчани сат са песком који тече"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Заокружено велико латинично слово м"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Мали црни квадрат"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Мали бели квадрат"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Црни троугао усмерен надесно"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Црни троугао усмерен налево"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Средњи бели квадрат"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Средњи црни квадрат"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Средње мали бели квадрат"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Средње мали црни квадрат"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Црно сунце са зрацима"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Облак"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Црни телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Опција са знаком потврде"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Кишобран са кишним капима"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Врућ напитак"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Бели подигнути кажипрст"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Бело насмејано лице"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Ован"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Бик"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Близанци"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Рак"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Лав"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Девица"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Вага"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Шкорпија"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Стрелац"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Јарац"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Водолија"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Рибе"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Црни пик"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Црни треф"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Црни херц"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Црни каро"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Термални извори"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Црни универзални симбол за рециклажу"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Симбол инвалидских колица"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Сидро"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Знак упозорења"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Знак за високи напон"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Средњи бели круг"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Средњи црни круг"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Фудбалска лопта"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бејзбол"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Снешко без снега"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Сунце иза облака"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Змијоноша"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Забрањен улаз"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Црква"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтана"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Застава у рупи"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Једрењак"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Шатор"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Пумпа за гориво"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Црне маказе"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Бели попуњени знак потврде"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Авион"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Коверта"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Подигнута песница"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Подигнута рука"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Знак победе"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Оловка"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Црно перо"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Попуњени знак потврде"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Попуњен знак за множење x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Искре"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Осмокрака звезда"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Осмокрака црна звезда"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Пахуљица"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Искра"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Знак x"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Инверзни знак x"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Орнамент са црним знаком питања"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Орнамент са белим знаком питања"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Орнамент са белим знаком узвика"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Попуњен симбол знака узвика"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Потпуно црно срце"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Попуњен знак плус"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Попуњен знак минус"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Попуњен знак дељења"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Црна стрелица надесно"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Петља"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Двострука петља"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Стрелица усмерена надесно па нагоре"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Стрелица усмерена надесно па надоле"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Црна стрелица налево"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Црна стрелица нагоре"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Црна стрелица надоле"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Велики црни квадрат"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Велики бели квадрат"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Средња бела звезда"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Попуњени велики круг"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Таласаста цртица"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Знак за раздвајање делова"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Заокружени идеограф за честитање"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Заокружени идеограф за тајну"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong плочица са црвеним змајем"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Карта за играње са црним џокером"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Крвна група А"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Крвна група Б"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Нулта крвна група"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Паркинг"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Крвна група АБ"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL у квадрату"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"„Cool“ у квадрату"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"„Free“ у квадрату"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"„ID“ у квадрату"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"„New“ у квадрату"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"„N G“ у квадрату"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"„OK“ у квадрату"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"„SOS“ у квадрату"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"„Up“ са узвичником у квадрату"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"„VS“ у квадрату"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Катакана знак за „овде“ у квадрату"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Катакана знак за услугу у квадрату"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Идеограф „Бесплатно“ у квадрату"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Идеограф „Резервисано место“ у квадрату"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Идеограф „Забрана“ у квадрату"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Идеограф „Слободно место“ у квадрату"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Идеограф „Прихватање“ у квадрату"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Идеограф „Све је попуњено“ у квадрату"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Идеограф „Плаћено“ у квадрату"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Идеограф „Месечно“ у квадрату"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Идеограф „Пријава“ у квадрату"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Идеограф „Попуст“ у квадрату"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Идеограф „Радимо“ у квадрату"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Заокружени идеограф „Предност“"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Заокружени идеограф „Прихвати“"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Магла"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Затворени кишобран"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Звездана ноћ"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Излазак сунца изнад планина"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Излазак сунца"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Град у сумрак"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Залазак сунца изнад зграда"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Дуга"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Мост ноћу"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Водени талас"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Млечни пут"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Земаљска кугла са Европом и Африком"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Земаљска кугла са Америкама"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Земаљска кугла са Азијом и Аустралијом"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Земаљска кугла са меридијанима"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Симбол младог месеца"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Симбол месечевог српа у порасту"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Симбол прве четврти месеца"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Симбол месеца између прве четврти и пуног месеца"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Симбол пуног месеца"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Симбол месеца између пуног месеца и последње четврти"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Симбол последње четврти месеца"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Симбол месечевог српа у опадању"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Месечев срп"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Млад месец са лицем"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Прва четврт месеца са лицем"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Последња четврт месеца са лицем"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Пун месец са лицем"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Сунце са лицем"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Сјајна звезда"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Звезда падалица"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Кестен"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Младица"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Зимзелено дрво"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Листопадно дрво"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Палма"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Лала"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Цвет трешње"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Ружа"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Хибискус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Сунцокрет"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Цват"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Клип кукуруза"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Стабљика пиринча"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Биље"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Детелина са четири листа"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Јаворов лист"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Опали лист"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Опали лист лепрша на ветру"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Печурка"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Парадајз"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Патлиџан"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Грожђе"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Диња"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Лубеница"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарина"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимун"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банана"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Црвена јабука"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Зелена јабука"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Крушка"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Бресква"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Трешње"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Јагода"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Хамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Парче пице"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Месо са коском"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Батак"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Пиринчани крекер"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Куглица од пиринча"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Кувани пиринач"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Пиринач са каријем"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Врућа чинија"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Шпагете"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Хлеб"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Помфрит"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Печени слатки кромпир"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Оден"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суши"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Пржени шкампи"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Рибља пљескавица са шаром вртлога"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Течни сладолед"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Ломљени лед"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Сладолед"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Крофна"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Колачић"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Чоколадица"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Бомбона"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Лизалица"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Крем"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Ћуп са медом"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Тортица"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Кутија са ручком"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Чинија хране"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Кување"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Виљушка и нож"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Шољица без дршке"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Флаша сакеа и чаша"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Чаша вина"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Чаша коктела"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропско пиће"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Кригла пива"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Кригле пива које се куцају"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Флашица за бебе"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Трака"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Упакован поклон"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Рођенданскa тортa"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Изрезбарена бундева"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Новогодишња јелка"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Божић Бата"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Ватромет"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Прскалица"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Балон"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Журка"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Конфете"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Дрво танабата"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Укрштене заставе"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Украс за јелку"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Јапанске лутке"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Ветроказ у облику шарана"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Висећи метални звончићи"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Церемонија гледања месеца"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Школска торба"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Капа за дипломце"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Коњ са вртешке"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Панорамски точак"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Луна-парк"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Штап за пецање и риба"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Микрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Филмска камера"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Биоскоп"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Слушалице"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Сликарска палета"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Цилиндар"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Циркуски шатор"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Карта"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Режисерска табла"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Уметнички наступ"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Видео игра"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Директан погодак"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Слот-машина"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Билијар"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Коцкица за игру"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Куглање"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Карте за играње са цветом"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музичка нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Више музичких нота"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гитара"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Клавијатура"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Труба"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Виолина"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Нотни запис"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Спортска мајица са траком"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Тениски рекет и лоптица"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Скија и скијашка чизма"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Кошаркашка лопта и обруч"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Застава за крај трке"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордер"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Тркач"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Сурфер"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Трофеј"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Коњске трке"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Амерички фудбал"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Рагби"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Пливач"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Кућа"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Кућа са баштом"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Пословна зграда"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Јапанска пошта"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Европска пошта"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Болница"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банка"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Хотел"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Романтични хотел"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Продавница"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Школа"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Робна кућа"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Фабрика"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Изакаја лампа"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Јапански дворац"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Европски дворац"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Пацов"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Миш"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Во"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Водени биво"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Крава"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Зец"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Мачка"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Змај"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Пуж"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Змија"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Коњ"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ован"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Коза"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Овца"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Мајмун"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Петао"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Кокошка"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Пас"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Прасе"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Вепар"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Слон"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Октопод"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Спирална шкољка"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Буба"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Мрав"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Пчела"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Бубамара"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Риба"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропска риба"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Надувана риба"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Корњача"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Пиле које се испилило"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Пиле"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Пиле спреда"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Птица"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пингвин"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудлица"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Једногрба камила"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Двогрба камила"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Делфин"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Лице миша"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Лице краве"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Лице тигра"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Лице зеца"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Лице мачке"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Лице змаја"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Кит који је изронио"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Лице коња"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Лице мајмуна"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Лице пса"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Лице прасета"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Лице жабе"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Лице хрчка"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Лице вука"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Лице медведа"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Лице панде"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Њушка прасета"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Отисци шапа"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Очи"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Уво"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Нос"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Уста"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Језик"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Спољни део беле шаке са кажипрстом нагоре"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Спољни део беле шаке са кажипрстом надоле"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Спољни део беле шаке са кажипрстом налево"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Спољни део беле шаке са кажипрстом надесно"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Песница"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Рука која маше"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Знак руком „У реду“"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Палац окренут нагоре"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Палац окренут надоле"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Тапшање"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Отворене шаке"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Круна"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Женски шешир"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Наочаре"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Кравата"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Мајица"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Фармерке"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Хаљина"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кимоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бикини"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Женска гардероба"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Ташница"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Ташна"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Торбица"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Мушка ципела"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Патика"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Ципела са високом штиклом"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Женска сандала"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Женске чизме"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Отисци стопала"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Силуета бисте"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Силуета бисти"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Дечак"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Девојчица"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Мушкарац"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Жена"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Породица"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Мушкарац и жена се држе за руке"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Двојица мушкараца се држе за руке"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Две жене се држе за руке"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Полицајац"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Жена са зечјим ушима"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Невеста са велом"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Плавокоса особа"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Мушкарац са гуа пи мао капом"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Мушкарац са турбаном"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Старији човек"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Старија жена"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Беба"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Радник на градилишту"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцеза"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Јапански џин"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Јапански гоблин"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Дух"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Беба анђео"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Ванземаљац"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Чудовиште ванземаљац"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Ђаволчић"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Лобања"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Особа која даје информације"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Чувар"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Плесач"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Кармин"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Лак за нокте"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Масажа лица"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Фризура"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Берберски знак"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Пилула"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Отисак пољупца"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Љубавно писмо"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Прстен"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Драгуљ"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Пољубац"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Пар са срцем"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Венчање"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Срце које куца"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Сломљено срце"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Два срца"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Светлуцаво срце"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Срце које расте"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Срце прободено стрелом"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Плаво срце"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Зелено срце"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Жуто срце"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Љубичасто срце"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Срце са траком"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Срца која се окрећу"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Украс у облику срца"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Облик дијаманта са тачком у средини"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Електрична сијалица"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Симбол љутње"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Симбол спавања"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Симбол судара"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Симбол капи зноја"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Капљица"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Симбол црте"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Гомила измета"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Стегнути бицепс"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Симбол вртоглавице"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Облачић за говор"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Балончић за размишљање"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Бели цвет"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Симбол за сто поена"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Врећа новца"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Мењачница"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Попуњен симбол долара"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Кредитна картица"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Новчаница са знаком јена"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Новчаница са знаком долара"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Новчаница са знаком евра"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Новчаница са знаком фунте"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Новац са крилима"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Дијаграм са растућим трендом и знаком јена"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Седиште"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Лични рачунар"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Актен-ташна"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Мини-диск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптички диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Директоријум датотеке"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Отворени директоријум датотеке"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Увијена страница"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Страница окренута нагоре"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Календар"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Календар са листовима који се цепају"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Индекс картица"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Дијаграм са растућим трендом"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Дијаграм са опадајућим трендом"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Тракасти графикон"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Табла за поруке"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Прибадача"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Округла прибадача"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Спајалица"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Прав лењир"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Троугаони лењир"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Обележивачи страница"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Главна књига"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Бележница"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Бележница са декоративном корицом"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Затворена књига"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Отворена књига"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Зелена књига"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Плава књига"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Наранџаста књига"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Књиге"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Значка са именом"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Свитак"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Меморандум"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефонска слушалица"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пејџер"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Сателитска антена"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Разглас"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Навијачки мегафон"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Документи за слање"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Примљени документи"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Пакет"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Симбол имејла"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Долазна порука"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Стрелица надоле изнад коверте"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Затворено поштанско сандуче са спуштеном заставом"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Затворено поштанско сандуче са подигнутом заставом"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Отворено поштанско сандуче са подигнутом заставом"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Отворено поштанско сандуче са спуштеном заставом"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Поштанско сандуче"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Поштански рог"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Новине"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобилни телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Мобилни телефон са стрелицом надесно са леве стране"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Режим вибрације"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Мобилни телефон је искључен"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Без мобилних телефона"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Антена са тракама"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Видео камера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Телевизор"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радио"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Видео касета"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Укрштене стрелице надесно"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Кружне стрелице надесно и налево у смеру казаљки на сату"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Кружне стрелице надесно и налево у смеру казаљки на сату преко којих стоји уоквирен број један"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Кружне стрелице надоле и нагоре у смеру казаљки на сату"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Кружне стрелице надоле и нагоре у смеру супротном казаљки на сату"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Симбол слабог осветљења"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Симбол јаког осветљења"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Прецртани звучник"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Звучник"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Звучник са једним звучним таласом"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Звучник са три звучна таласа"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Батерија"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Електрични утикач"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Лупа окренута налево"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Лупа окренута надесно"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Катанац са пером"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Затворен катанац са кључем"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Кључ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Катанац"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Отворени катанац"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Звоно"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Прецртано звоно"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Обележивач"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Симбол везе"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Дугме за избор"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Стрелица налево изнад „Back“"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Стрелица налево изнад „End“"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Стрелица налево и надесно изнад „On“ са узвичником"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Стрелица надесно изнад „Soon“"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Стрелица нагоре изнад „Top“"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Забрањено за особе млађе од 18 година"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Тастер са бројем 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Симбол уноса за велика латинична слова"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Симбол уноса за мала латинична слова"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Симбол уноса за бројеве"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Улазни симбол за симболе"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Симбол уноса за латинична слова"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Пожар"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Батеријска лампа"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Француски кључ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Чекић"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Шраф и завртањ"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Хочо"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пиштољ"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Микроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Кристална кугла"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Шестокрака звезда са тачком у средини"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Јапански симбол за почетника"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Амблем трозупца"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Дугме са црним квадратом"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Дугме са белим квадратом"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Велики црвени круг"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Велики плави круг"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Велики наранџасти дијамант"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Велики плави дијамант"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Мали наранџасти дијамант"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Мали плави дијамант"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Црвени троугао усмерен нагоре"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Црвени троугао усмерен надоле"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Мали црвени троугао усмерен нагоре"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Мали црвени троугао усмерен надоле"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Бројчаник који показује један сат"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Бројчаник који показује два сата"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Бројчаник који показује три сата"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Бројчаник који показује четири сата"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Бројчаник који показује пет сати"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Бројчаник који показује шест сати"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Бројчаник који показује седам сати"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Бројчаник који показује осам сати"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Бројчаник који показује девет сати"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Бројчаник који показује десет сати"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Бројчаник који показује једанаест сати"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Бројчаник који показује дванаест сати"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Бројчаник који показује пола два"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Бројчаник који показује пола три"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Бројчаник који показује пола четири"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Бројчаник који показује пола пет"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Бројчаник који показује пола шест"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Бројчаник који показује пола седам"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Бројчаник који показује пола осам"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Бројчаник који показује пола девет"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Бројчаник који показује пола десет"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Бројчаник који показује пола једанаест"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Бројчаник који показује пола дванаест"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Бројчаник који показује пола један"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Планина Фуџи"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токијски торањ"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Кип слободе"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Силуета Јапана"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Мојаи"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Лице са широким осмехом"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Лице са широким осмехом и насмејаним очима"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Лице са сузама радосницама"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Насмејано лице са отвореним устима"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Насмејано лице са отвореним устима и насмејаним очима"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Насмејано лице са отвореним устима, обливено хладним знојем"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Насмејано лице са отвореним устима и чврсто затвореним очима"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Насмејано лице са ореолом"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Насмејано лице са роговима"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Лице које намигује"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Насмејано лице са насмејаним очима"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Лице које ужива у укусној храни"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Лице са изразом олакшања"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Насмејано лице са очима у облику срца"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Насмејано лице са наочарима за сунце"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Лице које се злобно смешка"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Лице са неутралним изразом"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Безизражајно лице"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Лице коме није забавно"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Лице обливено хладним знојем"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Замишљено лице"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Збуњено лице"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Лице у недоумици"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Лице које љуби"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Лице које шаље пољубац"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Лице које љуби са насмејаним очима"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Лице које љуби са затвореним очима"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Лице са исплаженим језиком"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Лице које се плази и намигује"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Лице које се плази са чврсто затвореним очима"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Разочарано лице"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Забринуто лице"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Љутито лице"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Надурено лице"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Уплакано лице"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Истрајно лице"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Лице са победничким изразом"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Разочарано лице коме је лакнуло"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Намрштено лице са отвореним устима"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Намучено лице"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Уплашено лице"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Опрезно лице"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Поспано лице"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Уморно лице"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Лице са гримасом"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Лице које плаче наглас"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Лице са отвореним устима"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Лице које ућуткује"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Лице са отвореним устима, обливено хладним знојем"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Лице које вришти у страху"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Запањено лице"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Зајапурено лице"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Успавано лице"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Лице коме се врти"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Лице без уста"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Лице са медицинском маском"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Лице мачке са широким осмехом и насмејаним очима"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Лице мачке са сузама радосницама"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Насмејано лице мачке са отвореним устима"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Насмејано лице мачке са очима у облику срца"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Лице мачке са киселим осмехом"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Лице мачке које љуби са затвореним очима"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Надурено лице мачке"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Уплакано лице мачке"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Уморно лице мачке"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Лице са изразом „нешто није у реду“"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Лице са изразом одобравања"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Особа која се дубоко клања"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Мајмун који не види ништа лоше"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Мајмун који не чује ништа лоше"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Мајмун који не говори ништа лоше"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Срећна особа са подигнутом руком"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Особа која је из радости подигла руке"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Намрштена особа"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Надурена особа"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Особа са спојеним рукама"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Хеликоптер"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Парна локомотива"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Вагон"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Брзи воз"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Брзи воз са заобљеним врхом"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Воз"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Градска железница"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станица"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвај"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Вагон трамваја"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Аутобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Аутобус који стиже"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Тролејбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Аутобуско стајалиште"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Минибус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Хитна помоћ"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Ватрогасна кола"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Полицијски ауто"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Полицијски ауто који стиже"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Такси"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Такси који стиже"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Аутомобил"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Аутомобил који стиже"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Камп-возило"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Камион за испоруку"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Камион са приколицом"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Пруга са једним колосеком"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Планинска пруга"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Висећа железница"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Планинска жичара"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Висећи трамвај"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Брод"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Чамац"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Брзи моторни чамац"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Хоризонтални семафор"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Вертикални семафор"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Знак за грађевинске радове"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Ротационо светло полицијског аутомобила"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Троугласта застава на стубу"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Врата"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Симбол за забрањен улаз"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Симбол за пушење"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Симбол забрањеног пушења"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Симбол који упозорава где треба бацати отпад"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Симбол забране бацања отпада"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Симбол воде за пиће"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Симбол воде која није за пиће"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Бицикл"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Забрањено за бицикле"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Бициклиста"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Планински бициклиста"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Пешак"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Забрањено за пешаке"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Деца прелазе"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Симбол мушког тоалета"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Симбол женског тоалета"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Тоалет"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Симбол за бебе"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Тоалет"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Туш"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Купатило"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Када"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Пасошка контрола"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Царина"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Преузимање пртљага"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Остављени пртљаг"</string>
+</resources>
diff --git a/java/res/values-sr/strings-talkback-descriptions.xml b/java/res/values-sr/strings-talkback-descriptions.xml
index 974ad3a..5e984d3 100644
--- a/java/res/values-sr/strings-talkback-descriptions.xml
+++ b/java/res/values-sr/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Текст није унет"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> исправља <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> у <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> обавља аутоматско исправљање"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Нема предлога"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Непознати знак"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Још симбола"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Велико И са тачком изнад"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Непознат симбол"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Непознати емоџи"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Лице коме је досадно"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Постиђено лице"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Лице са наочарима за сунце"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Изненађено лице"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Лице које љуби"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Намрштено лице"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступни су алтернативни знаци"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Алтернативни знаци су одбачени"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступни су алтернативни предлози"</string>
diff --git a/java/res/values-sr/strings.xml b/java/res/values-sr/strings.xml
index 4f1e426..5ff279d 100644
--- a/java/res/values-sr/strings.xml
+++ b/java/res/values-sr/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вибрирај на притисак тастера"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Звук на притисак тастера"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Искачући прозор приликом притиска тастера"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Подешавања"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Налози и приватност"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Изглед и распореди"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Куцање покретима"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Исправљање текста"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Напредно"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Омогући подељену тастатуру"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Синхронизуј Google тастатуру"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхронизација је укључена"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Синхронизујте лични речник на свим уређајима"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Синхронизуј одмах"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Избриши податке из клауда"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Брише синхронизоване податке са Google-а"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Избрисаћемо синхронизоване податке из клауда. Да ли сте сигурни?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Избриши"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Откажи"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Синхронизоваћемо лични речник и направићемо његову резервну копију на Google серверима. Можда ћемо прикупљати статистичке податке о учесталости речи да бисмо побољшали производе. Прикупљање и коришћење свих информација ће бити у складу са "<a href="https://www.google.com/policies/privacy">"Google-овом политиком приватности"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Додајте Google налог на уређај да бисте омогућили ову функцију"</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">"Тастер за пребацивање језика обухвата и друге методе уноса"</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">"Прикажи индикатор превлачења"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Приказује визуел. траг при превлачењу са тастера 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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Тастер за гласовни унос"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ниједан метод гласовног уноса није омогућен. Проверите Подешавања језика и уноса."</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="language_selection_title" msgid="3666971864764478269">"Језици"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Помоћ и повратне информације"</string>
+    <string name="select_language" msgid="5709487854987078367">"Језици"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Поново додирните да бисте сачували"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Додирните овде да бисте сачували"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема тастатуре"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Промените налог"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Није изабран ниједан налог"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Тренутно користите <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Потврди"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Откажи"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Одјави ме"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Изаберите налог који ћете користити"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"енглески (УК)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"енглески (САД)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"шпански (САД)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"хенглески"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"српски (латиница)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"енглески (УК) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"енглески (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"шпански (САД) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"хенглески (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"српски (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиционални)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ћирилица)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиница)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (компактна)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Нема језика (абецеда)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Абецеда (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Абецеда (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Абецеда (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Абецеда (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Емотикони"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Тема тастатуре"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Прилаг. стилови уноса"</string>
     <string name="add_style" msgid="6163126614514489951">"Додав. стила"</string>
     <string name="add" msgid="8299699805688017798">"Додај"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"Желите ли стварно да инсталирате ову датотеку за <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Дошло је до грешке"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Одлагање при дугом притиску"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Сада можете да куцате у свим омиљеним апликацијама помоћу <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">"Икона апликације се приказује у покретачу"</string>
     <string name="app_name" msgid="6320102637491234792">"Добављач речника"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Добављач речника"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Услуга речника"</string>
@@ -173,7 +170,7 @@
     <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_updating" msgid="4457761393932375219">"Траже се ажурирања"</string>
     <string name="message_loading" msgid="5638680861387748936">"Учитавање…"</string>
     <string name="main_dict_description" msgid="3072821352793492143">"Главни речник"</string>
     <string name="cancel" msgid="6830980399865683324">"Откажи"</string>
diff --git a/java/res/values-sv/strings-emoji-descriptions.xml b/java/res/values-sv/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..e49c73c
--- /dev/null
+++ b/java/res/values-sv/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Upphovsrättssymbol"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Symbol för registrerat varumärke"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dubbelt utropstecken"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Utropstecken och frågetecken"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Varumärkessymbol"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Informationskälla"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Vänster/höger-pil"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Upp/ned-pil"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Nordvästpil"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Nordostpil"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Sydostpil"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Sydvästpil"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Vänsterpil med krok"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Högerpil med krok"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Armbandsur"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Timglas"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Svart dubbeltriangel som pekar åt höger"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Svart dubbeltriangel som pekar åt vänster"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Svart dubbeltriangel som pekar uppåt"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Svart dubbeltriangel som pekar nedåt"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Väckarklocka"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Timglas med sand som rinner"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Stort M med cirkel runt"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Liten svart ruta"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Liten vit ruta"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Svart triangel som pekar mot höger"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Svart triangel som pekar åt vänster"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Medelstor vit ruta"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Medelstor svart ruta"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Medelliten vit ruta"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Medelliten svart ruta"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Svart sol med strålar"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Moln"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Svart telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Röstningsruta med bock"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Paraply med regndroppar"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Varm dryck"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Vitt pekfinger som pekar uppåt"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Vitt leende ansikte"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Väduren"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Oxen"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Tvillingarna"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Kräftan"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Lejonet"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Jungfrun"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Vågen"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Skorpionen"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Skytten"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Stenbocken"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Vattumannen"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Fiskarna"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Svart spader"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Svart klöver"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Svart hjärter"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Svart ruter"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Varma källor"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Svart återvinningssymbol"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Rullstolssymbol"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ankare"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Varningsskylt"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Högspänningsskylt"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Medelstor vit cirkel"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Medelstor svart cirkel"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Fotboll"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseboll"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snögubbe utan snö"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Sol bakom moln"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ormbäraren"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Inträde förbjudet"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kyrka"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fontän"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Flagga i hålet"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Segelbåt"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tält"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bensinpump"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Svart sax"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Vit tjock kryssmarkering"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Flygplan"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Kuvert"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Höjd knuten näve"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Handflata"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Segerhand"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Blyertspenna"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Svart pennspets"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Tjock kryssmarkering"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Tjockt multiplikationstecken"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Glitter"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisk med åtta streck"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Åttauddig stjärna"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snöflinga"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Glitter"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Kryss"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negativ kryssmarkering i fyrkant"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Svart frågetecken med utsmyckning"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Vitt frågetecken med utsmyckning"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Vitt utropstecken med utsmyckning"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Tjockt utropstecken"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Tungt svart hjärta"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Tjockt plustecken"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Tjockt minustecken"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Tjockt divisionstecken"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Svart högerpil"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Ögla"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dubbla öglor"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Högerpil som böjer sig uppåt"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Högerpil som böjer sig nedåt"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Svart vänsterpil"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Svart uppåtpil"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Svart nedåtpil"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Stor svart ruta"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Stor vit ruta"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Medelstor vit stjärna"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Tjock stor cirkel"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Vågigt streck"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Musikaliskt tecken för inledning av ny del"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Cirkelformat ideogram för gratulation"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Cirkelformat ideogram för hemlighet"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjongbricka röd drake"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Spelkort svart joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blodgrupp A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blodgrupp B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blodgrupp O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Parkeringsplats"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blodgrupp AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL i fyrkant"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cool i fyrkant"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Free i fyrkant"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID i fyrkant"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"New i fyrkant"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG i fyrkant"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK i fyrkant"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS i fyrkant"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Up! i fyrkant"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS i fyrkant"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana i fyrkant (här)"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Katakana i fyrkant (tjänst)"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Fyrkantigt ideogram för avgiftsfri"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Fyrkantigt ideogram för reserverad plats"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Fyrkantigt ideogram för förbud"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Fyrkantigt ideogram för rum finns"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Fyrkantigt ideogram för godkännande"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Fyrkantigt ideogram för fullbokat"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Fyrkantigt ideogram för betalat"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Fyrkantigt ideogram för månadsvis"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Fyrkantigt ideogram för ansökan"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Fyrkantigt ideogram för rabatt"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Fyrkantigt ideogram för öppet"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Cirkelformat ideogram för fördel"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Cirkelformat ideogram för acceptera"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Cyklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Dimma"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Stängt paraply"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Stjärnklar natt"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Soluppgång över berg"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Soluppgång"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Stadssilhuett i skymningen"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Solnedgång över byggnader"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Regnbåge"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Bro på natten"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Vattenvåg"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Vintergatan"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Jordglob Europa–Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Jordglob Nord- och Sydamerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Jordglob Asien–Australien"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Glob med meridianer"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Symbolen Nymåne"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Symbolen Tilltagande månskära"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Symbolen Måne första kvarteret"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Symbolen Tilltagande halvmåne"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Symbolen Fullmåne"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Symbolen Avtagande halvmåne"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Symbolen Måne sista kvarteret"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Symbolen Avtagande månskära"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Månskära"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Nymåne med ansikte"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Måne första kvarteret med ansikte"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Måne sista kvarteret med ansikte"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Fullmåne med ansikte"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Sol med ansikte"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Glödande stjärna"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Stjärnfall"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanj"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Groddplanta"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Vintergrönt träd"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Lövfällande träd"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palm"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulpan"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Körsbärsblomma"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Ros"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hibiskus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Solros"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blomma"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Majskolv"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Risvippa"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Ört"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Fyrklöver"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Lönnlöv"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Fallet löv"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Blad som fladdrar i vinden"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Svamp"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Tomat"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Vindruvor"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Vattenmelon"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tangerin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Citron"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Rött äpple"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Grönt äpple"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Päron"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Persika"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Körsbär"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Jordgubbe"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburgare"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizzabit"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Kött på ben"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Kyklingklubba"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Riskex"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Risboll"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kokt ris"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry och ris"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Ångande skål"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Bröd"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Pommes frites"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Rostad sötpotatis"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Friterde räkor"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fiskkaka med virvelmönster"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Mjukglass"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Shaved ice"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Glass"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Munk"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Småkaka"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chokladkaka"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Godis"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Vaniljkräm"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honungsburk"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Sockerkaka"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bentolåda"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Kastrull med mat"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Matlagning"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Gaffel och kniv"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tekopp utan handtag"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sakeflaska och kopp"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Vinglas"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktailglas"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropisk drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Ölglas"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Klirrande ölglas"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Nappflaska"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Band"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Inslagen present"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Födelsedagstårta"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Jack-O-Lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Julgran"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Jultomten"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fyrverkerier"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Tomtebloss"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ballong"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Konfettibomb"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfettiboll"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata-träd"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Korsade flaggor"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Bambudekoration"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japanska dockor"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Koinobori"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Vindspel"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Tsukimi-ceremoni"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Skolväska"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Examenshatt"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Karusellhäst"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Pariserhjul"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Berg-och-dal-bana"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Fiskespö och fisk"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Filmkamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Bio"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Hörlur"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palett"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Cylinderhatt"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Cirkustält"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Biljett"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Klappa"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Scenkonst"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Tv-spel"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Direktträff"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Enarmad bandit"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biljard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Speltärning"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Japanska spelkort"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nottecken"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Flera nottecken"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitarr"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Klaviatur"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trumpet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Fiol"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Klav"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Löpartröja med band"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennisracket och boll"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Skida och pjäxa"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketboll och korg"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Schackrutig flagga"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboardåkare"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Löpare"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfare"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trofé"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Hästkapplöpning"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikansk fotboll"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugbyboll"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Simmare"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Hus"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Hus med trädgård"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Kontorsbyggnad"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japanskt postkontor"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Europeiskt postkontor"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Sjukhus"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotell"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Kärlekshotell"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Närbutik"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Skola"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Varuhus"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrik"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya-lampa"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japanskt slott"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Europeiskt slott"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Råtta"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Mus"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Oxe"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Vattenbuffel"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Ko"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Hare"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Katt"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Drake"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Krokodil"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Val"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Snigel"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Orm"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Häst"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Bagge"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Get"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Får"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Apa"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Tupp"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Höna"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Hund"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Gris"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Galt"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elefant"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Bläckfisk"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiralformat snäckskal"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Larv"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Myra"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Bi"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Nyckelpiga"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Fisk"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropisk fisk"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Blåsfisk"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Sköldpadda"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kyckling som kläcks"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kyckling"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kyckling framifrån"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Fågel"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedar"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Kamel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mushuvud"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Kohuvud"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Tigerhuvud"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Harhuvud"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Katthuvud"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Drakhuvud"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Val som sprutar vatten"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Hästhuvud"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Aphuvud"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Hundhuvud"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Grishuvud"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Grodhuvud"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamsteransikte"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Varghuvud"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Björnhuvud"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Pandahuvud"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Gristryne"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Tassavtryck"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ögon"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Öra"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Näsa"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mun"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Tunga"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Vit handrygg med pekfinger som pekar uppåt"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Vit handrygg med pekfinger som pekar nedåt"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Vit handrygg med pekfinger som pekar åt vänster"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Vit handrygg med pekfinger som pekar åt höger"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Knuten näve-tecken"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Hand som vinkar-tecken"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Handtecknet OK"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Tummen upp-tecken"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Tummen ned-tecken"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Applåd-tecken"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Öppna händer-tecken"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Krona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Damhatt"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Glasögon"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Slips"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Klänning"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Damkläder"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Plånbok"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handväska"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Sminkväska"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Herrsko"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sportsko"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Högklackad sko"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Damsandal"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Damstövlar"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Fotavtryck"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Silhuett av byst"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Silhuett av byster"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Pojke"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Flicka"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Man"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Kvinna"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familj"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Man och kvinna som håller hand"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Två män som håller hand"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Två kvinnor som håller hand"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polis"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Kvinna med kaninöron"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Brud med slöja"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Person med blont hår"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Man med gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Man med turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Gammal man"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Gammal kvinna"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Baby"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Byggarbetare"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinsessa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japansk demon"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japansk Tengu"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Spöke"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Babyängel"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Utomjording"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Utomjordiskt monster"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Vätte"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Dödskalle"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Person i informationen"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Vakt med björnskinnsmössa"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dansare"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Läppstift"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nagellack"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Ansiktsmassage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Frisyr"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barberarstolpe"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Spruta"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Piller"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Pussmärke"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Kärleksbrev"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Ring"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Ädelsten"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Puss"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bukett"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Par med hjärta"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Bröllop"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Hjärta som slår"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Brustet hjärta"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Två hjärtan"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Glittrande hjärta"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Hjärta som växer"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Hjärta med pil"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Blått hjärta"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Grönt hjärta"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Gult hjärta"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Lila hjärta"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Hjärta med rosett"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Hjärtan som cirklar runt varandra"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Hjärtdekoration"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Romb med punkt inuti"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Glödlampa"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Symbol för ilska"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomb"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Symbol för sömn"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Symbol för krock"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Symbolen Svett som stänker"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Liten droppe"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Symbol för fart"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Bajskorv"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Spända biceps"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Symbol för yrhet"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Pratbubbla"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Tankebubbla"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Vit blomma"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Hundra poäng-symbol"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Påse med pengar"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valutaväxling"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Tjockt dollartecken"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kreditkort"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Sedel med yentecken"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Sedel med dollartecken"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Sedel med eurotecken"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Sedel med pundtecken"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Pengar med vingar"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Uppåtgående diagram och yentecken"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Säte"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"PC"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Portfölj"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Diskett"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optisk skiva"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Filmapp"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Öppen filmapp"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Sida som rullar upp sig"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Uppåtvänd sida"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalender"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Blockkalender"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kortregister"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Uppåtgående diagram"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Nedåtgående diagram"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Stapeldiagram"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Skrivunderlägg"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Kartnål"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Rund kartnål"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Gem"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Rak linjal"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Vinkelhake"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Märkflikar"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Liggare"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Anteckningsbok"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Anteckningsbok med snyggt omslag"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Stängd bok"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Öppen bok"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Grön bok"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Blå bok"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Orange bok"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Böcker"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Namnskylt"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Rulle"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Anteckning"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefonlur"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Personsökare"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellitantenn"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Högtalare för offentliga meddelanden"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Utkorg"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Inkorg"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-postsymbol"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Inkommande kuvert"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Kuvert med pil som pekar nedåt ovanför"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Stängd brevlåda med flaggan nere"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Stängd brevlåda med flaggan uppe"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Öppen brevlåda med flaggan uppe"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Öppen brevlåda med flaggan nere"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Brevlåda"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posthorn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Tidning"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobiltelefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobiltelefon med pil som pekar åt höger på vänster sida"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibrationsläge"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobiltelefonen av"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobiltelefoner förbjudna"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenn med staplar"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Tv"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokassett"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Tvinnade högerpilar"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Öppna cirkelpilar åt höger och vänster i riktning medurs"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Öppna cirkelpilar åt höger och vänster i riktning medurs med en etta i cirkel som överlägg"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Öppna cirkelpilar nedåt och uppåt i riktning medurs"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Öppna cirkelpilar nedåt och uppåt i riktning moturs"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Symbol för låg ljusstyrka"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Symbol för hög ljusstyrka"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Högtalare med annulleringsstreck"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Högtalare"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Högtalare med en ljudvåg"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Högtalare med tre ljudvågor"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batteri"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elkontakt"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Förstoringsglas riktat åt vänster"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Förstoringsglas riktat åt höger"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Hänglås med bläckpenna"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Stängt hänglås med nyckel"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Nyckel"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Hänglås"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Öppet hänglås"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Klocka"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Klocka med annulleringsstreck"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bokmärke"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Länksymbol"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radioknapp"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back (bakåt) med vänsterpil ovanför"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End (slut) med vänsterpil ovanför"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On (på) med utropstecken och vänster-höger-pil ovanför"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon (snart) med högerpil ovanför"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top (till toppen) med uppåtpil ovanför"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Symbol för 18 års åldersgräns"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Tangent 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Inmatningssymbol för latinska stora bokstäver"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Inmatningssymbol för latinska små bokstäver"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Inmatningssymbol för siffror"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Inmatningssymbol för symboler"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Inmatningssymbol för latinska bokstäver"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Eld"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Ficklampa"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Skiftnyckel"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Hammare"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Mutter och skruv"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Pistol"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristallkula"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Sexuddig stjärna med mittprick"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japansk symbol för nybörjare"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Trident-symbol"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Svart fyrkantig knapp"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Vit fyrkantig knapp"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Stor röd cirkel"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Stor blå cirkel"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Stor orange romb"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Stor blå romb"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Liten orange romb"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Liten blå romb"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Röd triangel som pekar uppåt"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Röd triangel som pekar nedåt"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Liten röd triangel som pekar uppåt"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Liten röd triangel som pekar nedåt"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Urtavla klockan ett"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Urtavla klockan två"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Urtavla klockan tre"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Urtavla klockan fyra"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Urtavla klockan fem"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Urtavla klockan sex"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Urtavla klockan sju"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Urtavla klockan åtta"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Urtavla klockan nio"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Urtavla klockan tio"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Urtavla klockan elva"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Urtavla klockan tolv"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Urtavla halv två"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Urtavla halv tre"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Urtavla halv fyra"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Urtavla halv fem"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Urtavla halv sex"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Urtavla halv sju"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Urtavla halv åtta"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Urtavla halv nio"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Urtavla halv tio"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Urtavla halv elva"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Urtavla halv tolv"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Urtavla halv ett"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Frihetsgudinnan"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Silhuett av Japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Storleende ansikte"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Storleende ansikte med leende ögon"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Ansikte med glädjetårar"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Leende ansikte med öppen mun"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Leende ansikte med öppen mun och leende ögon"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Leende ansikte med öppen mun och kallsvett"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Leende ansikte med öppen mun och ihopknipna ögon"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Leende ansikte med gloria"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Leende ansikte med horn"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Ansikte som blinkar med ena ögat"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Leende ansikte med leende ögon"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Ansikte som äter något gott"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Lättat ansikte"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Leende ansikte med hjärtformade ögon"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Leende ansikte med solglasögon"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Ansikte med snett leende"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Neutralt ansikte"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Uttryckslöst ansikte"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Ansikte som inte är roat"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Ansikte med kallsvett"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Eftertänksamt ansikte"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Förvirrat ansikte"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Förbryllat ansikte"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Kyssande ansikte"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Ansikte som blåser iväg en kyss"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Kyssande ansikte med leende ögon"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Kyssande ansikte med stängda ögon"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Ansikte som sticker ut tungan"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Ansikte som sticker ut tungan och blinkar med ena ögat"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Ansikte som sticker ut tungan och kniper ihop ögonen"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Besviket ansikte"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Oroligt ansikte"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Argt ansikte"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Tjurigt ansikte"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Ansikte som gråter"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Ihärdigt ansikte"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Triumferande ansikte"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Ansikte som ser besviket men lättat ut"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Missnöjt ansikte med öppen mun"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Plågat ansikte"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Ängsligt ansikte"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Trött och slitet ansikte"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Sömnigt ansikte"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Trött ansikte"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Grimaserande ansikte"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Ansikte som gråter högt"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Ansikte med öppen mun"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Tystat ansikte"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Ansikte med öppen mun och kallsvett"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Ansikte som skriker av rädsla"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Överraskat ansikte"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Rodnande ansikte"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Sovande ansikte"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Yrt ansikte"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Ansikte utan mun"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Ansikte med kirurgmask"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Storleende kattansikte med leende ögon"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Kattansikte med glädjetårar"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Leende kattansikte med öppen mun"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Leende kattansikte med hjärtformade ögon"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Kattansikte med snett leende"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Kyssande kattansikte med stängda ögon"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Tjurigt kattansikte"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Gråtande kattansikte"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Trött och slitet kattansikte"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Ansikte med \"sluta\"-gest"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Ansikte med OK-gest"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Person som bugar djupt"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Ser inget-apa"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Hör inget-apa"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Säger inget-apa"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Glad person som lyfter en hand"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Person som höjer båda händerna i en segergest"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Person som ser bister ut"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Person med tjurigt ansikte"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Person med knäppta händer"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Ånglok"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Järnvägsvagn"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Höghastighetståg"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Höghastighetståg med rund nos"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tåg"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Tunnelbana"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Snabbspårväg"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Station"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Spårvagn"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Spårvagn"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Buss"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Buss som närmar sig"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trådbuss"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Busshållplats"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibuss"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulans"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Brandbil"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Polisbil"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Polisbil som närmar sig"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi som närmar sig"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Bil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Bil som närmar sig"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Stadsjeep"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Skåpbil"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Långtradare"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Bergbana"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Hängbana"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Linbana"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Kabinbana"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Färja"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Roddbåt"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Racerbåt"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Horisontellt trafikljus"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Vertikalt trafikljus"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Vägbyggskylt"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Polissiren"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Vimpel på stång"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Dörr"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Inträde förbjudet-skylt"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Röksymbol"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Rökförbudssymbol"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Släng skräp här-symbol"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Nedskräpning förbjuden-symbol"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Dricksvattensymbol"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ej drickbart vatten-symbol"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Cykel"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Cyklar förbjudna"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Cyklist"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountainbikeåkare"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Fotgängare"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Inga fotgängare"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Barn"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Herrsymbol"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Damsymbol"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Toalett"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Babysymbol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Toalett"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"WC"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dusch"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Badrum"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Badkar"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Passkontroll"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Tull"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagageutlämning"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Effektförvaring"</string>
+</resources>
diff --git a/java/res/values-sv/strings-talkback-descriptions.xml b/java/res/values-sv/strings-talkback-descriptions.xml
index e3f7ca1..79339be 100644
--- a/java/res/values-sv/strings-talkback-descriptions.xml
+++ b/java/res/values-sv/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Ingen text har angetts"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Om du trycker på <xliff:g id="KEY_NAME">%1$s</xliff:g> rättas <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> till <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Om du trycker på <xliff:g id="KEY_NAME">%1$s</xliff:g> utförs autokorrigering"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Inga förslag"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Okänt tecken"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Skift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Fler symboler"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Versalt I, punkt ovanför"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Okänd symbol"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Okänd emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Uttråkat ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Generat ansikte"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ansikte med solglasögon"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Förvånat ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kyssande ansikte"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Ansikte med rynkad panna"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternativa tecken är tillgängliga"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternativa tecken avvisas"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternativa förslag är tillgängliga"</string>
diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml
index 798b26e..b9e8475 100644
--- a/java/res/values-sv/strings.xml
+++ b/java/res/values-sv/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Vibrera vid tangenttryck"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Knappljud"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Popup vid knapptryck"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Inställningar"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Konton och sekretess"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Utseende och layouter"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Svepskrivning"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Textkorrigering"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Avancerat"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Aktivera delat tangentbord"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Synkronisera Googles tangentbord"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Synkroniseringen har aktiverats"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Synkronisera din personliga ordlista på dina enheter"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Synkronisera nu"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Radera data i molnet"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Din synkroniserade data raderas från Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Din synkroniserade data raderas från molnet. Vill du fortsätta?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Radera"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Avbryt"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Den egna ordboken synkroniseras och säkerhetskopieras till Googles servrar. Statistisk information om ordfrekvens kan samlas in och användas för att förbättra våra produkter. Insamlingen och användningen av all information sker i enlighet med "<a href="https://www.google.com/policies/privacy">"Googles sekretesspolicy"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Lägg till ett Google-konto på enheten om du vill aktivera detta"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Byt till annan inmatning"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Språkbytesknappen omfattar även andra inmatningsmetoder"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Knapp för att byta språk"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Visa när flera inmatningsspråk är aktiverade"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Visa dragreglage"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Visa svepning när du drar från Skift- eller Symboltangenten"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ta bort popup-fördröjning"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Fördröj inte"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standard"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Huvudordlistan"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Visa rättningsförslag"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Visar ordförslag när du skriver"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Visa alltid"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Visa i stående format"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Dölj alltid"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Blockera stötande ord"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Visa inte förslag på ord som kan verka stötande"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Autokorrigering"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Röstinmatningsknapp"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ingen röstinmatningsmetod har aktiverats. Kontrollera språk- och inmatningsinställningarna."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Skicka feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Inmatningsspråk"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Språk"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Hjälp och feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Språk"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Tryck här om du vill spara"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tangentbordstema"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Byt konto"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Du har inte valt något konto"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Du använder nu <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Avbryt"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Logga ut"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Välj ett konto"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Engelskt (brittiskt)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Engelskt (amerikanskt)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"spanska (USA)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hindi/engelska"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbiska (latinsk)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Engelska (Storbritannien) <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Engelska (USA) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanska (USA (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hindi/engelska (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbiska (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (traditionell)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kyrillisk)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (latinsk)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Inget språk (alfabet)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabet (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabet (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabet (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabet (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Humörsymbol"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tangentbordstema"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Anpassade indatastilar"</string>
     <string name="add_style" msgid="6163126614514489951">"Ny stil"</string>
     <string name="add" msgid="8299699805688017798">"Lägg till"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Aktivera"</string>
     <string name="not_now" msgid="6172462888202790482">"Inte nu"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Samma indatastil finns redan: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Fördröjning vid långt tryck"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Vibrationslängd för tangenter"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Ljudvolym för tangenter"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Läs extern ordboksfil"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Inga ordboksfiler i mappen Hämtningar"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Välj en ordboksfil att installera"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Vill du verkligen installera filen för <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Ett fel uppstod"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Fördröjning vid långt tryck"</string>
     <string name="button_default" msgid="3988017840431881491">"Standard"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Välkommen till <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"med svepskrivning"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Nu kan du skriva i alla dina favoritappar med <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Konfigurera ytterligare språk"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Slutförda"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Visa appikon"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Visa appikonen i startprogrammet"</string>
     <string name="app_name" msgid="6320102637491234792">"Dictionary Provider"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Dictionary Provider"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Ordlistetjänst"</string>
@@ -181,11 +178,11 @@
     <string name="install_dict" msgid="180852772562189365">"Installera"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"Avbryt"</string>
     <string name="delete_dict" msgid="756853268088330054">"Ta bort"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Det finns en ordbok för språket du har valt på din mobila enhet.&lt;br/&gt; Vi rekommenderar att du &lt;b&gt;hämtar&lt;/b&gt; ordboken på <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>. Då blir det enklare och smidigare att skriva.&lt;br/&gt; &lt;br/&gt; Hämtningen tar en minut eller två om du använder 3G. Avgifter kan tillkomma om du inte har ett &lt;b&gt;abonnemang med obegränsad data&lt;/b&gt;.&lt;br/&gt; Om du inte är säker på vad som ingår i ditt abonnemang rekommenderar vi att du hittar en Wi-Fi-anslutning och påbörjar hämtningen automatiskt.&lt;br/&gt; &lt;br/&gt; Tips: Du kan hämta och ta bort ordböcker via &lt;b&gt;Språk och inmatning&lt;/b&gt; i menyn &lt;b&gt;Inställningar&lt;/b&gt; på din mobila enhet."</string>
-    <string name="download_over_metered" msgid="1643065851159409546">"Hämta nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Hämta via Wi-Fi"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Det finns en ordbok för språket du har valt på din mobila enhet.&lt;br/&gt; Vi rekommenderar att du &lt;b&amp;gtladdar ned&lt;/b&gt; ordboken på <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>. Då blir det enklare och smidigare att skriva.&lt;br/&gt; &lt;br/&gt; Laddningen tar en minut eller två om du använder 3G. Avgifter kan tillkomma om du inte har ett &lt;b&gt;abonnemang med obegränsad data&lt;/b&gt;.&lt;br/&gt; Om du inte är säker på vad som ingår i ditt abonnemang rekommenderar vi att du hittar en Wi-Fi-anslutning och påbörjar nedladdningen automatiskt.&lt;br/&gt; &lt;br/&gt; Tips: Du kan ladda ned och ta bort ordböcker via &lt;b&gt;Språk och inmatning&lt;/b&gt; i menyn &lt;b&gt;Inställningar&lt;/b&gt; på din mobila enhet."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Ladda ned nu (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Ladda ned via Wi-Fi"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"En ordlista för <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> är tillgänglig"</string>
-    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tryck om du vill granska och hämta"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Tryck om du vill granska och ladda ned"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Hämtar: förslag för <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> är snart klara."</string>
     <string name="version_text" msgid="2715354215568469385">"Version <xliff:g id="VERSION_NUMBER">%1$s</xliff:g>"</string>
     <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Lägg till"</string>
diff --git a/java/res/values-sw/strings-action-keys.xml b/java/res/values-sw/strings-action-keys.xml
index 21ed881..81ea374 100644
--- a/java/res/values-sw/strings-action-keys.xml
+++ b/java/res/values-sw/strings-action-keys.xml
@@ -20,10 +20,10 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="label_go_key" msgid="4033615332628671065">"Fanya"</string>
+    <string name="label_go_key" msgid="4033615332628671065">"Nenda"</string>
     <string name="label_next_key" msgid="5586407279258592635">"Inayofuata"</string>
     <string name="label_previous_key" msgid="1421141755779895275">"Nyuma"</string>
-    <string name="label_done_key" msgid="7564866296502630852">"Imekamilika"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Nimemaliza"</string>
     <string name="label_send_key" msgid="482252074224462163">"Tuma"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Tafuta"</string>
     <string name="label_pause_key" msgid="2225922926459730642">"Sitisha"</string>
diff --git a/java/res/values-sw/strings-emoji-descriptions.xml b/java/res/values-sw/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..329bf39
--- /dev/null
+++ b/java/res/values-sw/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Ishara ya hakimiliki"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Ishara ya usajili"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Emoji ya alama mbili za mshangao"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Emoji ya alama ya mshangao na kuuliza"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Emoji ya alama ya nembo ya biashara"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Emoji ya chanzo cha habari"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Emoji ya mshale unaoonyesha kushoto-kulia"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Emoji ya mshale unaoonyesha juu-chini"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Emoji ya mshale unaoonyesha upande wa kaskazini magharibi"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Emoji ya mshale unaoonyesha upande wa kaskazini mashariki"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Emoji ya mshale unaoonyesha upande wa kusini mashariki"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Emoji ya mshale unaoonyesha upande wa kusini magharibi"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Emoji ya mshale unaoonyeshea kushoto ukiwa umejikunja kwa juu kama ndoano"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Emoji ya mshale unaoonyeshea kulia ukiwa umejikunja kwa juu kama ndoano"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Emoji ya saa ya kuonyeshea wakati"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Emoji ya chupa inayopima muda kwa mtiririko wa mchanga"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Emoji ya pembetatu zilizoongozana zinazoonyeshea upande wa kulia"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Emoji ya pembetatu zilizoongozana zinazoonyeshea upande wa kushoto"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Emoji ya pembetatu zilizoongozana zinazoonyeshea juu"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Emoji ya pembetatu zilizoongozana zinazoonyeshea chini"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Emoji ya saa ya kengele"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Emoji ya chupa inayopima muda kwa mtiririko wa mchanga na mchanga ukitiririka"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Emoji ya herufi m iliyozungushiwa duara"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Emoji ya mraba mdogo mweusi"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Emoji ya mraba mdogo mweupe"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Emoji ya pembetatu inayoonyeshea upande wa kulia"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Emoji ya pembetatu inayoonyeshea upande wa kushoto"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Emoji ya mraba mweupe"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Emoji ya mraba mweusi"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Emoji ya mraba mdogo mweupe"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Emoji ya mraba mdogo mweusi"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Emoji ya jua lenye rangi nyeusi na miale"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Emoji ya wingu"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Emoji ya simu ya nyeusi ya mezani"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Emoji ya kisanduku cha kupigia kura na alama ya tiki"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Emoji ya mwavuli na manyunyu ya mvua"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Emoji ya kinywaji moto"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Ishara ya mkono ukiwa umenyoosha kidole kuelekea juu"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Emoji ya uso unaoonyesha tabasamu la kawaida"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Emoji inayoonyesha alama inayowakilisha nyota ya Kondoo"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Emoji inayoonyesha alama inayowakilisha nyota ya Ng\'ombe"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Emoji inayoonyesha alama inayowakilisha nyota ya Mapacha"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Emoji inayoonyesha alama inayowakilisha nyota ya Kaa"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Emoji inayoonyesha alama inayowakilisha nyota ya Simba"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Emoji inayoonyesha alama inayowakilisha nyota ya Mashuke"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Emoji inayoonyesha alama inayowakilisha nyota ya Mizani"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Emoji inayoonyesha alama inayowakilisha nyota ya Ng\'e"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Emoji inayoonyesha alama inayowakilisha nyota ya Mshale"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Emoji inayoonyesha alama inayowakilisha nyota ya Mbuzi"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Emoji inayoonyesha alama inayowakilisha nyota ya Ndoo"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Emoji inayoonyesha alama inayowakilisha nyota ya Samaki"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Emoji ya karata nyeusi ya jembe au shupaza"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Emoji ya karata nyeusi ya mavi au ua"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Emoji ya karata nyeusi ya kopa au moyo"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Emoji ya karata nyeusi ya almasi au kisu"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Emoji inayoonyesha chemchemi hai ya maji ya moto"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Emoji ya alama nyeusi ya kimataifa ya urejelezaji"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Emoji ya alama ya kiti cha magurudumu aghalabu kinachotumiwa na watu wenye ulemavu wa miguu"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Emoji ya Nanga"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Emoji ya alama ya tahadhari"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Emoji ya alama inayonyesha umeme wenye msongo mkubwa"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Emoji ya kiwambo chenye duara ya rangi nyeupe kati kati"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Emoji ya kiwambo chenye duara ya rangi nyeusi kati kati"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Emoji ya mpira wa soka"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Emoji ya mpira wa besiboli"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Emoji ya mwanatheluji bila theluji"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Emoji ya jua nyuma ya mawingu"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Emoji ya alama inayowakilisha nyota ya Nyoka, mtu akiwa amembeba nyoka"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Emoji ya duara na msitari uliokingama umepita kati kati, ikiwa ni ishara ya katazo la kuingia katika eneo hilo"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Emoji ya kanisa"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Emoji ya mashine inayorusha maji kama chemchemi"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Emoji ya bendera katika shimo, aghalabu hutumiwa kama kiashiria kwenye michezo"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Emoji ya mashua"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Emoji ya Hema"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Emoji ya pampu ya mafuta"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Emoji ya mkasi mweusi"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Emoji ya alama nyeupe ya tiki iliyokolezwa"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Emoji ya ndege"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Emoji ya bahasha"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Emoji ya mkono uliokunja ngumi umeinuliwa"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Emoji ya mkono umeinuliwa"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Emoji ya mkono umeinuliwa kama ishara ya ushindi"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Emoji ya penseli"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Emoji ya nibu nyeusi"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Emoji ya alama ya tiki iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Emoji ya alama ya kuzidisha iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Emoji ya vimuli muli"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Emoji ya alama ya nyota yenye pembe nane"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Emoji ya nyota nyeusi yenye pembe nane"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Emoji ya tone la maji lililobadilika kua barafu wakati likianguka kutoka mawinguni"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Emoji ya alama inayowakilisha tone la maji lililobadilika kua barafu wakati likianguka kutoka mawinguni"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Emoji ya alama ya msalaba"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Emoji ya alama ya msalaba iliyogeuka na kua kama alama ya kuzidisha"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Emoji ya pambo la alama nyeusi ya kuuliza"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Emoji ya pambo la alama nyeupe ya kuuliza"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Emoji ya pambo la alama nyeupe ya mshangao"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Emoji ya alama ya mshangao iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Emoji ya ua la moyo wenye rangi nyeusi iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Emoji ya alama ya kujumlisha iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Emoji ya alama ya kutoa iliyokolezwa sana"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Emoji ya alama ya kugawanya iliyokolezwa sana"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Emoji ya mshale mweusi unaoonyeshea kulia"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Emoji ya kitanzi kilichojikunja"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Emoji ya kitanzi kilichokunjwa mara mbili"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Emoji ya mshale unaoonyeshea kulia kisha unajikunja kuelekea juu"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Emoji ya mshale unaoonyeshea kulia kisha unajikunja kuelekea chini"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Emoji ya mshale mweusi unaoonyeshea kushoto"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Emoji ya mshale mweusi unaoonyeshea juu"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Emoji ya mshale mweusi unaoonyeshea chini"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Emoji ya mraba mkubwa wa rangi nyeusi"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Emoji ya mraba mkubwa wa rangi nyeupe"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Emoji ya nyota nyeupe ya wastani"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Emoji ya duara kubwa lililokolezwa sana"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Emoji ya kistari chenye mawimbi"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Emoji ya alama ya kiuandishi ya kijapani inayotumika kuonyeshea sehemu ya kuanzia mwimbaji hasa katika wimbo ambao pengine haufahamu vizuri, pia hutumika kama herufi M kwenye alfabeti za kigiriki"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Emoji ya lugha ya alama ya asili inayomaanisha hongera"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Emoji ya lugha ya alama ya asili inayomaanisha siri"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Kigae cha Mahjong chenye ishara inayowakilisha joka jekundu"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Jokari mweusi wa kadi za kucheza"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Aina A ya damu"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Aina B ya damu"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Aina O ya damu"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Eneo la kuegesha magari"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Aina AB ya damu"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Herufi CL ndani ya mraba"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Neno cool ndani ya mraba"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Neno free ndani ya mraba"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Herufi ID ndani ya mraba"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Neno new ndani ya mraba"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Herufi NG ndani ya mraba"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK Ndani ya mraba"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS Ndani ya mraba"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Neno up likiwa na alama ya mshangao ndani ya mraba"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Herufi vs ndani ya mraba"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Alama mbili ndani ya mraba zinazowakilisha maneno katakana koko inapatikana hapa"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Alama moja ya ndani ya mraba inayowakilisha maneno huduma ya katakana sa"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha bila malipo"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha nafasi iliyohifadhiwa"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha marufuku au katazo"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha uwepo wa nafasi za wazi"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha kukubaliwa"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha umiliki kamili"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha malipo yamekwisha fanyika"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha jambo ambalo hufanyika kila mwezi"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha maombi"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha punguzo la bei"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mraba ikiwakilisha shughuli zinaendelea kama vile biashara"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mduara ikiwakilisha upekee"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Alama ya mfumo wa asili wa pamoja wa China, Japan na Korea ikiwa ndani ya mduara ikiwakilisha ombi la kupokea au kupokelewa"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Kimbunga"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Hali ya ukungu"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Mwavuli uliofungwa"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Usiku wenye nyota"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Maawio ya jua juu ya milima"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Mapambazuko"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Mji mkubwa wakati wa machweo ya jua"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Machweo ya jua juu ya majengo"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Upinde wa mvua"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Daraja wakati wa usiku"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Wimbi la maji"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Volkano"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Kilimia"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Dunia kama inavyoonekana kutoka angani ikionyesha bara Ulaya na Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Dunia kama inavyoonekana kutoka angani ikionyesha mabara yote ya Amerika"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Dunia kama inavyoonekana kutoka angani ikionyesha bara Asia na Australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Dunia ikionyesha mistari yake ya meridiani"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Alama ya mwezi mpya"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Alama ya mwezi mpevu"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Alama inayoonesha hatua ya tatu ya kuonekana kwa mwezi ambapo nusu ya mwezi upande wa kulia huonekana"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Alama inayoonesha hatua ya nne ya kuonekana kwa mwezi ambapo robo tatu ya mwezi upande wa kulia huonekana"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Alama inayoonesha hatua ya tano ya kuonekana kwa mwezi ambapo mwezi wote huonekana"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Alama inayoonesha hatua ya sita ya kuonekana kwa mwezi ambapo robo tatu ya mwezi upande wa kushoto huonekana"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Alama inayoonesha hatua ya saba ya kuonekana kwa mwezi ambapo nusu ya mwezi upande wa kushoto huonekana"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Hatua ya nane na ya mwisho ya kuonekana kwa mwezi ambapo sehemu ndogo ya upande wa kushoto huonekana."</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Mwezi mpevu"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Mwezi mpya wenye uso wa mtu"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Nusu ya mwezi upande wa kulia wenye uso wa mtu"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Nusu ya mwezi upande wa kushoto wenye uso wa mtu"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Mwezi mzima wenye uso wa mtu"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Jua lenye uso wa mtu"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Nyota ing\'arayo"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Kimondo"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Karanga za Kichina"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Mche ukichipuka"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Mti wa kijani kibichi"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Mti wa jamii ya mwaloni"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Mnazi"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kakati dungusi"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Ua la Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Ua dogo la rangi ya waridi au jeupe lililochanua ambalo kutokea kwake huchukuliwa kama ishara ya kumalizika kwa majira ya baridi"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Waridi"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Haibiskasi"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Ua la alizeti"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Ua lililochanua"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Ganda ambalo halijamaliziwa kutolewa kutoka kwenye mhindi"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Suke la mpunga"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Mmea wenye majani"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Jamii ya mimea adimu yenye majani ya pande nne"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Jani la mti jamii ya mwaloni utoao juisi yenye sukari"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Jani lililoanguka"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Jani likipeperushwa na upepo"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Uyoga"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Nyanya"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Bilinganya"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Zabibu"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Tikiti"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Tikitimaji"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Chenza"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Emoji ya Limao"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Ndizi"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Nanasi"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Tufaha jekundu"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Tufaha la kijani"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Pea"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Pichi"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Mizabibu mwitu"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Stroberi"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Mkate mwembamba unaoliwa kwa kuwekwa vyakula vingine kati kati yake kama nyama na mboga mboga"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Kipande cha pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Nyama iliyoshikiliwa kwenye mfupa"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Paja la nyama kuku"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Biskuti ngumu kiasi iliyotengenezwa kwa unga wa mchele"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Tonge la ubwabwa"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Wali"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Mchuzi mzito na wali"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Bakuli linalofuka mvuke"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spageti, aina fulani ya tambi"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Mkate"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Viazi vya Kifaransa vilivyokatwa kwa urefu na wembamba kisha kukaangwa na kukaushwa sana"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Kiazi cha kuokwa"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango, chakula cha asili cha kijapani ambapo hua na matonge ya wali yaliyoshikizwa kwenye kijiti"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden, chakula cha asili cha kijapani ambapo hua na vyakula aina mbali mbali vimeshikizwa kwenye kijiti"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi, chakula cha asili cha kijapani ambapo hua na aina mbali mbali za vyakula vya asili hasa vya baharini vikichanganywa na wali na kuundwa kiustadi kufuata umbo maalum"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Uduvi wa kukaangwa"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Kipande cha samaki aliyetengenezwa kama keki kikiwa na mchoro unaowakilisha kimbunga katikati."</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Aiskrimu laini"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Kipande cha barafu tamu iliyotengenezwa kilichokatwa katika umbo maalum"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Aiskrimu"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Donati"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Biskuti"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Mchi wa chokoleti"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Peremende"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Faluda au Kastadi"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Emoji ya chungu cha asali"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Keki tamu yenye vitandamlo inayofanana na biskuti"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Chakula cha asili ya kijapan kinachobebwa kwenye kijisanduku maalum"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Chakula cha asili ya kijapani kinachowekwa kwenye chungu maalum, pia huitwa nabemono"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Upishi"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Uma na kisu"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Emoji ya kikombe cha chai kisicho na mshikio"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Chupa ya mvinyo wa kijapani wa mchele na kikombe"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Glasi ya mvinyo"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Glass maalum yenye umbo la V na kitako cha duara, aghalabu hutumika kunywea pombe kali"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Kinywaji cha mchanganyiko wa matunda ya kitropiki"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Kombe la kunywea bia"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Makombe mawili yaliyojaa bia yakigonganishwa kwa mtindo wa kusherehekea"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Chupa maalum ya mtoto"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Utepe"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Zawadi iliyofungwa kwenye karatasi maalum"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Keki ya siku ya kuzaliwa"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Emoji ya boga lililochongwa kiustadi kama sura ya mtu na mshumaa kuwekwa ndani kulifanya liwe na mwanga"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Mkrismasi, pia Mvinje"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Baba Krismasi"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Fataki"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Cheche za fataki"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Puto"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Kifaa cha kufyatua vikaratasi kwa mpigo, aghalabu kwa ajili ya kusherehekea"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Mpira maalum uliowekwa chengechenge za rangi mbalimbali, ambapo ukifunguliwa hutoka na kuleta mwako aghalabu katika sherehe ya harusi"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tawi la mwanzi maalum uliofungwa vijikaratasi vyenye matilaba au matamanio ya watu"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bendera zilizokingamanishwa"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Urembo wa asili ya kijapani wa misonobari na matawi ya mianzi ambao huwekwa mlangoni kuwakilisha heri na bahati, aghalabu hutumika kwenye sherehe za mwaka mpya"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Emoji ya midoli ya kijapani"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Pia Koinobori, vibango maalum vyenye picha za samaki ambavyo hupambwa au kushikwa kwenye siku ya watoto huko Japan, ambapo samaki wakubwa huwakilisha wazazi na wadogo kwa idadi ya watoto katika familia."</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Kifaa kilichofanyizwa kutoa sauti upepo unapovuma"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Sherehe za kutazama mwezi"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Kibegi maalum cha kubebea vifaa vya shule vya mtoto"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Kofia ya Mahafali"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Kifani cha farasi wa kuendeshwa kwenye sehemu ya michezo na burudani"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Gurudumu kubwa la mduara ambalo hua na vijumba maalum ambapo watu hukaa na huzungushwa na mitambo ili kutoa burudani"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Mfano wa reli ndefu ambamo hua na vijumba maalum vilivyoungwa kama treni ambapo watu hukaa na kuendeshwa kwa kwasi na mitambo ili kutoa burudani"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Ndoano na samaki"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Kipaza sauti"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Kamera ya filamu"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Sinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Kifaa cha sauti"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Ubao wa msanii ambao hua na rangi mbali mbali za kuchorea"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Kofia ya pama"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Hema kubwa sana la mduara, aghalabu la kufanyia michezo ya jukwaani"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Tiketi"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Ubao maalum wa milia ambao hutumika kutoa ishara ya mahali na kuanza kitendo wakati wa kurekodi filamu"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Sanaa ya maonyesho"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Mchezo wa video"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Ubao maalum wenye miduara huku ukiwa na kishale kimejikita kati kati kuwakilisha lengo la moja kwa moja la mtupa vishale"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Mashine ya kuchezea michezo ya kubahatisha"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Biliadi"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Kete ya mchezo, aghalabu hua na umba la mchi mraba"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Mchezo wa kuviringisha matufe chini"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Kadi ya mchezo wa Hanafuda wa Kijapan inayowakilisha mwezi wa nane, kati ya kadi kumi na mbili, moja kwa kila mwezi"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota ya muziki"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Nota nyingi za muziki"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksafoni"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Emoji ya Gitaa"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Kibodi ya Muziki"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Tarumbeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Fidla"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Alama ya muziki ambayo hutambulisha kwa mistari ya nota kiwango cha juu cha sauti kinachotakiwa kwa muziki husika"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Nguo maalum kwa ajili ya mbio likiwa na utepe maalum wa utambulisho"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Emoji ya raketi na mpira wa tenisi"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Relitheluji na mabuti ya skii"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Mpira wa kikapu wa rangi ya kahawia nyepesi ukiwa chini"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Ruwaza yenye miraba ya rangi nyeusi na nyeupe ambayo huinuliwa mwazo au mwisho wa mashindano, aghalabu huambatana na mshindi"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Emoji ya mtu akiteleza juu ya barafu kwa kibao maalum"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Mkimbiaji"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Emoji ya mtu akiteleza katika mawimbi meupe kwa ubao"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Kombe, aghalabu taji kwa ajili ya mshindi kwa mashindano husika"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Mashindano ya mbio za farasi"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Mpira wa miguu wa kimarekani"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Mpira wa ragbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Mwogeleaji"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Jengo la nyumba"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Nyumba yenye bustani"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Jengo la ofisi"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Ofisi ya posta ya kijapani"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Ofisi ya posta ya Ulaya"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Emoji ya Hospitali"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Benki"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Machine ya kutolea pesa ya kiotomatiki"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hoteli"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Emoji ya jengo la hoteli ikiwa na ua la upendo"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Maduka yanayofikiwa kwa urahisi"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Emoji ya Shule"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Duka la idara"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Kiwanda"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Alama ya asili ya kijapani yenye mfano wa taa iliyo ndani ya chombo kilichofungwa pande zote ikiwakilisha sehemu ya biashara au mahali panapouzwa chakula na mvinyo"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Kasri la kijapani"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Kasri la Ulaya"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Panya buku"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Panya"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Maksai"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Nyati wa majini"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Emoji ya Ng\'ombe"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Chui"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Sungura"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Paka"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Joka, aghalabu kwenye hadithi za asili za China,Japan na Korea"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Mamba"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Nyangumi"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Konokono"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Nyoka"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Farasi"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Kondoo Mume, aghalabu mwenye uwezo wa kuzalisha"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Mbuzi"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Kondoo"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Tumbili"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Jogoo"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Kuku"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Mbwa"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Nguruwe"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Nguruwe dume, aghalabu mwenye uwezo wa kuzalisha"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Tembo"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pweza"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Jumba la konokono au viumbe wengine wa jamii hiyo ambalo limejikunja kama duara inayoanzia ndani kuelekea nje"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Mdudu"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Chungu chungu"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Nyuki wa asali"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Kombamwiko jike"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Samaki"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Samaki wa kitropiki"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Samaki mwenye miiba mwenye tabia ya kufutuka au kufura anapohisi hatari"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Kobe"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Kifaranga wa kuku akitotolewa kwenye yai"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Kifaranga wa kuku mdogo"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Kifaranga wa kuku anayeangalia mbele"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ndege"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pengwini, ndege mnene wa majini mwenye rangi nyeusi na nyeupe na miguu mifupi asiyeweza kuruka angani"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala, dubu mdogo wa Australia migodini"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Emoji ya jibwa lenye asili ya manyoya mengi sana yaliyojikunja"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Ngamia wa asili ya mashariki ya kati mwnye nundu moja"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Ngamia wa asili ya Asia ya kati mwenye nundu mbili"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Pomboo"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Uso wa panya"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Uso wa ng\'ombe"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Uso wa Duma"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Uso wa sungura"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Uso wa paka"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Uso wa joka"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Nyangumi anayevurumisha maji juu"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Uso wa farasi"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Uso wa tumbili"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Uso wa mbwa"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Uso wa nguruwe"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Uso wa chura"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Emoji ya uso wa panya buku"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Uso wa mbwa mwitu"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Uso wa dubu"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Uso wa panda, aina ya dubu wa rangi nyeusi na nyeupe apatikanaye Tibeti"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Pua ya nguruwe"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Alama za uwayo wa mnyama"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Macho"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Sikio"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Pua"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Mdomo"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Ulimi"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Ishara ya mkono unaoonekana kwa nyuma ukiwa umenyoosha kidole kuelekea juu"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Ishara ya mkono unaoonekana kwa nyuma ukiwa umenyoosha kidole kuelekea chini"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Ishara ya mkono unaoonekana kwa nyuma ukiwa umenyoosha kidole kuelekea kushoto"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Ishara ya mkono unaoonekana kwa nyuma ukiwa umenyoosha kidole kuelekea kulia"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Ishara ya mkono uliokunja ngumi"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Ishara ya  mkono ukipunga"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Ishara ya mkono ikimaanisha Sawa"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Ishara ya kidole gumba kuinuliwa juu ikiwakilisha mambo bomba"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Ishara ya kidole gumba kuinamishwa chini ikiwakilisha mambo sio safi"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Ishara ya mikono inapiga makofi"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Ishara ya mikono ikiwa wazi"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Taji"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Kofia ya mwanamke"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Miwani"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Tai"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Fulana"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jinzi au Dengrizi"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Gauni"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Vazi la kike kama gauni refu lenye mikono mirefu la asili ya kijapani ambalo huvaliwa na mkanda mpana kiunoni"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Mavazi ya kike"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Mfuko wa fedha"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Begi dogo la mkononi"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pochi"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Kiatu cha kiume"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Kiatu cha riadha"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Emoji ya kiatu chenye kisigino kirefu"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Kiatu cha wazi cha kike"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Mabuti ya kike"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Alama za nyayo"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Taswira ya umbo au kivuli cha mtu aliyepenya au kuvunja mahali"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Taswira mbili za maumbo au vivuli vya watu waliopenya au kuvunja mahali"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Mvulana"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Msichana"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Mwanaume"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Mwanamke"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Familia"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Mwanaume na mwanamke wameshikana mikono"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Wanaume wawili wameshikana mikono"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Wanawake wawili wameshikana mikono"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Afisa wa polisi"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Mwanamke aliyevalia kama sungura aghalabu anayehudumia kwenye baa"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Mwanamwali au bi harusi aliyevaa shela"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Mtu mwenye nywele zenye rangi ya shaba au rangi ya kimanjano"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Mwanaume akiwa amevaa kofia maalum ya kichina"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Mwanaume aliyevaa kilemba"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Mwanaume mzee"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Mwanamke mzee"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Mtoto"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Mfanyakazi wa shughuli za ujenzi akiwa na kofia ngumu ya manjano"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Binti Mfalme"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Kinyago cha shetani mwekundu wa kijapani"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Kinyago cha zimwi jekundu lenye mfano wa ndege la kijapani"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Mzimu"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Emoji ya malaika mtoto mwenye mbawa na duara ya mwangaza wa samawati kichwani"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Emoji ya kiumbe mgeni kutoka sayari nyingine tofauti na dunia"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Emoji ya jinamizi la kigeni, aghalabu kwenye hadithi za wavamizi kutika nje ya dunia waliokua na teknolojia kubwa"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Emoji ya shetani mdogo mwenye pembe aliyekasirika"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Fuvu"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Emoji ya mtu wa dawati la maelezo"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Mlinzi"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Mcheza dansi"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Rangi ya midomo"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Rangi ya kucha"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Emoji ya mtu akichuliwa au kusingwa uso"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Emoji ya mtu akikata nywele"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Emoji ya ufito wa kinyozi"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Sindano aghalabu ya kutumika kuchomea dawa kwa mtu au myama"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Kidonge"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Alama ya busu"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Barua ya kimapenzi"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Pete"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Jiwe la kito"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Busu"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Maua mazuri yaliyofungwa pamoja"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Emoji ya wanandoa na kifani cha moyo"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Harusi"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Emoji ya moyo unaodunda"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Emoji ya moyo uliovunjika"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Emoji ya mioyo miwili"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Emoji ya moyo unaong\'aa"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Emoji ya moyo unaokua"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Emoji ya moyo na mshale"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Emoji ya moyo wa rangi ya samawati"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Emoji ya moyo wa rangi ya kijani"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Emoji ya moyo wa rangi ya manjano"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Emoji ya moyo wa rangi ya zambarau"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Emoji ya moyo uliofungwa utepe"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Emoji ya mioyo inayozunguka"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Emoji ya kitufe kilichopambwa ua la moyo"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Umbo la almasi ikiwa na kidoa kati kati"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Taa ya balbu ya umeme"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Emoji ya ishara ya hasira"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Emoji ya Bomu"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Emoji ya ishara ya hali tuli au kulala"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Emoji ya ishara ya mgongano"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Emoji ya alama ya jasho likitiririka"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Emoji ya tone aghalabu la maji"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Emoji ya ishara ya kitu kilichoondoka kwa ghafla sana kutimua vumbi nyumba"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Rundo la kinyesi"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Emoji ya mkono uliotunisha msuli"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Emoji ya ishara ya kizunguzungu"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Emoji ya kiputo kinachoashiria mtu alikua anasema"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Emoji ya kiputo kinachoashiria mtu alikua anawaza"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Emoji ya ua jeupe"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Emoji ya alama mia ya mia"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Emoji ya mfuko wa pesa"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Emoji ya mbadilishano wa sarafu"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Emoji ya alama ya dola iliyokolezwa"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Emoji ya kadi ya mkopo"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Emoji ya noti ya benki yenye alama ya fedha ya japan yaani yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Emoji ya noti ya benki yenye alama ya dola"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Emoji ya noti ya benki yenye alama ya fedha ya ulaya yaani yuro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Emoji ya noti ya benki yenye alama ya fedha ya uingereza yaani pauni"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Emoji ya pesa iliyo na mbawa"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Emoji ya chati yenye alama ya yen na ikionesha kupanda aghalabu thamani"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Emoji ya kiti cha kukalia aghalabu kwenye ndege"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Emoji ya kompyuta ya mezani"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Emoji ya mkoba"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Emoji ya diski iliyohifadhiwa kwenye kasha maalum"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Emoji ya diski tepe"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Emoji ya diski yenye uwezo wa kuhifadhi picha"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Emoji ya diski ya dijitali ya video"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Emoji ya folda la faili"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Emoji ya folda la faili lililofunguliwa"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Emoji ya ukurasa uliojikunja"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Emoji ya ukurasa unaoangalia juu"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalenda"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Emoji ya kalenda maalum ya kufuatilia aghalabu hutumiwa na mashirika ambapo tukio la tarehe maalum inayofuatiliwa likikamilika, karatasi lenye tarehe husika huondolewa kwa kuchanwa"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Emoji ya kifaa maalum cha kuhifadhia kadi zenye anwani na mawasiliano ya watu"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Emoji ya chati inayoonesha grafu ikipanda"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Emoji ya chati inayoonesha grafu ikishuka"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Emoji ya chati inayotumia miche kuwakilisha data zake"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Emoji ya ubao maalum wenye kishikizio cha karatasi, aghalabu kwa urahisi wa kuandika au kusoma"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Emoji ya kipini maalum kinachotumika kushikizia karatasi ukutani"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Emoji ya kipini chenye kichwa cha mduara kinachotumika kushikizia karatasi kwenye kuta maalum zinazoweza kutumika na vipini hivyo"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Emoji ya kibanio cha karatasi"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Emoji ya rula nyoofu"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Emoji ya rula ya pembetatu"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Emoji ya vichupo vya alamisho"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Emoji ya leja"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Emoji ya daftari"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Emoji ya daftari yenye jalada lenye urembo"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Emoji ya kitabu kimefungwa"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Emoji ya kitabu kimefunguliwa"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Emoji ya kitabu cha rangi ya kijani"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Emoji ya kitabu cha rangi ya samawati"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Emoji ya kitabu cha rangi ya manjano"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Emoji ya vitabu"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Emoji ya beji ya jina"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Emoji ya hati ndefu ya kukunja kwa kuvingirisha hasa zile za zamani"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Emoji ya kikaratasi cha kuchukulia taarifa muhimu au kumbukumbu"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Emoji ya risiva ya simu"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Emoji ya kifaa maalum ambacho kinataarifa za vikumbusho mbali mbali kama kupiga simu"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Emoji ya mashine ya faksi"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Emoji ya antena ya setilaiti"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Emoji ya kipaza sauti cha kuzungumzia kwenye umma"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Emoji ya kifaa mfano wa tarumbeta kwa ajili ya kushangilia aghalabu huitwa vuvuzela kwenye baadhi ya maeneo"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Emoji ya kikasha toezi cha kuhifadhia aghalabu jumbe au barua zinazopaswa kuelekea mahali husika"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Emoji ya kikasha hifadhi ambacho hua na jumbe au barua zilizowasili"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Emoji ya kifurushi"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Emoji ya alama ya barua pepe"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Emoji ya bahasha ikishuka, ishara ya barua au ujumbe unaongia"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Emoji ya bahasha ikiwa na mshale kwa juu unaoangalia chini, ishara ya tuma kwenye barua pepe"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Emoji ya kisanduku cha barua ambacho bendera yake imeshushwa, ikimaanisha hakuna barua au vifurushi vya kuondoka"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Emoji ya kisanduku cha barua ambacho bendera yake imeinuliwa, ikimaanisha kuna barua au vifurushi vya kuondoka"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Emoji ya kisanduku cha barua kilichowazi ambacho bendera yake imeinuliwa, ikimaanisha kuna barua au vifurushi vya kuondoka"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Emoji ya kisanduku cha barua kilichowazi ambacho bendera yake imeshushwa, ikimaanisha hakuna barua au vifurushi vya kuondoka"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Emoji ya sanduku la posta"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Emoji ya king\'ora maalum au honi ipigwayo kuomba njia ili kuwahisha barua au vifurushi mahali husika"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Emoji ya Gazeti"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Emoji ya simu ya mkononi"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Emoji ya simu ya mkononi ikiwa na mshale upande wa kushoto unaooneshea kulia au uelekeo wa simu ilipo, ikiwakilisha tuma kwenye simu"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Emoji inayowakilisha hali ya mtetemo pekee, aghalabu kwenye maeneo kama maktaba, majumba ya ibada nk"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Emoji ya picha ya simu ikiwa katika hali ya kuzimwa"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Emoji ya simu ikiwa ndani ya duara na msitari umepita kati kati, ikimaanisha matumizi ya simu hayaruhusiwi kwenye eneo hilo"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Emoji ya michi kwenye sehemu ya kijisanduku cha mnara wa simu, kikiwakilisha nguvu ya mawimbi yaliyopo"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Emoji ya kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Emoji ya kamera ya kuchukulia video"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Emoji ya televisheni"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Emoji ya redio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Emoji ya kanda ya video"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Emoji ya mishale inayoelekea kulia ikiwa imepishana"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Emoji ya mishale iliyochorwa kufuata mwendo saa kama duara mmoja ukielekea kulia na mwingine kushoto, ikimaanisha kujirudia kwa tendo husika"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Emoji ya mishale iliyochorwa kufuata mwendo saa kama duara mmoja ukielekea kulia na mwingine kushoto, huku kukiwa na namba moja iliyondani ya duara juu yake  ikimaanisha kujirudia mara moja tu kwa tendo husika"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Emoji ya mishale iliyochorwa kufuata mwendo saa kama duara mmoja ukielekea juu na mwingine chini, ikimaanisha rudia tena tendo husika aghalabu kwenye kupakia programu za vifaa"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Emoji ya mishale iliyochorwa kwa mwendo wa kinyume saa kama duara mmoja ukielekea juu na mwingine chini, ambayo huwakilisha kurudia kwa tendo husika"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Emoji ya mduara uliozungukwa na vistari vifupi ikimaanisha ung\'avu kiasi kidogo, aghalabu kwenye kompyuta au simu ya mkononi humaanisha matumizi ya mwangaza kidogo wa skrini"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Emoji ya mduara uliozungukwa na vistari virefu ikimaanisha ung\'avu sana, aghalabu kwenye kompyuta au simu ya mkononi humaanisha matumizi ya mwangaza mkubwa wa skrini"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Emoji ya spika ikiwa na alama ya mstari wa kukata, aghalabu kwenye matumizi ya simu au kompyuta humaanisha kuzima matumizi ya sauti"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Emoji ya spika"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Emoji ya spika ikiwa na alama ya wimbi moja la sauti, aghalabu kwenye matumizi ya simu au kompyuta humaanisha matumizi ya sauti ya chini"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Emoji ya spika ikiwa na alama ya mawimbi matatu ya sauti, aghalabu kwenye matumizi ya simu au kompyuta humaanisha matumizi ya sauti ya juu"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Emoji ya betri"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Emoji ya plagi ya umeme"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Emoji ya lenzi ikiwa imeegemea upande wa kushoto"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Emoji ya lenzi ikiwa imeegemea upande wa kulia"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Emoji ya kufuli na kalamu ya wino, aghalabu kwenye nyaraka za kielectroniki humaanisha ni inayolindwa na imefungwa"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Emoji ya kufuli na ufunguo"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Emoji ya ufunguo"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Emoji ya kufuli"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Emoji ya kufuli lililofunguliwa"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Emoji ya kengele"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Emoji ya kengele ikiwa na alama ya mstari wa kukata, aghalabu kwenye matumizi ya simu au kompyuta humaanisha kuzima matumizi ya sauti"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Emoji ya alamisho"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Emoji ya kiungo"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Emoji ya kitufe cha redio"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Emoji yenye neno back na mshale unaoonesha kushoto ukiwa juu yake, aghalabu ikimaanisha rudi nyuma, nenda mwanzo wa wimbo, filamu, hadithi nk"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Emoji yenye neno end na mshale unaoonesha kushoto ukiwa juu yake, ikimaanisha nenda mwisho wa jambo, ingawa yaweza pia kumaanisha rudi nyuma, nenda mwanzo wa wimbo, filamu, hadithi nk kwenye matumizi ya hangout na android"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Emoji ya neno On na mshale unaoonesha pande zote ukiwa juu yake, ikimaanisha uamuzi wa kusonga mbele kwa furaha, au njia zote zitakufikisha kwenye lengo iwe ya kushoto au kulia"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Emoji yenye neno Soon na mshale unaoonyesha upande wa kulia ukiwa juu yake, ikimaanisha jambo, au tukio litatokea baada ya muda mfupi"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Emoji yenye neno Top na mshale unaoonyesha juu ukiwa juu yake, ikimaanisha nenda juu aghalabu kwenye kurasa za tovuti nk"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Emoji ya namba kumi na nane ikiwa ndani ya duara na msitari umepita kati kati, ikimaanisha matumizi ya kitu husika hayaruhusiwi kwa mtu wa chini ya umri wa miaka kumi na minane"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Emoji ya kitufe cha kibodi chenye namba kumi"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Emoji ya kitufe cha kibodi kwa ajili ya kugeuza herufi kuwa kubwa"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Emoji ya kitufe cha kibodi kwa ajili ya kugeuza herufi kuwa ndogo"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Emoji ya kitufe cha kibodi kwa ajili ya kupata uandishi wa namba"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Emoji ya kitufe cha kibodi kwa ajili ya kupata uandishi wa alama"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Emoji ya kitufe cha kibodi kwa ajili ya kupata uandishi wa herufi"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Emoji ya moto"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Emoji ya tochi ya umeme"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Emoji ya spana inayorekebishika kuweza kufunga nati za ukubwa mbali mbali"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Emoji ya nyundo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Emoji ya nati na bolti"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Emoji ya kisu cha jikoni"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Emoji ya bastola"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Emoji ya hadubini"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Emoji ya darubini maalum aghalabu kwa kuangalizia anga za mbali"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Emoji ya tufe la kioo"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Emoji ya nyota yenye pembe sita ikiwa na alama ya kitone kati kati"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Emoji ya alama ya kijapani inayowakilisha mtu ambaye bado hana uzoefu kama vile dereva ambaye bado anajifunza"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emoji ya nembo ya nanga"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Emoji ya kitufe cha umbo la mraba cha rangi nyeusi"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Emoji ya kitufe cha umbo la mraba cha rangi nyeupe"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Emoji ya duara kubwa la rangi nyekundu"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Emoji ya duara kubwa la rangi ya samawati"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Emoji ya almasi kubwa ya rangi ya manjano"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Emoji ya almasi kubwa ya rangi ya samawati"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Emoji ya almasi ndogo ya rangi ya manjano"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Emoji ya almasi ndogo ya rangi ya samawati"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Emoji ya pembetatu ya rangi nyekundu inayoangalia juu"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Emoji ya pembetatu ya rangi nyekundu inayoangalia chini"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Emoji ya pembetatu ndogo ya rangi nyekundu inayoangalia juu"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Emoji ya pembetatu ndogo ya rangi nyekundu inayoangalia chini"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Emoji ya uso wa saa inayoonesha saa saba kamili"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Emoji ya uso wa saa inayoonesha saa nane kamili"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Emoji ya uso wa saa inayoonesha saa tisa kamili"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Emoji ya uso wa saa inayoonesha saa tisa kamili"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Emoji ya uso wa saa inayoonesha saa kumi na moja kamili"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Emoji ya uso wa saa inayoonesha saa kumi na mbili kamili"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Emoji ya uso wa saa inayoonesha saa moja kamili"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Emoji ya uso wa saa inayoonesha saa mbili kamili"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Emoji ya uso wa saa inayoonesha saa tatu kamili"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Emoji ya uso wa saa inayoonesha saa nne kamili"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Emoji ya uso wa saa inayoonesha saa tano kamili"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Emoji ya uso wa saa inayoonesha saa sita kamili"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Emoji ya uso wa saa inayoonesha saa saba na nusu"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Emoji ya uso wa saa inayoonesha saa nane na nusu"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Emoji ya uso wa saa inayoonesha saa tisa na nusu"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Emoji ya uso wa saa inayoonesha saa kumi na nusu"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Emoji ya uso wa saa inayoonesha saa kumi na moja na nusu"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Emoji ya uso wa saa inayoonesha saa kumi na mbili na nusu"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Emoji ya uso wa saa inayoonesha saa moja na nusu"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Emoji ya uso wa saa inayoonesha saa mbili na nusu"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Emoji ya uso wa saa inayoonesha saa tatu na nusu"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Emoji ya uso wa saa inayoonesha saa nne na nusu"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Emoji ya uso wa saa inayoonesha saa tano na nusu"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Emoji ya uso wa saa inayoonesha saa sita na nusu"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Emoji ya mlima Fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Emoji ya mnara wa Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Emoji ya Sanamu ya uhuru"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Emoji ya ramani ya Japan kama inavyoonekana katika bahari ya Pasifiki"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Emoji ya Moyai, sanamu ya kuchonga iliyopo katika mji wa Tokyo huko Japani kwenye kituo cha Shibuya, mahali ambapo hufikiwa na watu wengi wanaoitembelea nchi hiyo"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Emoji ya uso unaoonyesha furaha kwa tabasamu pana"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Emoji ya uso unaoonyesha furaha na macho ya tabasamu"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Emoji ya uso wenye machozi ya furaha"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Emoji ya uso wa tabasamu kwa kinywa wazi"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Emoji ya uso wa tabasamu kwa kinywa wazi na macho yaliyosinzia kwa tabasamu"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Emoji ya uso wa tabasamu kwa kinywa wazi na kijasho chembamba"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Emoji ya uso wa tabasamu kwa kinywa wazi na macho yaliyofinywa kwa nguvu"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Emoji ya uso wa tabasamu na duara ya mwangaza inayozunguka kichwa ikiwakilisha malaika"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Emoji ya uso wa tabasamu wenye pembe kichwani"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Emoji ya uso unaokonyeza"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Emoji ya uso wa tabasamu na macho yaliyosinzia kwa tabasamu"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Emoji ya uso wa kutamani chakula kitamu, pia aliyemaliza kula chakula kitamu hivyo anajilamba midomo"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Emoji ya uso unaoonesha hali ya kufarijika au kuridhishwa na hali ya mambo"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Uso wa tabasamu na macho yaliyoumbwa kama ua la moyo, ishara ya mapenzi mazito juu ya mtu au kitu kinachotazamwa"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Emoji ya uso wa tabasamu ukiwa umevaa miwani ya jua"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Emoji ya uso wa kicheko cha dharau"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Emoji ya uso wa kawaida"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Emoji ya uso usioonyesha hisia yoyote"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Emoji ya uso unaoonyesha kutoridhishwa na hali ya mambo"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Emoji ya uso wenye kijasho chembamba"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Emoji ya uso unaoonyesha mtu aliyezama katika lindi la mawazo"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Emoji ya uso unaoonyesha mtu aliyechanganyikiwa pengine kutokana na mambo kutokueleweka au kutokua katika utaratibu"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Emoji ya uso unaoonyesha hasira, kuuma midomo na kukunja sura pengine kutokana na mambo kutokuelewaeka au kutokua katika utaratibu"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Emoji ya uso unaoonyesha busu"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Emoji ya uso unaotupia busu"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Emoji ya uso ukibusu na macho ya tabasamu kwa hisia"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Emoji ya uso ukibusu na macho yaliyosinzia kwa hisia"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Emoji ya uso uliotoa ulimi nje"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Emoji ya uso uliotoa ulimi nje na macho ya kukonyeza"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Emoji ya uso uliotoa ulimi nje na macho yaliyofumbwa kwa nguvu"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Emoji ya uso unaoonyesha hali ya kukatishwa tamaa"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Emoji ya uso wa wasiwasi"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Emoji ya uso wa hasira"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Emoji ya uso uliokunja sura kwa manung\'uniko"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Emoji ya uso unaolia machozi"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Emoji ya uso unaoonyesha hali ya kuvumilia"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Emoji ya uso unaoonyesha ushindi"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Emoji ya uso unaoonyesha kukatishwa tamaa lakini umeamua kuridhika na hali ya mambo"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Emoji ya uso unaoonyesha hali ya kutopendezwa na jambo"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Emoji ya uso unaoonyesha hali ya uchungu"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Emoji inayoonyesha uso wa woga"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Emoji inayoonyesha uso wa uchovu wa hali ya juu"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Emoji inaoonyesha uso wa kusinzia"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Emoji ya uso unaoonyesha uchovu"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Emoji ya uso unaoonyesha kukunja sura kwa maumivu au kuchekesha meno yote yakionekana"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Emoji inayoonyesha uso wa kulia kwa nguvu"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Emoji ya uso ukiwa kinywa wazi"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Emoji ya uso unaosubiri kimya, kwa utulivu na subira"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Emoji ya uso ukiwa kinywa wazi na kijasho chembamba"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Emoji ya uso unaopiga kelele za woga"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Emoji ya uso unaoonyesha hali ya kushangazwa sana"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Emoji ya uso uliotumbua macho"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Emoji inayoonyesha uso wa mtu aliye katika hali tuli fofofo"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Emoji inayoonyesha uso wenye kizunguzungu"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Emoji inayoonyesha uso usio na mdomo"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Emoji ya uso uliovaa barakoa ya kitabibu"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Emoji ya uso wa paka unaoonyesha furaha na macho ya tabasamu"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Emoji ya uso wa paka wenye machozi ya furaha"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Emoji ya uso wa paka wenye tabasamu pana na mdomo wazi"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Uso wa paka wenye tabasamu na macho yaliyoumbwa kama ua la moyo, ishara ya mapenzi mazito juu ya mtu au kitu kinachotazamwa"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Emoji ya uso wa paka unaoonyesha hali ya dharau au mzaha"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Emoji ya uso wa paka ukibusu na macho yaliyosinzia kwa hisia"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Emoji ya uso wa paka uliokunja sura kwa manung\'uniko"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Emoji ya uso wa paka alieangua kilio"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Emoji ya uso wa paka unaoonyesha uchovu wa hali ya juu"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Emoji ya uso pamoja na ishara ya kuonyesha kutokukubaliana na kinachoendelea au kukataza kisiendelee, aghalabu hua na mtu aliyepishanisha mikono ili kufanya alama ya x"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Emoji ya uso na ishara ya sawa, kukubaliana na kinachofanyika au kukubali"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Emoji ya mtu aliyeinama sana, karibu na kusujudu"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Emoji ya tumbili aliyeaficha uso wake, hujulikana kama asiyetaka kuona mabaya yatakayotendeka"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Emoji ya tumbili aliyeziba masikio yake, hujulikana kama asiyetaka kusikia mabaya yatakayosemwa"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Emoji ya tumbili aliyefumba kinywa kwa mikono yake, hujulikana kama asiyetaka kunena baya lolote"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Emoji ya mtu mwenye furaha akiwa amenyanyua mkono mmoja"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Emoji ya mtu anayeshangilia akiwa amenyanyua mikono yote"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Emoji ya mtu anayeonyesha hali ya kutopendezwa na jambo"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Emoji ya mtu aliyekunja sura kwa manung\'uniko"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Emoji ya mtu amekunja mikono"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Emoji ya Roketi"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Emoji ya Helikopta"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Emoji ya Garimoshi"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Emoji ya gari linaloendeshwa kwenye reli maalum"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Emoji ya Treni iendayo kasi"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Emoji ya Treni iendayo kasi ikiwa na kichwa kilichotengenezwa kwa mfano wa risasi"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Emoji ya Treni"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Emoji ya metro, neno litalotumika aghalabu kuelezea mfumo wa usafirishaji watu kwenye miji kwa kutumia treni hasa ziendazo kasi za ardhini"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Emoji ya treni ya usafirishaji watu na mizigo miepesi kwenye miji kwa mwendo kasi"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Emoji ya Kituo"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Emoji ya treni ambayo hufanya kazi ndogo ndogo za kusafirisha abairia kwenye umbali mfupi"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Emoji ya behewa la treni ambayo hufanya kazi ndogo ndogo za kusafirisha abairia kwenye umbali mfupi"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Emoji ya basi"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Emoji ya basi linaloonekana kuja"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleybus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Emoji ya basi linaloendeshwa kwa nguvu za umeme"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Emoji ya basi dogo"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Emoji ya gari la wagonjwa"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Emoji ya gari lenye injini maalum kwa ajili ya kusukuma maji kwa mgandamizo kubwa ili kuzima moto"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Emoji ya gari la polisi"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Emoji ya gari la polisi linaloonekana kuja"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Emoji ya teksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Emoji ya teksi inayoonekana kuja"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Emoji ya gari"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Emoji ya gari inayoonekana kuja"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Emoji ya gari kubwa uwezo mkubwa kidogo kuliko gari ya kawaida"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Emoji ya gari ya usambazi mizigo"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Emoji ya lori linalokokota tela au mtambaazi"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Emoji ya trekta"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Emoji ya reli moja, ambapo treni hupita kanakwamba imeivaa"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Emoji ya reli inayoelekea mlimani"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Emoji ya reli inayopita juu"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Emoji ya waya ambapo gari maalum kusafirisha watu au mizigo kwenye eneo lenye mlima mkali hupita kwenye waya huo kwa kuning\'inia"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Emoji ya muonekano wa mbali wa gari maalum la kusafirisha watu au mizigo kwenye eneo lenye mlima mkali na hupita kwenye waya"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Emoji ya meli"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Emoji ya mtumbwi"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Emoji ya boti inayoendeshwa kwa injini hivyo kua na kasi zaidi"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Emoji ya taa za trafiki zilizowekwa mlalo"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Emoji ya taa za kuongozea magari zilizowima"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Emoji inayoonyesha ishara ya kwamba ujenzi unaendelea"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Emoji ya taa ya gari ya polisi ambayo huzunguka ili kutoa ishara"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Emoji ya mti wa bendera ya pembetatu, aghalabu hutumika kama kiashiria"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Emoji ya mlango"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Emoji ya duara na msitari uliokingama umepita kati kati, ikiwa ni ishara ya katazo la kuingia katika eneo hilo"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Emoji ya sigara iliyowashwa inayotoa moshi"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Emoji ya duara lenye picha ya sigara ndani na msitari uliokatiza kati kati ya sigara, ikimaanisha uvutaji wa sigara hauruhusiwi kwenye eneo hilo"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Emoji ya ishara ya maelekezo ya mahali maalum pa kutupia taka"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Emoji ya ishara ya maelekezo ya kutotupa taka mahali hapo"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Emoji ya ishara ya maji ya bomba lakini yaliyo salama kwa matumizi hasa kunywa"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Emoji ya ishara ya maji ya bomba yasiyo salama kwa matumizi hasa kunywa"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Emoji ya baiskeli"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Emoji ya baiskeli ndani ya duara na msitari uliokingama umepita kati kati, ikiwa ni ishara ya katazo la baiskeli kuingia katika eneo hilo"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Emoji ya mwendesha baiskeli"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Emoji ya mwendesha baiskeli ya milimani"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Emoji ya mwenda kwa miguu"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Emoji ya mwenda kwa miguu ndani ya duara na msitari uliokingama umepita kati kati, ikiwa ni ishara ya katazo la waenda kwa miguu kuingia katika eneo hilo"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Emoji ya kivuko cha watoto"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Emoji ya ishara ya mwanaume, aghalabu kuashiria kua kitu au mahali husika ni maalum kwa ajili ya kutumiwa na wanaume"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Emoji ya ishara ya mwanamke, aghalabu kuashiria kua kitu au mahali husika ni maalum kwa ajili ya kutumiwa na wanawake"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Emoji inayoonesha picha ya mwanaume na mwanamke, aghalabu huwekwa kwenye maliwato ambazo zinaweza kutumika na watu wa jinsia zote"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Emoji ya mtoto"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Emoji ya msala, nyumba maalum ya kujihifadhi kwa haja"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Emoji ya neno WC, namna ya kiingereza kusema bafuni"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Emoji ya bomba la maji ya kuoga yanayotoka kwa rasha rasha, aghalabu huitwa bomba la mvua"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Emoji ya bafu"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Emoji ya hodhi la kuogea"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Emoji ya eneo linalodhibitiwa na pasipoti"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Emoji ya mamlaka ya forodha"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Emoji ya sehemu ya madai ya mizigo"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Emoji inayoonyesha mahali ambapo wanaweza kuchukua mizigo waliyoisahau"</string>
+</resources>
diff --git a/java/res/values-sw/strings-talkback-descriptions.xml b/java/res/values-sw/strings-talkback-descriptions.xml
index 6f84aa8..84c8d3a 100644
--- a/java/res/values-sw/strings-talkback-descriptions.xml
+++ b/java/res/values-sw/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Hakuna maandishi yaliyoingizwa"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> hurekebisha <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> kuwa <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> hufanya marekebisho otomatiki"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Hakuna pendekezo"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Herufi isiyojulikana"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Alama zaidi"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Herufi I kubwa, alama ya kitone inayowekwa sehemu ya juu ya herufi katika alfabeti za Kilatini na Kivietnamu"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Alama isiyojulikana"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Emoji isiyojulikana"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Kikaragosi cha uso uliochoka"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Kikaragosi cha uso ulio tahayari"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Kikaragosi cha uso uliovaa miwani ya jua"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Kikaragosi cha uso unaoonyesha kushangaa"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Kikaragosi cha uso unaoonyesha busu"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Kikaragosi cha uso uliokunja ndita"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Herufi mbadala zinapatikana"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Herufi mbadala huondolewa"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Mapendekezo mbadala yanapatikana"</string>
diff --git a/java/res/values-sw/strings.xml b/java/res/values-sw/strings.xml
index 8f2a662..e2471fb 100644
--- a/java/res/values-sw/strings.xml
+++ b/java/res/values-sw/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tetema unabofya kitufe"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Toa sauti unapobofya kitufe"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Ibuka kitufe kinapobonyezwa"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Mapendeleo"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Akaunti na Faragha"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Mwonekano na Mipangilio"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Kuandika kwa Ishara"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Masahihisho ya maandishi"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Mahiri"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Mandhari"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Washa muundo wa kibodi inayogawanyika"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Usawazishaji wa Kibodi ya Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Usawazishaji umewashwa"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Sawazisha kamusi yako binafsi katika vifaa vyote"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Sawazisha sasa"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Futa data ya wingu"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Hufuta data yako iliyosawazishwa kutoka Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Data yako iliyosawazishwa itafutwa kutoka kwenye wingu. Je, una uhakika?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Futa"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Ghairi"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Kamusi yako ya kibinafsi itasawazishwa na nakala ihifadhiwe kwenye seva za Google. Maelezo ya takwimu ya marudio ya maneno yanaweza kukusanywa ili kusaidia kuboresha bidhaa zetu. Ukusanyaji na matumizi ya maelezo haya yatatii "<a href="https://www.google.com/policies/privacy">"Sera ya Faragha ya Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Tafadhali ongeza akaunti ya Google kwenye kifaa hiki ili uwashe kipengele hiki"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Badilisha hadi kwa mbinu zingine za ingizo"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ufunguo wa kubadilisha lugha unashughulikia mbinu zingine za ingizo pia"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Kitufe cha kubadilisha lugha"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Onyesha wakati lugha ingizo mbalimbali zinapowezeshwa"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Onyesha kiashirio cha slaidi"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Onyesha ishara dhahiri unapotelezesha kutoka kwenye vitufe vya Shift au Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Kuchelewesha kutupa kitufe ibukizi"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Hakuna kuchelewa"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Chaguo-msingi"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Kamusi kuu"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Onyesha mapendekezo ya marekebisho"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Onyesha maneno yaliyopendekezwa wakati unachapa"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Onyesha kila wakati"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Onyesha katika hali wima"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Ficha kila wakati"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Zuia maneno yanayokera"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Usipendekeze maneno yanayoweza kukera"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Usahihishaji otomatiki"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Kibao cha kuweka data kwa kutamka"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Hakuna mbinu ya kuweka data kwa kutamka iliyowashwa. Angalia Lugha na mipangilio ya kuingiza data."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Tuma maoni"</string>
-    <string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Lugha"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Usaidizi na maoni"</string>
+    <string name="select_language" msgid="5709487854987078367">"Lugha"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Gusa hapa ili uhifadhi"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Maandhari ya kibodi"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Badili akaunti"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Hakuna akaunti zilizochaguliwa"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Kwa sasa unatumia <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"SAWA"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Ghairi"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Toka"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Chagua akaunti ya kutumia"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Kiingereza cha (Uingereza)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Kiingereza cha (Marekani)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Kihispania (Marekani)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Kiserbia (Kilatino)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Kiingereza (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Kiingereza (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Kihispania (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Kiserbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (cha Jadi)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kikriliki)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kilatini)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Thabiti)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Hakuna lugha (Alfabeti)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabeti (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabeti (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabeti (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabeti (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Mandhari ya kibodi"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Mitindo maalum ya ingizo"</string>
     <string name="add_style" msgid="6163126614514489951">"Ongeza mtindo"</string>
     <string name="add" msgid="8299699805688017798">"Ongeza"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Washa"</string>
     <string name="not_now" msgid="6172462888202790482">"Sio sasa"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Mfumo sawa wa maingizo tayari upo: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ubofyaji kitufe kunakochelewa"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Bonyeza kitufe cha muda wa kutetema"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Bonyeza kitufe cha kiwango cha sauti"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Soma faili ya kamusi ya nje"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Hakuna faili za kamusi katika folda ya Vilivyopakuliwa"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chagua faili ya kamusi ya kusakinisha"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Ungependa kusakinisha faili hii ya <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Kulikuwa na hitilafu"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ubofyaji kitufe kunakochelewa"</string>
     <string name="button_default" msgid="3988017840431881491">"Chaguo-msingi"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Karibu kwenye <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"kwa Kuandika kwa ishara"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Sasa unaweza kuchapa programu zako zote uzipendazo ukitumia <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Sanidi lugha za ziada"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Imemaliza"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Onyesha ikoni ya programu"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Onyesha ikoni ya programu kwenye kizinduzi"</string>
     <string name="app_name" msgid="6320102637491234792">"Programu ya kamusi"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Programu ya kamusi"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Huduma ya Kamusi"</string>
diff --git a/java/res/values-ta-rIN/strings-emoji-descriptions.xml b/java/res/values-ta-rIN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..863449d
--- /dev/null
+++ b/java/res/values-ta-rIN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"பதிப்புரிமைச் சின்னம்"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"பதிவுசெய்த சின்னம்"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"இரட்டை ஆச்சரியக்குறி"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"வியப்புக் கேள்வி குறி"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"வர்த்தக முத்திரை சின்னம்"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"தகவல் மூலம்"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"இடது-வலது அம்புக்குறி"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"மேல்-கீழ் அம்புக்குறி"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"வடமேற்கு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"வட-கிழக்கு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"தென்-கிழக்கு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"தென்-மேற்கு அம்புக்குறி"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"தூண்டிலுடன் இடப்புறம் நோக்கிய அம்புக்குறி"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"தூண்டிலுடன் வலப்புறம் நோக்கிய அம்புக்குறி"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"வாட்ச்"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"மணற்கடிகாரம்"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"வலப்பக்கத்தைச் சுட்டிக்காட்டும் இரட்டை முக்கோணம்"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"இடப்பக்கத்தைச் சுட்டிக்காட்டும் இரட்டை முக்கோணம்"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"மேலே சுட்டிக்காட்டும் இரட்டை முக்கோணம்"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"கீழே சுட்டிக்காட்டும் இரட்டை முக்கோணம்"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"அலார கடிகாரம்"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"சரியும் மணலுடன் மணற்கடிகாரம்"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"வட்டத்திற்குள் பெரிய இலத்தீன் எழுத்து m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"சிறிய கருப்பு சதுரம்"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"சிறிய வெள்ளைச் சதுரம்"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"வலப்பக்கத்தைச் சுட்டிக்காட்டும் முக்கோணம்"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"இடப்பக்கத்தைச் சுட்டிக்காட்டும் முக்கோணம்"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"நடுத்தர வெள்ளை சதுரம்"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"மிதமான கருப்பு சதுரம்"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"மிதமான வெள்ளைநிறத்தில் சிறிய சதுரம்"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"மிதமான கருப்புநிறத்தில் சிறிய சதுரம்"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"கதிர்களுடன் கூடிய சூரியன்"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"மேகம்"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"கருப்பு தொலைபேசி"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"டிக் செய்யப்பட்ட தேர்வுபெட்டி"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"மழைத்துளிகளுடன் குடை"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"சூடான பானம்"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"வெள்ளை நிறத்தில் விரலை மேல்நோக்கிக் காட்டு"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"கள்ளங்கபடமற்ற சிரித்த முகம்"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"மேஷம்"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"ரிஷபம்"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"மிதுனம்"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"கடகம்"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"சிம்மம்"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"கன்னி"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"துலாம்"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"விருச்சிகம்"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"தனுசு"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"மகரம்"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"கும்பம்"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"மீனம்"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"கருப்புநிற ஸ்பேட்"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"கருப்புநிற கிளப்"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"கருப்புநிற இதயம்"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"கருப்புநிற வைரம்"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"ஆவிபறக்கும் பானம்"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"மறுசுழற்சி சின்னம்"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"சக்கர நாற்காலி சின்னம்"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"நங்கூரம்"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"எச்சரிக்கை அறிகுறி"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"உயர் மின்னழுத்த சின்னம்"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"நடுத்தர வெள்ளை வட்டம்"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"நடுத்தர கருப்பு வட்டம்"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"கால்பந்து"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"பேஸ்பால்"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"பனிமனிதன்"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"மேகத்தின் பின்னால் மறைந்திருக்கும் சூரியன்"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ஓஃபியாகெஸ்"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"அனுமதி இல்லை"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"தேவாலயம்"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"நீரூற்று"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"துளையில் கொடி"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"உலாப் படகு"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"கூடாரம்"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"எரிபொருள் குழாய்"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"கருப்பு கத்தரிக்கோல்"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"அடர்வெள்ளை நிற டிக் சின்னம்"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"விமானம்"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"கடிதஉறை"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"கைவிரலை மடக்குதல்"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"கைகளைக் காட்டுதல்"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"வெற்றி சின்னம்"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"பென்சில்"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"எழுதுமுனை"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"அடர்கருப்பில் டிக் சின்னம்"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"அடர்ந்த பெருக்கல் குறி"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"ஒளிரும் நட்சத்திரம்"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"எட்டு முனை நட்சத்திரம்"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"எட்டு முனை கருப்பு நட்சத்திரம்"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"ஸ்னோஃபிளாக்"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"ஸ்பார்க்கல்"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"பெருக்கல் குறி"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"சதுரத்திற்குள் பெருக்கல் குறி"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"அடர் நிற கேள்விக் குறி"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"வெள்ளை நிற கேள்விக்குறி"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"வெள்ளை நிற ஆச்சரியக்குறி"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"அடர் நிற ஆச்சரியக்குறி"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"ஆழமான காதலுடன் உள்ள இதயம்"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"அடர் கருப்பில் கூட்டல் குறி"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"அடர் கருப்பில் கழித்தல் குறி"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"அடர் கருப்பில் வகுத்தல் குறி"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"அடர் கருப்பில் வலப்பக்கம் அம்பு"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"சுருள் வளைவு"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"இரட்டை சுருள் வளைவு"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"வலப்புறமாக மேல்நோக்கி வளைந்த அம்புக்குறி"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"வலப்புறமாக கீழ்நோக்கி வளைந்த அம்புக்குறி"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"இடப்புறம் நோக்கிய கருப்பு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"மேல்நோக்கிய கருப்பு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"கீழ்நோக்கிய கருப்பு அம்புக்குறி"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"பெரிய கருப்பு சதுரம்"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"பெரிய வெள்ளை சதுரம்"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"நடுத்தர வெள்ளை நட்சத்திரம்"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"பெரிய வட்டம்"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"அலைகுறி"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"பார்ட் ஆல்டெர்னேஷன் மார்க்"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"வட்டத்திற்குள் வாழ்த்துகள் ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"வட்டத்திற்குள் ரகசியம் குறித்த ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"மஹ்ஜோங் டைலில் ரெட் டிராகன்"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"சீட்டு அட்டையில் கருப்பு ஜோக்கர்"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"இரத்த வகை A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"இரத்த வகை B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"இரத்த வகை O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"பார்கிங் லாட்"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"இரத்த வகை AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"சதுரத்திற்குள் CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"சதுரத்திற்குள் cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"சதுரத்திற்குள் free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"சதுரத்திற்குள் ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"சதுரத்திற்குள் new"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"சதுரத்திற்குள் N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"சதுரத்திற்குள் OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"சதுரத்திற்குள் SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"சதுரத்திற்குள் up!"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"சதுரத்திற்குள் vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"சதுரத்திற்குள் கட்டகான கோகோ"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"சதுரத்திற்குள் கட்டகான சேவை"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"சதுரத்திற்குள் இலவச ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"சதுரத்திற்குள் இடத்தைக் காட்டும் விரல் ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"சதுரத்திற்குள் தடை ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"சதுரத்திற்குள் காலியிடம் ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"சதுரத்திற்குள் ஏற்றுக்கொள்ளல் ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"சதுரத்திற்குள் முழுவதும் நிரம்பிய ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"சதுரத்திற்குள் கட்டணம் செலுத்திய ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"சதுரத்திற்குள் மாதந்திர ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"சதுரத்திற்குள் விண்ணப்ப ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"சதுரத்திற்குள் சலுகை ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"சதுரத்திற்குள் வணிக ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"வட்டத்திற்குள் நன்மைகள் ஐடியோகிராஃப்"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"வட்டத்திற்குள் ஐடியோகிராஃப் ஏற்றுக்கொள்ளல்"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"சூறாவளி"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"பனிமூட்டம்"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"மூடிய குடை"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"நட்சத்திரங்கள் சூழ்ந்த இரவு"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"மலைகளுக்கு இடையே சூரிய உதயம்"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"சூரிய உதயம்"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"அந்திப் பொழுதில் நகரமைப்பு"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"கட்டிடங்கள் மேல் சூரிய அஸ்தமனம்"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"வானவில்"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"இரவில் பாலம்"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"நீர் அலை"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"எரிமலை"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"பால்வெளி வீதி"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"உலக உருண்டையில் ஐரோப்பா ஆப்பிரிக்கா"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"உலக உருண்டையில் அமெரிக்கா"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"உலக உருண்டையில் ஆசியா ஆஸ்திரேலியா"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"தீர்க்க ரேகையுடன் உலக உருண்டை"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"அமாவாசை நிலவு"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"கால்பகுதி வளர்பிறை"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"அரைபாதி வளர்பிறை"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"முக்கால்பகுதி வளர்பிறை"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"முழு நிலவு"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"கால்பகுதி தேய்பிறை"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"அரைபாதி தேய்பிறை"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"முக்கால்பகுதி தேய்பிறை"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"பிறைவடிவம்"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"அமாவாசை நிலவு வடிவத்தில் முகம்"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"அரைபாதி வளர்பிறை வடிவத்தில் முகம்"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"அரைபாதி தேய்பிறை வடிவத்தில் முகம்"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"முழு நிலவு வடிவத்தில் முகம்"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"சூரியன் வடிவத்தில் முகம்"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"மின்னும் நட்சத்திரம்"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"வால்நட்சத்திரம்"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"பருப்பு வகையைச் சார்ந்த கொட்டை"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"நாற்று"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"பசுமையான மரம்"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"இலையுதிர் மரம்"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"பனைமரம்"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"சப்பாத்திக் கள்ளி"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"அல்லிப் பூ"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"செர்ரி மலர்"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"ரோஜா"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"செம்பருத்தி"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"சூரியகாந்தி"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"மலர்"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"தோலுரித்த மக்காச்சோளம்"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"நெற்பயிர்"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"மூலிகை"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"நான்கு இலை கொண்ட குளோவர்"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"மாப்பிள் இலை"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"மரத்திலிருந்து உதிர்ந்த இலை"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"காற்றில் அசைந்தாடும் இலை"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"காளான்"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"தக்காளி"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"கத்தரிக்காய்"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"திராட்சைகள்"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"முலாம்பழம்"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"தர்பூசணி"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"டேன்ஜெரின்"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"எலுமிச்சை"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"வாழைப் பழம்"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"அன்னாசிப்பழம்"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"சிவப்புநிற ஆப்பிள்"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"பச்சைநிற ஆப்பிள்"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"பேரி"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"பீச்சுப்பழம்"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"செர்ரி"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"ஸ்ட்ராபெரி"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ஹம்பர்கர்"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"பீட்சாவின் ஒரு பகுதி"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"எலும்பைச் சுற்றிய இறைச்சி"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"கோழிக் கால்"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"அரிசி ரொட்டி"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"அரிசி பந்து"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"சமைத்த அரிசி"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"குழம்பும் சாதமும்"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"சூடான உணவுக் கிண்ணம்"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"பாஸ்தா"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ரொட்டி"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"பிரெஞ்சு ஃபிரைஸ்"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"உருளைக்கிழங்கு வறுவல்"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"டாங்கோ"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ஓடென்"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"சூஷி"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"இறால் வறுவல்"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"சுருள் வடிவ மீன் கேக்"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"வெண்ணிலா ஐஸ்கிரீம்"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"நுரைபொங்கும் ஐஸ்"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ஐஸ்கிரீம்"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"டோனட்"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"குக்கீ"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"சாக்லேட் பார்"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"மிட்டாய்"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"லாலிபாப்"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"பாற்கூழ்"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"தேன் கிண்ணம்"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"சிறிய கேக்"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"உணவு பெட்டி"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"உணவு உள்ள கிண்ணம்"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"சமையல்"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"முட்கரண்டியும் கத்தியும்"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"கைப்பிடி இல்லாத தேநீர் கோப்பை"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"அரசி ஒயின் குடுவையும் கிண்ணமும்"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"ஒயின் டம்ளர்"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"மதுகலவை டம்ளர்"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"பழக்கலவைப் பானம்"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"பீர் குவளை"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"பீர் பொங்கும் குவளைகள்"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"குழந்தை பாட்டில்"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ரிப்பன்"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"அழகாக மடித்த பரிசு"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"பிறந்த நாள் கேக்"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"சிரிக்கும் பூசணிக்காய் விளக்கு"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"கிறிஸ்துமஸ் மரம்"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"கிறிஸ்துமஸ் தாத்தா"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"வாணவேடிக்கைகள்"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"வானத்தில் வெடித்துசிதறும் பட்டாசு"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"பலூன்"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"விழாக்கால வண்ண வேடிக்கை"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"வண்ணக் காகிதங்களைத் தூவும் பந்து"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"தனபதா மரம்"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"குறுக்கே அமைந்த இரண்டு கொடிகள்"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"பைன் அலங்காரம்"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"ஜப்பான் பொம்மைகள்"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"மீன் வடிவ கொடிகள்"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"காற்றில் பறக்கும் மணி"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"முழுநிலவைக் கொண்டாடும் விழா"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"பள்ளிக்கூட பை"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"பட்டமளிப்புத் தொப்பி"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"கேராசூல் ஹார்ஸ்"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"பெர்ரிஸ் வீல்"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"ரோலர் கோஸ்டர்"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"மீன்பிடிக்கும் கருவியும் மீனும்"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"மைக்ரோஃபோன்"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"மூவி கேமரா"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"சினிமா"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"ஹெட்ஃபோன்"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"பெயிண்டிங் தட்டு"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"அரசு விழாக்களில் அணியப்படும் பிரிட்டிஷ் தொப்பி"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"சர்க்கஸ் கூடாரம்"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"டிக்கெட்"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"கிளாப்பர் பலகை"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"நிகழ் கலைகள்"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"வீடியோ கேம்"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"சரியான குறி"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"ஸ்லாட் இயந்திரம்"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"பில்லியர்ட்ஸ்"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"விளையாட்டுப் பகடை"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"பௌலிங்"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"அட்டைகள் விளையாட்டு"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"இசைக் குறிப்பு"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"பல இசைக் குறிப்புகள்"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"சாக்ஸோஃபோன்"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"கிட்டார்"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"இசை விசைப்பலகை"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ட்ரம்பெட்"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"வயலின்"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"இசை ஸ்கோர்"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"ஓட்டப்பந்தய சட்டை"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"டென்னிஸ் மட்டை மற்றும் பந்து"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"பனிச்சறுக்கு பலகையும் கம்பும்"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"கூடைப்பந்து"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"சதுரங்க அமைப்பில் கொடி"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"பனிச்சறுக்குபவர்"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"ஓடுபவர்"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"அலையில் சாகசம் செய்பவர்"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"கோப்பை"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"குதிரைப் பந்தயம்"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"அமெரிக்க கால்பந்து"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"ரக்பி கால்பந்து"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"நீந்துபவர்"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"வீடு"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"தோட்டத்துடன் கூடிய வீடு"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"அலுவலகக் கட்டிடம்"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"ஜாப்பனீஸ் அஞ்சல் அலுவலகம்"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"ஐரோப்பிய அஞ்சல் அலுவலகம்"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"மருத்துவமனை"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"வங்கி"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"தன்னியக்கக் காசளிப்பு எந்திரம்"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ஹோட்டல்"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"காதலர்களுக்கான ஹோட்டல்"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"24 மணிநேரக் கடை"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"பள்ளி"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"பல்பொருள் அங்காடி"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"ஆலை"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"சிவப்பு நிற விளக்கு"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"ஜாப்பனீஸ் கோட்டை"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"ஐரோப்பிய கோட்டை"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"எலி"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"மௌஸ்"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"எருது"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"நீர் எருமை"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"பசு"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"சிறுத்தை"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"முயல்"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"பூனை"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"டிராகன்"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"முதலை"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"திமிங்கலம்"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"நத்தை"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"பாம்பு"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"குதிரை"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"செம்மறிக் கிடா"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"ஆடு"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"செம்மறியாடு"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"குரங்கு"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"சேவல்"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"கோழி"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"நாய்"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"பன்றி"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"ஆண் பன்றி"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"யானை"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ஆக்டோபஸ்"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"கடல் சங்கு"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"மூட்டைப் பூச்சி"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"எறும்பு"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"தேனீ"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"பெண் வண்டு"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"மீன்"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"மஞ்சளும் நீலமும் கலந்த மீன்"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"பலூன் மீன்"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"கடல் ஆமை"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"முட்டை ஓட்டிலிருந்து வெளிவரும் குஞ்சு"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"கோழிக்குஞ்சு"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"உற்றுப் பார்க்கும் கோழிக்குஞ்சு"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"பறவை"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"பென்குயின்"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"கோலா"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"பூடில்"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"ஒற்றை திமில் கொண்ட ஒட்டகம்"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"இரண்டு திமில்கள் கொண்ட ஆசிய ஒட்டகம்"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"டால்பின்"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"எலி முகம்"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"பசு முகம்"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"புலி முகம்"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"முயல் முகம்"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"பூனை முகம்"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"டிராகன் முகம்"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"நீரில் விளையாடும் திமிங்கிலம்"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"குதிரை முகம்"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"குரங்கு முகம்"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"நாய் முகம்"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"பன்றி முகம்"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"தவளை முகம்"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"வெள்ளெலி முகம்"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"ஓநாய் முகம்"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"கரடி முகம்"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"பாண்டாகரடி முகம்"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"பன்றி மூக்கு"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"கால் தடங்கள்"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"கண்கள்"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"காது"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"மூக்கு"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"வாய்"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"நாக்கு"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"வெள்ளை நிறத்தில் விரலை மேல்நோக்கிக் காட்டுதல்"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"வெள்ளை நிறத்தில் விரலை கீழ்நோக்கிக் காட்டுதல்"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"வெள்ளை நிறத்தில் விரலை இடப்பக்கம் நோக்கிக் காட்டுதல்"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"வெள்ளை நிறத்தில் விரலை வலப்பக்கம் நோக்கிக் காட்டுதல்"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"கைமடக்கி குத்துதல்"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"கை அசைத்தல்"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"அருமை என்பதைக் குறிக்கும் கை சின்னம்"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"கட்டை விரலை உயர்த்துதல்"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"கட்டை விரலைத் தாழ்த்துதல்"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"கைதட்டல்"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"கைகளை விரித்தல்"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"கிரீடம்"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"பெண்கள் அணியும் தொப்பி"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"கண்கண்ணாடிகள்"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"டை"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"டி-சர்ட்"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"ஜீன்ஸ்"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"ஆடை"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"கிமோனோ"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"நீச்சலுடை"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"பெண்கள் ஆடைகள்"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"பணப்பை"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"கைப்பை"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"சிறு பை"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"ஆண்கள் ஷூ"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"தடகள வீரருக்கான ஷூக்கள்"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ஹை ஹீல் செருப்பு"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"பெண்கள் செருப்பு"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"பெண்கள் ஷூக்கள்"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"கால் தடங்கள்"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"மார்பளவு வரை நிழல்"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"மார்பளவு வரை நிழல்கள்"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"சிறுவன்"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"இளம் பெண்"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"ஆண்"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"பெண்"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"குடும்பம்"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"கைகோர்த்த ஆண்களும் பெண்களும்"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"கைகோர்த்த இரண்டு ஆண்கள்"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"கைகோர்த்த இரண்டு பெண்கள்"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"போலீஸ் அதிகாரி"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"முயல் காதுகளுடன் பெண்கள்"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"முக்காடு அணிந்த மணமகள்"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"பொன் நிறத்தில் முடி கொண்டவர்"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"ஒட்டுத்தொப்பியுடன் கூடிய ஆண்"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"தலைப்பாகை அணிந்தவர்"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"வயதானவர்"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"வயதான பெண்மணி"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"பேபி"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"கட்டுமான தொழிலாளி"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"இளவரசி"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"ஜாப்பனீஸ் பயமுறுத்தும் முகம்"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"ஜாப்பனீஸ் பூதம்"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"பேய்"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"குட்டித் தேவதை"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"வேற்று கிரகவாசி"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"ஏலியன் மான்ஸ்டர்"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"வருத்தத்துடன் இருக்கும் பேய்"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"மண்டை ஓடு"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"வழிகாட்டுபவர்"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"பாதுகாவலர்"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"டான்சர்"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"லிப்ஸ்டிக்"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"நெயில்பாலிஷ்"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"முக மசாஜ்"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"முடித்திருத்தம்"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"பார்பர் ஃபோல்"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"மருந்தூசி"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"மாத்திரை"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"முத்தம்"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"காதல் கடிதம்"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"மோதிரம்"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"மாணிக்கக் கல்"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"கிஸ்"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"மலர்க்கொத்து"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"காதலில் திளைக்கும் ஜோடி"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"திருமணம்"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"துடிக்கும் இதயம்"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"உடைந்த இதயம்"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"இரண்டு இதயங்கள்"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"ஜொலிக்கும் இதயம்"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"விரிவடையும் இதயம்"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"அம்புடன் இதயம்"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"நீலநிற இதயம்"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"பச்சைநிற இதயம்"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"மஞ்சள்நிற இதயம்"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"பர்பிள்நிற இதயம்"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"ரிப்பன் கட்டிய இதயம்"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"சுற்றும் இதயங்கள்"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"அலங்கார இதயம்"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"நடுவில் புள்ளியுடன் கூடிய வைர வடிவம்"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"மின்சார ஒளி விளக்கு"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"ஆங்கர் சின்னம்"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"வெடிகுண்டு"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"தூங்கும் சின்னம்"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"வெடித்தல்"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"வியர்வைக் கொட்டும் சின்னம்"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"நீர் விழுதல்"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"காற்றடிக்கும் சின்னம்"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"பைல் ஆஃப் ஃபு"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"மடக்கிய கை"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"தலைச்சுற்றல்"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"பேச்சு வடிவ பலூன்"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"சிந்தனை கொண்ட பலூன்"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"வெள்ளைநிறப் பூ"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"நூறு மதிப்பெண்கள்"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"பணப்பை"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"நாணயப் பரிமாற்றம்"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"பெரிய டாலர் குறியீடு"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"கிரெடிட் கார்டு"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"யென் குறியீடுடன் கூடிய வங்கிநோட்டு"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"டாலர் குறியீடுடன் கூடிய வங்கிநோட்டு"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"யூரோ குறியீடுடன் கூடிய வங்கிநோட்டு"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"பவுண்டு குறியீடுடன் கூடிய வங்கிநோட்டு"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"இறக்கைகள் உள்ள பணம்"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"யென் குறியீட்டுடன் மேல்நோக்கிய போக்கைக் கொண்ட விளக்கப்படம்"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"இருக்கை"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"தனிப்பட்ட கணினி"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"குறும்பெட்டி"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"குறு வட்டு"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"நெகிழ் வட்டு"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ஆப்டிகல் வட்டு"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"டிவிடி"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"கோப்புறை"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"கோப்பின் திறந்த கோப்புறை"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"கீழே சுருட்டிய பக்கம்"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"மேலே லேசாக மடித்த பக்கம்"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"கேலெண்டர்"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"கிழிக்கும் வகையிலான கேலெண்டர்"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"கார்டில் அட்டவணை"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"மேல்நோக்கிய போக்கைக் கொண்ட விளக்கப்படம்"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"கீழ்நோக்கிய போக்கைக் கொண்ட விளக்கப்படம்"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"பார் விளக்கப்படம்"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"கிளிப்போர்டு"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"பின்"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"வட்ட வடிவ பின்"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"பேப்பர் கிளிப்"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"நேர் ரூலர்"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"முக்கோண ரூலர்"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"புத்தகக்குறி தாவல்கள்"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"லெட்ஜர்"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"நோட்புக்"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"அலங்கார கவர் நோட்புக்"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"மூடிய புத்தகம்"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"திறந்த புத்தகம்"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"பச்சைநிற கவர் புத்தகம்"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"நீலநிற கவர் புத்தகம்"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"ஆரஞ்சுநிற கவர் புத்தகம்"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"புத்தகங்கள்"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"பெயர் பேட்ஜ்"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"உருட்டு"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"மெமோ"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"ஃபோன் ரிசீவர்"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"பேஜர்"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"தொலைநகல் இயந்திரம்"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"சேட்டிலைட் ஆன்டெனா"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"பொது ஒலிபெருக்கி"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"அதிக சத்தம் கொடுக்கும் மெகாஃபோன்"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"அவுட்பாக்ஸ் தட்டு"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"இன்பாக்ஸ் தட்டு"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"பரிசு"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"மின்னஞ்சல் சின்னம்"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"உள்வரும் கடித உறை"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"கடித உறைக்கும் மேலே கீழ்நோக்கிய அம்புக்குறி"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"கீழே ஃபிளாக் உடன் கூடிய மூடப்பட்ட அஞ்சல் பெட்டி"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"மேலே ஃபிளாக் உடன் கூடிய மூடப்பட்ட அஞ்சல் பெட்டி"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"மேலே ஃபிளாக் உடன் கூடிய திறந்த அஞ்சல் பெட்டி"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"கீழே ஃபிளாக் உடன் கூடிய திறந்த அஞ்சல் பெட்டி"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"தபால் பெட்டி"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"தபால் ஹார்ன்"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"செய்தித்தாள்"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"மொபைல்"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"இடப் பக்கத்தில் வலப் புறம் நோக்கிய மொபைல்"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"அதிர்வு முறை"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"மொபைல் ஆஃப்"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"மொபைல் பயன்படுத்தக்கூடாது"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"கோடுகளுடன் ஆன்டெனா"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"கேமரா"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"வீடியோ கேமரா"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"தொலைக்காட்சி"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"ரேடியோ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"வீடியோ கேசட்"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"பிணைந்த வலப்புறம் நோக்கிய அம்புகள்"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"கடிகாரத்திசையில் வலம் மற்றும் இடப் புறம் நோக்கிய திறந்த வட்ட அம்புகள்"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"கடிகாரத்திசையில் வட்டத்திற்குள் ஒன்று என எழுதப்பட்டதுடன் வலம் மற்றும் இடப் புறம் நோக்கிய திறந்த வட்ட அம்புகள்"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"கடிகாரத்திசையில் கீழ் மற்றும் மேல் நோக்கிய திறந்த வட்ட அம்புகள்"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"எதிர்கடிகாரத்திசையில் கீழ் மற்றும் மேல் நோக்கிய திறந்த வட்ட அம்புகள்"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"ஒளிர்வு குறைவு சின்னம்"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"ஒளிர்வு அதிகம் சின்னம்"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"ரத்து என்னும் ஸ்ட்ரோக்குடன் ஸ்பீக்கர்"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"ஸ்பீக்கர்"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ஒற்றை ஒலி அலையுடன் ஸ்பீக்கர்"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"மூன்று ஒலி அலைகளுடன் ஸ்பீக்கர்"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"பேட்டரி"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"மின்செருகி"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"இடது பக்கத்திலிருக்கும் உருப்பெருக்கி கண்ணாடி"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"வலது பக்கத்திலிருக்கும் உருப்பெருக்கி கண்ணாடி"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"மை பேனா மூலம் பூட்டுதல்"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"பூட்டிய பூட்டும் சாவியும்"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"சாவி"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"பூட்டு"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"திறந்த பூட்டு"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"மணி"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"ரத்து என்னும் ஸ்ட்ரோக்குடன் மணி"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"புக்மார்க்"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"இணைப்பு சின்னம்"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ரேடியோ பட்டன்"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"மேலே பின்நோக்கிய இடப்புற அம்பு"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End என்பதற்கு மேலே இடப்புறம் நோக்கிய அம்பு"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On க்கு அடுத்து ஆச்சர்யக்குறியுடன், மேலே இடப்புற அம்பு"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon க்கு மேலே வலப்புறம் நோக்கிய அம்பு"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top க்கு மேலே, மேல்நோக்கிய அம்பு"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18 வயதுக்குட்பட்டவர்களுக்கு அனுமதி இல்லை"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"பெரிய எழுத்தில் பத்து"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"இலத்தீன் பெரிய எழுத்துகளுக்கான உள்ளீட்டு சின்னம்"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"இலத்தீன் சிறிய எழுத்துகளுக்கான உள்ளீட்டு சின்னம்"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"எண்களுக்கான உள்ளீட்டு சின்னம்"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"சின்னங்களுக்கான உள்ளீட்டுச் சின்னம்"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"இலத்தீன் எழுத்துகளுக்கான உள்ளீட்டு சின்னம்"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"நெருப்பு"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"டார்ச்"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"குறடு"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"சுத்தி"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"திருகும் அச்சாணியும்"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"கத்தி"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"துப்பாக்கி"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"நுண்பெருக்கி"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"தொலைநோக்கி"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"கண்ணாடி பந்து"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"ஒற்றைப் புள்ளியுடன் ஆறு பாகம் கொண்ட நட்சத்திரம்"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"தொடக்கத்திற்கான ஜாப்பனீஸ் சின்னம்"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"திரிசூல சின்னம்"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"கருப்பு சதுர பட்டன்"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"வெள்ளை சதுர பட்டன்"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"பெரிய சிவப்பு வட்டம்"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"பெரிய நீல வட்டம்"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"பெரிய ஆரஞ்சுநிற வைரம்"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"பெரிய நீலநிற வைரம்"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"சிறிய ஆரஞ்சுநிற வைரம்"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"சிறிய நீலநிற வைரம்"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"மேல்நோக்கிய சிவப்பு முக்கோணம்"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"கீழ்நோக்கிய சிவப்பு முக்கோணம்"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"மேல்நோக்கிய சிறிய சிவப்பு முக்கோணம்"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"கீழ்நோக்கிய சிறிய சிவப்பு முக்கோணம்"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"ஒரு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"இரண்டு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"மூன்று மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"நான்கு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"ஐந்து மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"ஆறு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"ஏழு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"எட்டு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"ஒன்பது மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"பத்து மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"பதினொரு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"பன்னிரண்டு மணியைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"ஒரு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"இரண்டு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"மூன்று மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"நான்கு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"ஐந்து மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"ஆறு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"ஏழு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"எட்டு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"ஒன்பது மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"பத்து மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"பதினொரு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"பன்னிரண்டு மணி, 30 நிமிடத்தைக் காட்டும் கடிகாரம்"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ஃபுஜி மலை"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"டோக்கியோ கோபுரம்"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"சுதந்திரத் தேவி சிலை"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"ஜப்பான் வரைபடத்தின் நிழல்"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"மொயாய்"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"புன்னகைக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"சிரித்த கண்களுடன் புன்னகைக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"ஆனந்தக் கண்ணீருடன் முகம்"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"திறந்த வாயுடன் சிரிக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"திறந்த வாய்ப் புன்னகை, புன்னகைக்கும் கண்களுடன் முகம்"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"திறந்த வாய்ப் புன்னகையும் குளிர்ந்த வியர்வையும் உள்ள முகம்"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"திறந்த வாய்ப் புன்னகை, இறுக்கமாக மூடப்பட்ட கண்களுடன் முகம்"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"ஒளிவட்டத்துடன் சிரித்த முகம்"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"கொம்புகளுடன் சிரித்த முகம்"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"கண்ணடிக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"சிரித்த கண்களுடன் சிரித்த முகம்"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"ருசியான உணவு சுவைக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"நிம்மதி முகம்"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"இதய வடிவிலான கண்களுடன் சிரித்த முகம்"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"சூரியக்கண்ணாடிகள் அணிந்த சிரித்த முகம்"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"பகட்டாகச் சிரிக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"வாயை நேராக இறுக்கமாக மூடிய முகம்"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"உணர்ச்சியற்ற முகம்"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"அதிருப்தியுடன் கூடிய முகம்"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"வியர்வைச் சொட்டும் முகம்"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"வருத்தமான முகம்"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"குழப்பமான முகம்"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"கண்களை மூடிக்கொண்டு அழும் முகம்"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"முத்தமிடும் முகம்"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"பறக்கும் முத்தம்"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"சிரித்த கண்களுடன் முத்தமிடும் முகம்"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"மூடிய கண்களுடன் முத்தமிடும் முகம்"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"நாக்கை வெளித்தள்ளிய முகம்"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"நாக்கை வெளித்தள்ளியதுடன் கண் சிமிட்டும் முகம்"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"நாக்கை வெளித்தள்ளி இறுக்கமாக மூடப்பட்ட கண்களுடன் முகம்"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"ஏமாற்றமடைந்த முகம்"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"கவலைதோய்ந்த முகம்"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"கோபமான முகம்"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"மஞ்சள்நிற கோப முகம்"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"அழும் முகம்"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"உதவியில்லாமல் இருப்பதை வெளிப்படுத்தும் முகம்"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"பெரும் மூச்சு விடும் முகம்"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"வியர்வை சொட்டும் சோக முகம்"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"கண்களும் வாயும் திறந்த நிலையில் இருக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"கலங்கின முகம்"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"பயந்த முகம்"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"பயந்து அழும் முகம்"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"தூங்கும் முகம்"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"சோர்வான முகம்"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"பற்களைக் கடிக்கும் முகம்"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"சத்தமாக அழும் முகம்"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"திறந்த வாயுடன் முகம்"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"ஆச்சரியத்தை வெளிப்படுத்தும் முகம்"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"திறந்த வாயுடன், வியர்வைச் சொட்டும் முகம்"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"இரண்டு கைகளைக் கன்னத்தில் வைத்து கத்தும் முகம்"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"அதிர்ச்சியடைந்த முகம்"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"சிவந்த கன்னங்களுடன் அதிர்ச்சியடைந்த முகம்"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"தூங்கும் முகம்"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"தலைச்சுற்றும் முகம்"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"வாய் இல்லாத முகம்"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"மருத்துவ முகமூடி அணிந்த முகம்"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"சிரிக்கும் கண்களுடன் புன்னகைக்கும் பூனை முகம்"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"ஆனந்த கண்ணீருடன் பூனை முகம்"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"திறந்த வாய் கொண்ட சிரித்த முகத்துடன் பூனை"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"இதய வடிவிலான கண்களுடன் கூடிய சிரித்த முகப் பூனை"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"பகட்டு புன்னகையுடன் பூனை முகம்"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"மூடிய கண்களுடன் முத்தமிடும் பூனை முகம்"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"எரிச்சலான பூனை முகம்"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"அழும் பூனை முகம்"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"பயந்த பூனை முகம்"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"நல்ல பாவனை இல்லாத முகம்"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"சரி சொல்லும் பாவனையுடன் முகம்"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"மிகப் பணிவானவர்"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"தீயதைப் பார்க்காத குரங்கு"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"தீயதைக் கேட்காத குரங்கு"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"தீயதைப் பேசாத குரங்கு"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"மகிழ்ச்சியில் ஒரு கையை உயர்த்துபவர்"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"விழாவில் இரு கைகளையும் மேலே உயர்த்துதல்"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"வருத்தமாக இருப்பவர்"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"மஞ்சள்நிறத்தில் கோபமான முகம் கொண்டவர்"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"கைகளை மடக்கியவர்"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"ராக்கெட்"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ஹெலிகாப்டர்"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"நீராவி ரயில்"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"ரயில்வே கார்"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"அதிவேக ரயில்"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"புல்லட் மூக்குடன் கூடிய அதிவேக ரயில்"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ரயில்"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"மெட்ரோ"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"ஒளியுடன் கூடிய ரயில்"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"நிலையம்"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"டிராம்"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"டிராம் கார்"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"பேருந்து"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"வந்துகொண்டிருக்கும் பேருந்து"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"நகர்வூந்து"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"பேருந்து நிறுத்தும்"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"மினிபஸ்"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"ஆம்புலன்ஸ்"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"தீ வண்டி"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"போலீஸ் கார்"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"வந்துகொண்டிருக்கும் போலீஸ் கார்"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"டாக்ஸி"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"வந்துகொண்டிருக்கும் டாக்ஸி"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"வாகனம்"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"வந்துகொண்டிருக்கும் வாகனம்"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"கேளிக்கை வாகனம்"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"டெலிவரி வண்டி"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"கனரக லாரி"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"டிராக்டர்"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"மோனோரயில்"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"மலைப் பாதை ரயில்"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"சஸ்பென்ஸன் ரயில்பாதை"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"மலை கேபிள்வழி"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ஏரியல் டிராம் வழி"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"கப்பல்"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"துடுப்பு படகு"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"விரைவுபடகு"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"கிடைமட்ட ட்ராஃபிக் விளக்கு"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"செங்குத்து ட்ராஃபிக் விளக்கு"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"கட்டுமான சின்னம்"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"போலீஸ் கார்களில் சுழலும் விளக்கு"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"கம்பத்தில் முக்கோண கொடி"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"கதவு"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"அனுமதி இல்லை சின்னம்"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"புகைச் சின்னம்"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"புகைபிடிக்கக்கூடாது சின்னம்"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"குப்பையை அதன் இடத்தில் போடும் சின்னம்"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"குப்பையைப் போடக்கூடாது சின்னம்"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"கிண்ணத்தில் குடிநீர் சின்னம்"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"குடிப்பதற்கான தண்ணீர் அல்ல"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"சைக்கிள்"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"சைக்கிளுக்கு அனுமதி இல்லை"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"சைக்கிள் ஓட்டுபவர்கள்"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"மலையில் சைக்கிள் ஓட்டுபவர்கள்"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"பாதசாரிகள்"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"பாதசாரிகளுக்கு அனுமதி இல்லை"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"குழந்தைகள் கடக்கும் வழி"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"ஆண்கள் சின்னம்"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"பெண்கள் சின்னம்"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"கழிவறை"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"குழந்தை சின்னம்"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"கழிப்பிடம்"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"வாட்டர் குளோசட்"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"பொழிவு"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"குளிப்பது"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"குளிக்கும் தொட்டி"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"பாஸ்போர்ட் கட்டுப்பாடு"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"சுங்கம்"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"உடைமை கோருமிடம்"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"உடைமை விடுமிடம்"</string>
+</resources>
diff --git a/java/res/values-ta-rIN/strings-talkback-descriptions.xml b/java/res/values-ta-rIN/strings-talkback-descriptions.xml
index a65c8de..bc01472 100644
--- a/java/res/values-ta-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-ta-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"உரை எதுவும் உள்ளிடப்படவில்லை"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> இலிருந்து <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> ஆக <xliff:g id="KEY_NAME">%1$s</xliff:g> திருத்துகிறது"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> தன்னியக்க திருத்தத்தைச் செயல்படுத்துகிறது"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"பரிந்துரை எதுவுமில்லை"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"அறியப்படாத எழுத்துக்குறி"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"ஷிஃப்டு"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"கூடுதல் குறியீடுகள்"</string>
@@ -35,7 +36,7 @@
     <string name="spoken_description_to_symbol" msgid="8244903740201126590">"சின்னங்கள்"</string>
     <string name="spoken_description_to_alpha" msgid="4081215210530031950">"எழுத்துகள்"</string>
     <string name="spoken_description_to_numeric" msgid="4560261331530795682">"எண்கள்"</string>
-    <string name="spoken_description_settings" msgid="7281251004003143204">"அமைப்புகள்"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"அமைப்பு"</string>
     <string name="spoken_description_tab" msgid="8210782459446866716">"டேப்"</string>
     <string name="spoken_description_space" msgid="5908716896642059145">"ஸ்பேஸ்"</string>
     <string name="spoken_description_mic" msgid="6153138783813452464">"குரல் உள்ளீடு"</string>
@@ -58,7 +59,7 @@
     <string name="keyboard_mode_date" msgid="6597407244976713364">"தேதி"</string>
     <string name="keyboard_mode_date_time" msgid="3642804408726668808">"தேதி மற்றும் நேரம்"</string>
     <string name="keyboard_mode_email" msgid="1239682082047693644">"மின்னஞ்சல்"</string>
-    <string name="keyboard_mode_im" msgid="3812086215529493501">"செய்தியிடல்"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"மெசேஜ்"</string>
     <string name="keyboard_mode_number" msgid="5395042245837996809">"எண்"</string>
     <string name="keyboard_mode_phone" msgid="2486230278064523665">"ஃபோன்"</string>
     <string name="keyboard_mode_text" msgid="9138789594969187494">"உரை"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"பேரெழுத்து I, மேல் புள்ளி"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"அறியப்படாத குறியீடு"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"அறியப்படாத ஈமோஜி"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"அலுத்துப்போன முகம்"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"சங்கடமான முகம்"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"குளிர்கண்ணாடி அணிந்த முகம்"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"ஆச்சரியமான முகம்"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"முத்தமிடும் முகம்"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"கோபமான முகம்"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"மாற்று எழுத்துக்குறிகள் உள்ளன"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"மாற்று எழுத்துக்குறிகள் நிராகரிக்கப்பட்டன"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"மாற்று பரிந்துரைகள் உள்ளன"</string>
diff --git a/java/res/values-ta-rIN/strings.xml b/java/res/values-ta-rIN/strings.xml
index 14f64c6..d0f3aee 100644
--- a/java/res/values-ta-rIN/strings.xml
+++ b/java/res/values-ta-rIN/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"விசையழுத்தின்போது அதிர்வுரு"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"விசையழுத்தத்தின்போது ஒலியெழுப்பு"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"விழை அழுத்தத்தின்போது பாப்அப் செய்"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"விருப்பங்கள்"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"கணக்குகள் &amp; தனியுரிமை"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"தோற்றம் &amp; தளவமைப்புகள்"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"சைகைத் தட்டச்சு"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"உரை திருத்தம்"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"மேம்பட்டவை"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"தீம்"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"பிரிக்கப்பட்ட விசைப்பலகையை இயக்கு"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google விசைப்பலகை ஒத்திசைவு"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"ஒத்திசைவு இயக்கப்பட்டது"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"எல்லா சாதனங்களிலும் தனிப்பட்ட அகராதியை ஒத்திசைக்கவும்"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"இப்போது ஒத்திசைத்தல்"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"மேகக்கணி தரவை நீக்கவும்"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google இலிருந்து ஒத்திசைத்த தரவை நீக்கும்"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ஒத்திசைத்தத் தரவு மேகக்கணியிலிருந்து நீக்கப்படும். நிச்சயமாக நீக்கவா?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"நீக்கு"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ரத்துசெய்"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"உங்கள் தனிப்பட்ட அகராதி ஒத்திசைக்கப்பட்டு, Google சேவையகங்களில் காப்புப் பிரதி எடுக்கப்படும். எங்கள் தயாரிப்புகளை மேம்படுத்த உதவ, சொல் உபயோகத்தின் புள்ளிவிவரத் தகவல் சேகரிக்கப்படலாம். எல்லா தகவல்களின் சேகரிப்பும், உபயோகமும் "<a href="https://www.google.com/policies/privacy">"Google இன் தனியுரிமைக் கொள்கைக்கு"</a>" இணங்கியபடியே இருக்கும்."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"இந்த அம்சத்தை இயக்க, சாதனத்தில் Google கணக்கைச் சேர்க்கவும்"</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">"மொழி மாற்றல் விசை பிற உள்ளீட்டு முறைகளையும் கட்டுப்படுத்துகிறது"</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">"இழுத்தல் குறிப்பானைக் காட்டு"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"ஷிப்ட் அல்லது குறியீட்டு விசைகளிலிருந்து இழுத்து செல்லும்போது காட்சித் தடத்தைக் காட்டு"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"குரல் உள்ளீட்டு விசை"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"குரல் உள்ளீட்டு முறைகள் எதுவும் இயக்கப்படவில்லை. மொழி &amp; உள்ளீட்டு அமைப்புகளைச் சரிபார்க்கவும்."</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="language_selection_title" msgid="3666971864764478269">"மொழிகள்"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"உதவி &amp; கருத்து"</string>
+    <string name="select_language" msgid="5709487854987078367">"மொழிகள்"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"சேமிக்க தொடவும்"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"சேமிக்க இங்கு தொடவும்"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"அகராதி உள்ளது"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"விசைப்பலகை தீம்"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"கணக்குகளை மாற்று"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"கணக்குகள் எதையும் தேர்வுசெய்யவில்லை"</string>
+    <string name="account_selected" msgid="2846876462199625974">"இப்போது <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>ஐப் பயன்படுத்துகிறீர்கள்"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"சரி"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"ரத்துசெய்"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"வெளியேறு"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"பயன்படுத்த, கணக்கைத் தேர்ந்தெடு"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ஆங்கிலம் (யூகே)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ஆங்கிலம் (யூஎஸ்)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ஸ்பானிஷ் (யூஎஸ்)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ஹிங்கிலிஷ்"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"செர்பியன் (லத்தீன்)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ஆங்கிலம் (யூகே) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ஆங்கிலம் (யூஎஸ்) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ஸ்பானிஷ் (யூஎஸ்) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ஹிங்கிலிஷ் (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"செர்பியன் (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (பாரம்பரியமானது)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (சிரிலிக்)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (இலத்தீன்)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (வசதியான)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"மொழியில்லை (அகரவரிசை)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"அகரவரிசை (க்வெர்டி)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"அகரவரிசை (க்வெர்ட்ச்)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"அகரவரிசை (கொல்மக்)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"அகரவரிசை (பிசி)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"எமோஜி"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"விசைப்பலகை தீம்"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"தனிப்பயன் உள்ளீட்டு நடைகள்"</string>
     <string name="add_style" msgid="6163126614514489951">"நடையைச் சேர்"</string>
     <string name="add" msgid="8299699805688017798">"சேர்"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> மொழிக்கான இந்தக் கோப்பை நிச்சயமாக நிறுவ வேண்டுமா?"</string>
-    <string name="error" msgid="8940763624668513648">"பிழை ஏற்பட்டது"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"விசையின் நீண்ட அழுத்தத்தின் தாமதம்"</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>
@@ -154,15 +153,13 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"<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">"துவக்கியில் பயன்பாட்டு ஐகானைக் காட்டும்"</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="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>
@@ -177,13 +174,13 @@
     <string name="message_loading" msgid="5638680861387748936">"ஏற்றுகிறது..."</string>
     <string name="main_dict_description" msgid="3072821352793492143">"முதன்மை அகராதி"</string>
     <string name="cancel" msgid="6830980399865683324">"ரத்துசெய்"</string>
-    <string name="go_to_settings" msgid="3876892339342569259">"அமைப்புகள்"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"அமைப்பு"</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="1583881200688185508">"உங்கள் மொபைலில் தேர்ந்தெடுத்த மொழிக்கு அகராதி உள்ளது.&lt;br/&gt; உங்கள் உள்ளீட்டு அனுபவத்தை மேம்படுத்த <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> அகராதியைப்  &lt;b&gt;பதிவிறக்குவதைப்&lt;/b&gt; பரிந்துரைக்கிறோம்.&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;மொழி &amp; உள்ளீடு&lt;/b&gt; என்பதற்குச் செலவதன் மூலம் அகராதிகளைப் பதிவிறக்கலாம் மற்றும் அகற்றலாம்."</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"உங்கள் மொபைலில் தேர்ந்தெடுத்த மொழிக்கு அகராதி உள்ளது.&lt;br/&gt; உங்கள் உள்ளீட்டு அனுபவத்தை மேம்படுத்த <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> அகராதியைப்  &lt;b&gt;பதிவிறக்குவதைப்&lt;/b&gt; பரிந்துரைக்கிறோம்.&lt;br/&gt; &lt;br/&gt; 3G இல் பதிவிறக்கத்திற்கு ஒன்று அல்லது இரண்டு நிமிடங்கள் ஆகலாம். உங்களிடம் &lt;b&gt;வரம்பில்லா தரவு திட்டம்&lt;/b&gt; இல்லையெனில் கட்டணம் விதிக்கப்படலாம்.&lt;br/&gt; உங்களிடம் எந்தத் தரவு திட்டம் உள்ளது என்பது உறுதியாகத் தெரியவில்லையெனில், பதிவிறக்கத்தைத் தானாகத் துவங்க, வைஃபை இணைப்பைக் கண்டறிவதைப் பரிந்துரைக்கிறோம்.&lt;br/&gt; &lt;br/&gt; உதவிக்குறிப்பு: உங்கள் மொபைல் சாதனத்தில் &lt;b&gt;அமைப்பு&lt;/b&gt; மெனுவில் உள்ள &lt;b&gt;மொழி &amp; உள்ளீடு&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="do_not_download_over_metered" msgid="2176209579313941583">"வைஃபை வழியாகப் பதிவிறக்கு"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> மொழிக்கு அகராதி கிடைக்கிறது"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"மதிப்பாய்வு செய்து பதிவிறக்க அழுத்தவும்"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"பதிவிறக்குகிறது: <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> க்கான பரிந்துரைகள் விரைவில் தயாராகிவிடும்."</string>
diff --git a/java/res/values-te-rIN/strings-emoji-descriptions.xml b/java/res/values-te-rIN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..f8ea9ea
--- /dev/null
+++ b/java/res/values-te-rIN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"కాపీరైట్ గుర్తు"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"రిజిష్టర్డ్ గుర్తు"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"డబుల్ ఆశ్చర్యార్థక గుర్తు"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"ఆశ్చర్యార్థక ప్రశ్నార్థక గుర్తు"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"వ్యాపారచిహ్నం గుర్తు"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"సమాచార మూలం"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"ఎడమ కుడి రెండువైపులా చూపే బాణం"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"ఎగువ దిగువ రెండువైపులా చూపే బాణం"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"వాయువ్య దిశవైపు చూపే బాణం"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"ఈశాన్య దిశవైపు చూపే బాణం"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"ఆగ్నేయ దిశవైపు చూపే బాణం"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"నైరుతి దిశవైపు చూపే బాణం"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"హుక్ గల ఎడమవైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"హుక్ గల కుడివైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"గడియారం"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"అవర్ గ్లాస్"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"నలుపు రంగులో కుడివైపుకి చూపే డబుల్ త్రిభుజం"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"నలుపు రంగులో ఎడమవైపుకి చూపే డబుల్ త్రిభుజం"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"నలుపు రంగులో పైకి చూపే డబుల్ త్రిభుజం"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"నలుపు రంగులో క్రిందికి చూపే డబుల్ త్రిభుజం"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"అలారం గడియారం"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"ఇసుకను ప్రవహింపచేసే అవర్ గ్లాస్"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"వలయంలో ఉన్న లాటిన్ క్యాపిటల్ అక్షరం m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"నలుపు రంగు చిన్న చతురస్రం"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"తెలుపు రంగు చిన్న చతురస్రం"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"నలుపు రంగులో కుడివైపుకి చూపే త్రిభుజం"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"నలుపు రంగులో ఎడమవైపుకి చూపే త్రిభుజం"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"తెలుపు రంగు మధ్యస్థాయి చతురస్రం"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"నలుపు రంగు మధ్యస్థాయి చతురస్రం"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"తెలుపు రంగు మధ్యస్థాయి చిన్న చతురస్రం"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"నలుపు రంగు మధ్యస్థాయి చిన్న చతురస్రం"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"నలుపు రంగు సూర్యకిరణాలు"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"మేఘం"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"నలుపు రంగు టెలిఫోన్"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"ఎంచుకున్న బ్యాలెట్ పెట్టె"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"వర్షపు చినుకులు పడుతున్న గొడుగు"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"వేడి పానీయాలు"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"తెలుపు రంగులో చూపుడు వేలుని పైకి చూపుతున్నట్లు"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"తెలుపు రంగులో నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"మేషం"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"వృషభం"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"మిథునం"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"కర్కాటకం"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"సింహం"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"కన్య"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"తులం"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"వృశ్చికం"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"ధనస్సు"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"మకరం"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"కుంభం"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"మీనం"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"నలుపు బ్లాక్ స్పేడ్ సూట్"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"నలుపు క్లబ్ సూట్"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"నలుపు హార్ట్ సూట్"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"నలుపు డైమండ్ సూట్"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"వేడి ఊటలు"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"నలుపు రంగు సార్వత్రిక పునర్వినియోగ చిహ్నం"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"చక్రాల కుర్చీ చిహ్నం"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"లంగరు"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"హెచ్చరిక చిహ్నం"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"అధిక వోల్టేజీ చిహ్నం"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"మధ్యలో తెలుపు రంగు వలయం"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"మధ్యలో నలుపు రంగు వలయం"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"సాకర్ బాల్"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"బేస్‌బాల్"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"మంచు లేకుండా మంచుమనిషి"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"మేఘం వెనుక దాగిన సూర్యుడు"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"అఫ్యూకస్"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"ప్రవేశం లేదు"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"చర్చి"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"ఫౌంటైన్"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"రంధ్రంలో ఉంచిన జెండా"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"తెరచాప గల పడవ"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"గుడారం"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"ఇంధన పంపు"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"నలుపు రంగు కత్తెరలు"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"తెలుపు రంగు పెద్ద పరిమాణ ఎంపిక చేసుకునే గుర్తు"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"విమానం"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"ఎన్వలప్"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"పైకి ఎత్తి చూపుతున్న పిడికిలి"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"పైకి ఎత్తి చూపుతున్న చెయ్యి"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"విజయ సంకేతాన్ని చూపుతున్న చెయ్యి"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"పెన్సిల్"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"నలుపు రంగు పాళీ"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"పెద్ద పరిమాణంలో ఎంపిక చేసుకునే గుర్తు"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"పెద్ద పరిమాణంలో గుణకారం గుర్తు x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"మెరుపులు"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"ఎనిమిది ఆకులు గల నక్షత్రం గుర్తు"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"ఎనిమిది వైపులకు చూపే నలుపు రంగు నక్షత్రం"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"స్నోఫ్లేక్"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"తళతళమని మెరిసే మెరుపు"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"క్రాస్ గుర్తు"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"నెగిటివ్ చతురస్రంలో ఉన్న క్రాస్ గుర్తు"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"నలుపు రంగు ప్రశ్నార్థక గుర్తు ఆర్నమెంట్"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"తెలుపు రంగు ప్రశ్నార్థక గుర్తు ఆర్నమెంట్"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"తెలుపు రంగు ఆశ్చర్యార్థక గుర్తు ఆర్నమెంట్"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"పెద్ద పరిమాణ ఆశ్చర్యార్థక చిహ్నం"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"ముదురు నలుపు రంగులో ఉన్న హృదయాకారం"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"పెద్ద పరిమాణ కూడిక గుర్తు"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"పెద్ద పరిమాణ తీసివేత గుర్తు"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"పెద్ద పరిమాణ భాగహారం గుర్తు"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"నలుపు రంగులో కుడివైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"మెలితిరిగి ఉన్న వంపు"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"రెండుసార్లు మెలితిరిగి ఉన్న వంపు"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"కుడివైపుకి చూపుతూ ఆపై ఎగువకి వంగిన బాణం"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"కుడివైపు చూపుతూ ఆపై దిగువకి వంగిన బాణం"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"ఎడమవైపుకి చూపే నలుపు రంగు బాణం"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"ఎగువకి చూపే నలుపు రంగు బాణం"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"దిగువకి చూపే నలుపు రంగు బాణం"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"నలుపు రంగు పెద్ద పరిమాణ చతురస్రం"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"తెలుపు రంగు పెద్ద పరిమాణ చతురస్రం"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"తెలుపు రంగు మధ్యస్థ పరిమాణ నక్షత్రం"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"అత్యంత పెద్ద పరిమాణ వలయం"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"తరంగ రూపంలో ఉండే డాష్"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"పరివర్తన గుర్తు భాగం"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"వృత్తంలో ఉన్న అభినందన ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"వృత్తంలో ఉన్న రహస్యం ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"మహ్‌జాంగ్ టైల్ ఎరుపు రంగు డ్రాగన్"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"పేకాటలోని నలుపు రంగు జోకర్"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"రక్తం రకం A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"రక్తం రకం B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"రక్తం రకం O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"పార్కింగ్ లాట్"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"రక్తం రకం AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"చతురస్రంలో ఉన్న CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"చతురస్రంలో ఉన్న కూల్"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"చతురస్రంలో ఉన్న ఫ్రీ"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"చతురస్రంలో ఉన్న ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"చతురస్రంలో ఉన్న న్యూ"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"చతురస్రంలో ఉన్న N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"చతురస్రంలో ఉన్న ఓకే"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"చతురస్రంలో ఉన్న SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"ఆశ్చర్యార్థక గుర్తుతో చతురస్రంలో ఉన్న అప్"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"చతురస్రంలో ఉన్న వర్సెస్"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"చతురస్రంలో ఉన్న కటకానా హియర్"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"చతురస్రంలో ఉన్న కటకానా సర్వీస్"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"చతురస్రంలో ఉన్న ఛార్జ్-ఫ్రీ ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"చతురస్రంలో ఉన్న రిజర్వ్ చేసిన సీటు ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"చతురస్రంలో ఉన్న నిషేధ ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"చతురస్రంలో ఉన్న ఖాళీ ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"చతురస్రంలో ఉన్న ఆమోద ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"చతురస్రంలో ఉన్న పూర్తి స్వాధీనత ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"చతురస్రంలో ఉన్న చెల్లింపు ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"చతురస్రంలో ఉన్న నెలవారీ ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"చతురస్రంలో ఉన్న అనువర్తనం ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"చతురస్రంలో ఉన్న తగ్గింపు ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"చతురస్రంలో ఉన్న వ్యాపారంలో ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"వృత్తంలో ఉన్న ప్రయోజన ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"వృత్తంలో ఉన్న ఆమోద ఇడియోగ్రాఫ్"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"తుఫాను"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"పొగమంచు పూరితం"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"మూసివేయబడిన గొడుగు"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"నక్షత్రాలతో కూడిన రాత్రి"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"పర్వతాల నడుమ సూర్యోదయం"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"సూర్యోదయం"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"సంధ్యా సమయంలో నగర ఆకాశహర్మ్యం"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"భవనాల నడుమ సూర్యాస్తమయం"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"ఇంద్రధనస్సు"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"రాత్రివేళలో కనబడే వంతెన"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"నీటి అల"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"అగ్నిపర్వతం"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"పాలపుంత"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"భూమిపై కనిపించే యూరప్-ఆఫ్రికా"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"భూమిపై కనిపించే అమెరికాలు"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"భూమిపై కనిపించే ఆసియా-ఆస్ట్రేలియా"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"ధృవరేఖలు గల భూమి"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"అమావాస్య చంద్రుని గుర్తు"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"నెల వంక వృద్ధి చెందుతున్న గుర్తు"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"మొదటి పావు భాగంలో ఉండే చంద్రుని గుర్తు"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"బోర్లించిన గిన్నె ఆకారంలో ఉండే చంద్రుని ఆకృతి వృద్ధి చెందుతున్న గుర్తు"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"పౌర్ణమి గుర్తు"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"బోర్లించిన గిన్నె ఆకారంలో ఉండే చంద్రుని ఆకృతి క్షీణిస్తున్న గుర్తు"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"చివరి పావు భాగంలో ఉండే చంద్రుని గుర్తు"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"నెల వంక క్షీణిస్తున్న గుర్తు"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"నెల వంక"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"ముఖం గల అమావాస్య చంద్రుడు"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"ముఖం గల మొదటి పావు భాగంలో ఉండే చంద్రుడు"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"ముఖం గల చివరి పావు భాగంలో ఉండే చంద్రుడు"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"ముఖం గల పౌర్ణమి చంద్రుడు"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"ముఖం గల సూర్యుడు"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"మెరుస్తున్న నక్షత్రం"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"ఉల్క"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"చెస్ట్‌నట్"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"మొలక"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"ఎప్పుడూ పచ్చగా ఉండే చెట్టు"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"ఆకులు రాల్చే చెట్టు"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"తాటి చెట్టు"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"కాక్టస్"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"తులిప్"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"చెర్రీ బ్లాసమ్"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"గులాబీ"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"మందారం"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"సూర్యకాంతి"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"బ్లాసమ్"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"మొక్కజొన్న కంకి"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"వరి వంగడం"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"మూలిక"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"నాలుగు ఆకుల క్లోవర్"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"మాపుల్ ఆకు"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"క్రింద పడే ఆకు"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"గాలికి ఊగుతున్న ఆకు"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"పుట్టగొడుగు"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"టమోట"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"వంకాయ"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"ద్రాక్షపళ్లు"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"ఖర్బూజాపండు"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"పుచ్చకాయ"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"నారింజ పండు"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"నిమ్మకాయ"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"అరటి పండు"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"అనాస పండు"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"ఎరుపు రంగు యాపిల్ పండు"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"పచ్చ యాపిల్ పండు"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"బేరీ పండు"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"పీచ్"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"చెర్రీలు"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"స్ట్రాబెర్రీ"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"హ్యాంబర్గర్"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"పిజ్జా ముక్క"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"ఎముక మాంసం"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"కోడి కాలు"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"రైస్ క్రాకర్"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"రైస్ బాల్"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"వండిన అన్నం"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"కూర మరియు అన్నం"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"స్టీమింగ్ బౌల్"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"స్పఘెట్టి"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"రొట్టె"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"ఫ్రెంచ్ ఫ్రైస్"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"కాల్చిన తీపి బంగాళాదుంప"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"డాంగో"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"ఓడెన్"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"సుషి"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"వేయించిన రొయ్య"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"సుడులు తిరిగినట్లు ఉండే ఆకారం గల చేప కేకు"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"మృదువైన ఐస్ క్రీమ్"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"షేవ్డ్ ఐస్"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ఐస్ క్రీమ్"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"డోనట్"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"కుకీ"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"చాక్లెట్ బార్"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"క్యాండీ"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"లాలిపాప్"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"కస్టర్డ్"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"తేనె కలశం"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"కేకు ముక్క"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"బెంటో బాక్స్"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"ఆహారం గల పాత్ర"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"వంట"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ఫోర్క్ మరియు కత్తి"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"హ్యాండిల్ లేని టీకప్పు"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"సేక్ సీసా మరియు కప్పు"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"వైన్ గ్లాసు"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"కాక్‌టెయిల్ గ్లాసు"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"ఉష్ణమండల పానీయం"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"బీరు కప్పు"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"క్లింక్‌మని శబ్దం చేస్తున్న బీరు కప్పులు"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"చిన్నపిల్లలు పాలు తాగే సీసా"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"రిబ్బన్"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"ప్యాక్ చేసిన బహుమతి"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"పుట్టినరోజు కేకు"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"గుమ్మడికాయ రూప లాంతరు"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"క్రిస్మస్ చెట్టు"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"ఫాదర్ క్రిస్మస్"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"బాణసంచా"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"బాణాసంచా మెరుపులు"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"బెలూన్"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"పార్టీ పాపర్"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"కాన్ఫెట్టి బాల్"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"టనబాటా చెట్టు"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"క్రాస్డ్ ఫ్లాగ్స్"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"దేవదారు వృక్షంతో చేసిన అలంకరణ"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"జపనీస్ బొమ్మలు"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"కార్ప్ స్ట్రీమర్"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"విండ్ చైమ్"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"చంద్రుణ్ణి చూస్తూ చేసుకునే వేడుక"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"పాఠశాలకు తీసుకెళ్లే సంచి"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"గ్రాడ్యుయేషన్ టోపీ"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"రంగులరాట్నంలోని గుర్రం"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"ఫెర్రిస్ వీల్"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"రోలర్ కోస్టర్"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"చేపలు పట్టడానికి వాడే పోల్ మరియు చేప"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"మైక్రోఫోన్"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"చలన చిత్రాలను తీసే కెమెరా"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"చలన చిత్రం"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"హెడ్‌ఫోన్"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"కళాకారుని రంగుల ఫలకం"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"పొడవాటి టోపీ"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"సర్కస్ గుడారం"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"టిక్కెట్"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"క్లాప్ కొట్టే పలక"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"ప్రదర్శక కళలు"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"వీడియో గేమ్"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"డైరెక్ట్ హిట్"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"స్లాట్ మెషీన్"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"బిలియర్డ్స్"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"ఆటకు ఉపయోగించే పాచిక"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"బౌలింగ్"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"ఫ్లవర్ ప్లేయింగ్ కార్డ్స్"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"సంగీత స్వరం"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"బహుళ సంగీత స్వరాలు"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"సాక్సోఫోన్"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"గిటార్"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"సంగీత కీబోర్డ్"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ట్రంపెట్"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"వయోలిన్"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"సంగీత స్కోర్"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"సాష్ గల పరిగెత్తడానికి వాడే షర్టు"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"టెన్నిస్ రాకెట్ మరియు బంతి"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"స్కీ మరియు స్కీ బూటు"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"బాస్కెట్‌బాల్ మరియు హూప్"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"చదరపు గడుల జెండా"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"స్నోబోర్డర్"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"రన్నర్"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"సర్ఫర్"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ట్రోఫీ"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"గుర్రపు పందెం"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"అమెరికన్ ఫుట్‌బాల్"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"రగ్బీ ఫుట్‌బాల్"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"ఈతగాడు"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"ఇంటి భవనం"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"ఉద్యానవనం ఉన్న ఇల్లు"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"కార్యాలయ భవనం"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"జపనీస్ తపాలా కార్యాలయం"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"యూరోపిన్ తపాలా కార్యాలయం"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"ఆసుపత్రి"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"బ్యాంక్"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ఆటోమేటెడ్ టెల్లర్ మెషీన్"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"హోటల్"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"లవ్ హోటల్"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"వసతి దుకాణం"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"పాఠశాల"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"కిరాణా దుకాణం"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"కర్మాగారం"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"ఇజకాయా లాంతరు"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"జపనీస్ కోట"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"యూరోపియన్ కోట"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"ఎలుక"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"చిట్టెలుక"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"ఎద్దు"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"నీటి దున్నపోతు"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"ఆవు"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"చిరుతపులి"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"కుందేలు"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"పిల్లి"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"డ్రాగన్"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"మొసలి"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"తిమింగలం"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"నత్త"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"పాము"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"గుర్రం"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"పొట్టేలు"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"మేక"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"గొర్రె"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"కోతి"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"కోడిపుంజు"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"కోడి"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"కుక్క"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"పంది"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"అడవి పంది"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ఏనుగు"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ఆక్టోపస్"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"సర్పిలాకార గుల్ల"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"నల్లి"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"చీమ"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"తేనెటీగ"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"ఆడ పేడపురుగు"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"చేప"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ఉష్ణమండల చేప"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"బ్లోఫిష్"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"సముద్రపు తాబేలు"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"పొదుగుతున్న కోడిపిల్ల"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"చిన్న కోడిపిల్ల"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"ముందువైపుకి ముఖాన్ని చూపుతున్న చిన్న కోడిపిల్ల"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"పక్షి"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"పెంగ్విన్"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"కోలా"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"పూడ్లే"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"డ్రోమేడరి క్యామెల్"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"బ్యాక్ట్రియాన్ క్యామెల్"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"డాల్ఫిన్"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"చిట్టెలుక ముఖం"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"ఆవు ముఖం"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"పులి ముఖం"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"కుందేలు ముఖం"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"డ్రాగన్ ముఖం"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"నీటిని చిమ్ముతున్న తిమింగలం"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"గుర్రం ముఖం"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"కోతి ముఖం"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"కుక్క ముఖం"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"పంది ముఖం"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"కప్ప ముఖం"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"చుంచు ముఖం"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"తోడేలు ముఖం"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"ఎలుగుబంటి ముఖం"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"పాండా ముఖం"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"పంది ముక్కు"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"జంతువుల పాదముద్రలు"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"కళ్లు"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"చెవి"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"ముక్కు"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"నోరు"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"నాలుక"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"తెలుపు రంగులో చూపుడు వేలుని వెనుకభాగంతో పాటు పైకి చూపుతున్నట్లు"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"తెలుపు రంగులో చూపుడు వేలుని వెనుకభాగంతో పాటు క్రిందికి చూపుతున్నట్లు"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"తెలుపు రంగులో చూపుడు వేలుని వెనుకభాగంతో పాటు ఎడమవైపుకి చూపుతున్నట్లు"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"తెలుపు రంగులో చూపుడు వేలుని వెనుకభాగంతో పాటు కుడివైపుకి చూపుతున్నట్లు"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"పిడికిలి బిగించి చూపే సంకేతం"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"చెయ్యి ఊపుతున్నట్లు చూపే సంకేతం"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"బాగుంది అని చూపే సంకేతం"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"విజయ సంకేతం"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"ఓటమి సంకేతం"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"చప్పట్లు కొడుతున్నట్లు చూపే సంకేతం"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"చేతులను తెరిచి చూపే సంకేతం"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"కిరీటం"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"ఆడవారు ధరించే టోపీ"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"కళ్లద్దాలు"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"నెక్‌టై"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"టి-షర్ట్"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"జీన్స్"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"డ్రెస్"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"కిమోనో"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"బికినీ"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"ఆడవారి దుస్తులు"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"పర్సు"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"హ్యాండ్‌బ్యాగ్"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"పౌచ్"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"మగవారి బూటు"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"అథ్లెటిక్ బూటు"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"ఎత్తైన మడమ గల బూట్లు"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"ఆడవారి చెప్పులు"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"ఆడవారి బూట్లు"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"పాదముద్రలు"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"నీడరూపంలో ఉండే ప్రతిమ"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"నీడరూపంలో ఉండే ప్రతిమలు"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"అబ్బాయి"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"అమ్మాయి"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"పురుషుడు"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"స్త్రీ"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"కుటుంబం"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"స్త్రీ, పురుషులు ఇరువురూ చేతులు పట్టుకున్నట్లు"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"ఇద్దరు పురుషులు చేతులు పట్టుకున్నట్లు"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"ఇద్దరు స్త్రీలు చేతులు పట్టుకున్నట్లు"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"పోలీసు అధికారి"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"కుందేలు చెవులను ధరించిన స్త్రీ"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"మేలి ముసుగు వేసుకున్న పెళ్లికూతురు"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"బంగారు రంగు జుట్టు గల వ్యక్తి"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"గ్వా పై మావో ధరించిన పురుషుడు"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"తలపాగా ధరించిన పురుషుడు"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"తాత"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"బామ్మ"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"శిశువు"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"నిర్మాణ కార్మికుడు"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"యువరాణి"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"జపనీస్ ఓగర్"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"జపనీస్ గాబ్లిన్"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"దెయ్యం"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"బేబీ ఏంజెల్"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"గ్రాహాంతర జీవి"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"గ్రహాంతర రాక్షస జీవి"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"ఇంప్"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"కపాలం"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"సమాచారం అందించే వ్యక్తి"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"కాపలాదారుడు"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"డాన్సర్"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"లిప్‌స్టిక్"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"గోళ్ల పాలిష్"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"ముఖ మర్దనం"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"హెయిర్‌కట్"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"బార్బర్ పోల్"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"సిరంజ్"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"మాత్ర"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"ముద్దు పెట్టినట్లు చూపే గుర్తు"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"ప్రేమ లేఖ"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"ఉంగరం"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"విలువైన రత్నం"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"ముద్దు పెడుతున్నట్లు"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"పుష్పగుచ్ఛం"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"హృదయాకారం గల జంట"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"పెళ్లి"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"స్పందిస్తున్న గుండె"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"పగిలిన గుండె"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"రెండు గుండెలు"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"తళతళమని మెరుస్తున్న గుండె"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"పెరుగుతున్న గుండె"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"బాణం గుర్తు గల గుండె"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"నీలి రంగు గుండె"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"పచ్చ రంగు గుండె"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"పసుపు రంగు గుండె"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"ఊదా రంగు గుండె"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"రిబ్బన్ కట్టిన గుండె"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"పరిభ్రమిస్తున్న గుండెలు"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"గుండె అలంకరణ"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"లోపల చుక్క ఉండే డైమండ్ ఆకారం"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"విద్యుత్ కాంతి బల్బు"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"కోపంగా ఉన్నట్లు చూపే చిహ్నం"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"బాంబ్"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"నిద్రపోతున్నట్లు చూపే చిహ్నం"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"ఘర్షణ కలిగినట్లు చూపే చిహ్నం"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"చిలకరించిన చెమట గుర్తు"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"నీటిబొట్టు"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"డాష్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"పైల్ ఆఫ్ పూ"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"వంగడానికి వీలుగా ఉండే కండరపుష్టి"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"డిజ్జీ చిహ్నం"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"స్పీచ్ బెలూన్"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"ఆలోచన బెలూన్"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"తెలుపురంగు పువ్వు"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"వంద పాయింట్‌ల చిహ్నం"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"డబ్బు సంచి"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"కరెన్సీ మార్పిడి"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"ముదురు రంగులోని డాలర్ గుర్తు"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"క్రెడిట్ కార్డు"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"యెన్ గుర్తు గల బ్యాంక్ నోటు"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"డాలర్ గుర్తు గల బ్యాంక్ నోటు"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"యూరో గుర్తు గల బ్యాంక్ నోటు"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"పౌండ్ గుర్తు గల బ్యాంక్ నోటు"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"రెక్కలు గల డబ్బు"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"పైకి వెళ్తున్న ట్రెండ్‌తో పాటు యెన్ గుర్తుని చూపే చార్ట్"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"సీటు"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"వ్యక్తిగత కంప్యూటర్"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"బ్రీఫ్‌కేస్"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"మినిడిస్క్"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ఫ్లాపీ డిస్క్"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"ఆప్టికల్ డిస్క్"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"ఫైల్ ఫోల్డర్"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"తెరిచిన ఫైల్ ఫోల్డర్"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"మెలితిప్పి ఉన్న పేజీ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"ఎగువన కొద్దిగా మడిచినట్లు ఉండే పేజీ"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"క్యాలండర్"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"టియర్-ఆఫ్ క్యాలెండర్"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"కార్డు సూచిక"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"పైకి వెళ్తున్న ట్రెండ్‌ని చూపే చార్ట్"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"క్రిందికి దిగుతున్న ట్రెండ్‌ని చూపే చార్ట్"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"బార్ చార్ట్"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"క్లిప్‌బోర్డ్"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"పుష్‌పిన్"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"వృత్తాకార పుష్‌పిన్"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"కాగితానికి వేసే క్లిప్"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"నేరుగా ఉండే రూలర్"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"త్రిభుజాకార రూలర్"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"బుక్‌మార్క్ ట్యాబ్‌లు"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"లెడ్జర్"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"నోటుపుస్తకం"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"కవర్‌ వేసిన నోటుపుస్తకం"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"మూసివేయబడిన పుస్తకం"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"తెరచిన పుస్తకం"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"పచ్చరంగు పుస్తకం"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"నీలిరంగు పుస్తకం"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"నారింజరంగు పుస్తకం"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"పుస్తకాలు"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"పేరు బ్యాడ్జి"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"స్క్రోల్"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"మెమో"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"టెలిఫోన్ రిసీవర్"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"పేజర్"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"ఫ్యాక్స్ మెషీన్"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"ఉపగ్రహ యాంటెన్నా"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"ప్రజలకు వినపడేలా ప్రతిధ్వనించే లౌడ్‌స్పీకర్"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"ప్రతిధ్వనిస్తున్న మెగాఫోన్"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"అవుట్‌బాక్స్ ట్రే"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ఇన్‌బాక్స్ ట్రే"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"ప్యాకేజీ"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ఇ-మెయిల్ సంకేతం"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ఇన్‌కమింగ్ ఎన్వలప్"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ఎన్వలప్‌కి ఎగువన క్రిందికి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"క్రిందికి దించిన ఫ్లాగ్‌తో మూసివేయబడిన మెయిల్‌పెట్టె"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"పైకి ఎత్తిన ఫ్లాగ్‌తో మూసివేయబడిన మెయిల్‌పెట్టె"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"పైకి ఎత్తిన ఫ్లాగ్‌తో తెరిచిన మెయిల్‌పెట్టె"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"క్రిందికి దించిన ఫ్లాగ్‌తో తెరిచిన మెయిల్‌పెట్టె"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"తపాలాపెట్టె"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"పోస్టల్ హార్న్"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"వార్తా పత్రిక"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"మొబైల్ ఫోన్"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"మొబైల్ ఫోన్‌కి ఎడమవైపున కుడివైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"వైబ్రేషన్ మోడ్"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"మొబైల్ ఫోన్ ఆఫ్"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"మొబైల్ ఫోన్‌లు నిషేధం"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"బార్‌లు ఉన్న యాంటెన్నా"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"కెమెరా"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"వీడియో కెమెరా"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"టెలివిజన్"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"రేడియో"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"వీడియో క్యాసెట్"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"మెలివేయబడి ఉన్న కుడివైపుకి చూపే బాణాలు"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"సవ్యదిశలో కుడివైపు మరియు ఎడమవైపు తెరవబడిన వృత్తాకార బాణాలు"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"వృత్తాకారంలో ఉన్న ఒకటి ఓవర్‌లేతో సవ్యదిశలో కుడివైపు మరియు ఎడమవైపు తెరవబడిన వృత్తాకార బాణాలు"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"సవ్యదిశలో క్రిందికి మరియు పైకి తెరవబడిన వృత్తాకార బాణాలు"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"అపసవ్యదిశలో క్రిందికి మరియు పైకి తెరవబడిన వృత్తాకార బాణాలు"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"తక్కువ ప్రకాశం గల చిహ్నం"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"అధిక ప్రకాశం గల చిహ్నం"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"స్పీకర్ రద్దు"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"స్పీకర్"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ఒక ధ్వని తరంగం గల స్పీకర్"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"మూడు ధ్వని తరంగాలు గల స్పీకర్"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"బ్యాటరీ"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"విద్యుత్ ప్లగ్"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"ఎడమవైపుకి చూపే భూతద్దం"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"కుడివైపుకి చూపే భూతద్దం"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"ఇంక్ పెన్‌తో పాటు తాళం"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"తాళంచెవితో పాటు మూసివేయబడిన తాళం"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"తాళంచెవి"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"తాళం"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"తెరవబడిన తాళం"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"గంట"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"గంట రద్దు"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"బుక్‌మార్క్"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"లింక్ గుర్తు"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"రేడియో బటన్"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"బ్యాక్‌కి ఎగువన ఎడమవైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"ఎండ్‌కి ఎగువన ఎడమవైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ఆశ్చర్యార్థక గుర్తు ఉన్న ఆన్‌కి ఎగువన ఎడమ, కుడి రెండువైపులకు చూపే బాణం"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"సూన్‌కి ఎగువన కుడివైపుకి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"టాప్‌కి ఎగువన పైకి చూపే బాణం"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"పద్దెనిమిది కంటే తక్కువ వయస్సుగల వారు నిషిద్ధమని చూపే గుర్తు"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"కీ మీద పది"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"లాటిన్ క్యాపిటల్ అక్షరాల కోసం ఇన్‌పుట్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"లాటిన్ చిన్న అక్షరాల కోసం ఇన్‌పుట్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"సంఖ్యల కోసం ఇన్‌పుట్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"గుర్తుల కోసం ఇన్‌పుట్ గుర్తు"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"లాటిన్ అక్షరాల కోసం ఇన్‌పుట్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"నిప్పు"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"ఎలక్ట్రిక్ టార్చ్"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"రెంచి"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"సుత్తి"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"మర మరియు బోల్టు"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"హోషో"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"పిస్టల్"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"మైక్రోస్కోప్"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"టెలిస్కోప్"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"క్రిస్టల్ బాల్"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"మధ్య చుక్క గల ఆరు పాయింట్ల నక్షత్రం"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"ప్రారంభకుల కోసం జపనీస్ గుర్తు"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"త్రిశూల చిహ్నం"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"నలుపు రంగు చతురస్రాకార బటన్"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"తెలుపు రంగు చతురస్రాకార బటన్"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"పెద్ద ఎరుపు రంగు వృత్తం"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"పెద్ద నీలి రంగు వలయం"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"పెద్ద నారింజ రంగు డైమండ్"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"పెద్ద నీలి రంగు డైమండ్"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"చిన్న నారింజ రంగు డైమండ్"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"చిన్న నీలి రంగు డైమండ్"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"పైకి చూపే ఎరుపు రంగు త్రిభుజం"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"క్రిందికి చూపే ఎరుపు రంగు త్రిభుజం"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"పైకి చూపే చిన్న ఎరుపు రంగు త్రిభుజం"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"క్రిందికి చూపే చిన్న ఎరుపు రంగు త్రిభుజం"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"ఒంటి గంటను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"రెండు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"మూడు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"నాలుగు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"ఐదు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"ఆరు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"ఏడు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"ఎనిమిది గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"తొమ్మిది గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"పది గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"పదకొండు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"పన్నెండు గంటలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"ఒక గంట ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"రెండు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"మూడు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"నాలుగు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"ఐదు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"ఆరు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"ఏడు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"ఎనిమిది గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"తొమ్మిది గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"పది గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"పదకొండు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"పన్నెండు గంటల ముప్పై నిమిషాలను చూపే గడియారం రూపం"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ఫ్యూజీ పర్వతం"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"టోక్యో టవర్"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"లిబర్టీ విగ్రహం"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"జపాన్ ఛాయాచిత్రం"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"మొయాయి"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"పళ్లు కనబడేలా నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"నవ్వుతున్న కళ్లతో ఇకిలింత ముఖం"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"ఆనందభాష్పాలు గల ముఖం"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"నోరు తెరిచి నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"నవ్వుతున్న కళ్లతో నోరు తెరిచి నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"బిగ్గరగా నవ్వుతూ, భయంతో చెమటలు పట్టిన ముఖం"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"గట్టిగా మూసుకున్న కళ్లతో నోరు తెరిచి నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"ప్రకాశ వలయం గల నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"కొమ్ములు గల నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"కనుసైగ చేస్తున్న ముఖం"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"నవ్వుతున్న కళ్లతో నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"రుచికరమైన ఆహారాన్ని ఆస్వాదిస్తున్నట్లు చూపే ముఖం"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"ఉపశమనం పొందిన ముఖం"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"హృదయాకార కళ్లతో నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"సన్‌గ్లాసులు ధరించి నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"గర్వంగా నవ్వుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"నిష్పాక్షికంగా ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"భావరహిత ముఖం"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"రంజింపచేయని ముఖం"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"భయంతో చెమటలు పట్టిన ముఖం"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"దిగులుగా వున్న ముఖం"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"అయోమయంలో ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"కలవరపడిన ముఖం"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"ముద్దు పెడుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"గాలిలో ముద్దుని వదులుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"నవ్వుతున్న కళ్లతో ముద్దు పెడుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"మూసి ఉన్న కళ్లతో ముద్దు పెడుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"నాలుకను బయటకు చూపుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"నాలుకను బయటకు పెట్టి, కనుసైగ చేస్తున్న ముఖం"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"నాలుక బయటకు పెట్టి, గట్టిగా మూసుకున్న కళ్లతో ముఖం"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"నిరాశ చెందిన ముఖం"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"వ్యాకులత చెందిన ముఖం"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"కోపంతో ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"అలిగిన ముఖం"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"ఏడుస్తున్న ముఖం"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"పట్టుదలతో ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"విజయోత్సాహం నిండి ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"మనస్తాపం చెందినట్లు ఉన్నా ఉపశమనం పొందినట్లు ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"నోరు తెరిచి కోపంతో ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"బాధాకరమైన ముఖం"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"భయంతో కూడిన ముఖం"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"విసుగు చెందిన ముఖం"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"నిద్ర పోతున్నట్లు ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"అలసిన ముఖం"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"వెక్కిరిస్తున్నట్లు ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"బిగ్గరగా ఏడుస్తున్న ముఖం"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"నోరు తెరిచి ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"నిశ్శబ్దంగా ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"నోరు తెరిచి, భయంతో చెమటలు పట్టిన ముఖం"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"భయంతో కేక పెడుతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"ఆశ్చర్యపడిన ముఖం"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"ఉద్రేకించిన ముఖం"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"నిద్రపోతున్న ముఖం"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"అస్వస్థతతో ఉండే ముఖం"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"నోరు లేని ముఖం"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"వైద్య సంబంధిత ముసుగును ధరించిన ముఖం"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"నవ్వుతున్న కళ్లతో ఇకిలిస్తున్నట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"ఆనందభాష్పాలతో ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"నోరు తెరిచి నవ్వుతున్నట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"హృదయాకార కళ్లతో నవ్వుతున్నట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"వంకర నవ్వుతో పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"మూసి ఉన్న కళ్లతో ముద్దు పెడుతున్నట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"అలిగినట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"ఏడుస్తున్నట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"విసుగు చెందినట్లు ఉండే పిల్లి ముఖం"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"ఎటువంటి మంచి సంజ్ఞ చేయని ముఖం"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"సరే సంజ్ఞతో ఉన్న ముఖం"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"వ్యక్తి వినమ్రంగా వంగడం"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"చెడు చూడకు అని సంజ్ఞ చేసే కోతి"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"చెడు వినకు అని సంజ్ఞ చేసే కోతి"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"చెడు మాట్లాడకు అని సంజ్ఞ చేసే కోతి"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"వ్యక్తి సంతోషంగా ఒక చేతిని పైకి ఎత్తడం"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"వేడుకలో రెండు చేతులు పైకెత్తిన వ్యక్తి"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"కోపంగా ఉన్న వ్యక్తి"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"అలిగిన ముఖంతో ఉండే వ్యక్తి"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"చేతులు కట్టుకున్న వ్యక్తి"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"రాకెట్"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"హెలికాప్టర్"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"ఆవిరితో నడిచే రైలు"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"రైల్వే కారు"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"అత్యంత వేగవంతమైన రైలు"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"బుల్లెట్ మొన గల అత్యంత వేగవంతమైన రైలు"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"రైలు"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"మెట్రో"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"లైట్ రైలు"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"స్టేషన్"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ట్రామ్"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ట్రామ్ కారు"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"బస్సు"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"రానున్న బస్సు"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ట్రాలీబస్సు"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"బస్ స్టాప్"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"చిన్నబస్సు"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"అంబులెన్స్‌"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"అగ్నిమాపక యంత్రం"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"పోలీసు కారు"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"రానున్న పోలీసు కారు"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"ట్యాక్సీ"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"రానున్న ట్యాక్సీ"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"ఆటోమొబైల్"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"రానున్న ఆటోమొబైల్"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"వినోదభరిత వాహనం"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"డెలివరీ ట్రక్"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"జాయింట్లుగా కలపబడిన లారీ"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ట్రాక్టర్"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"మోనోరైల్"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"పర్వత రైల్వే"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"సస్పెన్షన్ రైల్వే"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"మౌంటెయిన్ కేబుల్‌వే"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ఏరియల్ ట్రామ్‌వే"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"ఓడ"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"చిన్న పడవ"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"వేగవంతమైన పడవ"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"సమతల ట్రాఫిక్ లైట్"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"లంబంగా ఉండే ట్రాఫిక్ లైట్"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"నిర్మాణం చిహ్నం"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"పోలీసు కార్లపై తిరిగే లైట్"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"పోస్ట్‌పై త్రిభుజాకార పతాకం"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"తలుపు"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"ప్రవేశం లేదు అని సూచించే చిహ్నం"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"స్మోకింగ్ చిహ్నం"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"ధూమపానం చేయవద్దు అని సూచించే గుర్తు"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"చెత్తను చెత్తకుండీలో వేయడానికి చిహ్నం"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"చెత్త వేయవద్దు అని సూచించే చిహ్నం"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"త్రాగునీరు చిహ్నం"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"నీరు రావడం లేదు చిహ్నం"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"సైకిల్"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"సైకిల్‌లు నిషిద్ధం"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"సైకిల్ నడిపేవారు"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"పర్వతంపై సైకిల్ నడిపేవారు"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"పాదచారి"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"పాదచారులు నిషిద్ధం"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"చిన్నపిల్లలు రహదారి దాటే కూడలి"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"పురుషుల చిహ్నం"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"స్త్రీల చిహ్నం"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"విశ్రాంతిగది"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"శిశువు చిహ్నం"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"మరుగుదొడ్డి"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"వాటర్ క్లోసెట్"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"షవర్"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"స్నానం"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"స్నానపు తొట్టె"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"పాస్‌పోర్ట్ నియంత్రణ"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"కస్టమ్స్"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"బ్యాగేజీ క్లెయిమ్"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"సామాను ఉంచు స్థలం"</string>
+</resources>
diff --git a/java/res/values-te-rIN/strings-talkback-descriptions.xml b/java/res/values-te-rIN/strings-talkback-descriptions.xml
index 175b13e..3c7a989 100644
--- a/java/res/values-te-rIN/strings-talkback-descriptions.xml
+++ b/java/res/values-te-rIN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"వచనం ఏదీ నమోదు చేయబడలేదు"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>ని <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>గా సరి చేస్తుంది"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> స్వీయ-సవరణను అమలు చేస్తుంది"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"సూచన లేదు"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"తెలియని అక్షరం"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"షిప్ట్"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"మరిన్ని గుర్తులు"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"క్యాపిటల్ I, ఎగువన చుక్క"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"తెలియని చిహ్నం"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"తెలియని ఎమోజీ"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"చికాకుగా ఉండే ముఖం"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"కలవరపడే ముఖం"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"కళ్లద్దాలు ధరించిన ముఖం"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"ఆశ్చర్యపడే ముఖం"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"ముద్దు పెడుతున్న ముఖం"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"కోపంతో ఉండే ముఖం"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"ప్రత్యామ్నాయ అక్షరాలు అందుబాటులో ఉన్నాయి"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ప్రత్యామ్నాయ అక్షరాలు తీసివేయబడ్డాయి"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ప్రత్యామ్నాయ సూచనలు అందుబాటులో ఉన్నాయి"</string>
diff --git a/java/res/values-te-rIN/strings.xml b/java/res/values-te-rIN/strings.xml
index fa46f64..085639c 100644
--- a/java/res/values-te-rIN/strings.xml
+++ b/java/res/values-te-rIN/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"కీని నొక్కినప్పుడు వైబ్రేట్"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"కీని నొక్కినప్పుడు ధ్వని"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"కీని నొక్కినప్పుడు పాప్‌అప్ చూపు"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ప్రాధాన్యతలు"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"ఖాతాలు &amp; గోప్యత"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"కనిపించే తీరు &amp; లేఅవుట్‌లు"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"సంజ్ఞ టైపింగ్"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"వచన సవరణ"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"అధునాతనం"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"థీమ్"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"విభజన కీబోర్డ్‌ను ప్రారంభించు"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google కీబోర్డ్ సమకాలీకరణ"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"సమకాలీకరణ ఆన్ చేయబడింది"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"పరికరాల్లో మీ వ్యక్తిగత నిఘంటువును సమకాలీకరించండి"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ఇప్పుడే సమకాలీకరించు"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"cloud డేటాను తొలగించండి"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"మీ సమకాలీకృత డేటాను Google నుండి తొలగిస్తుంది"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"cloud నుండి మీ సమ. డేటా తొలగించబడుతుంది. మీరు చేయాలనుకుంటున్నారా?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"తొలగించు"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"రద్దు చేయి"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"మీ వ్యక్తిగత నిఘంటువు Google సర్వర్‌లకు సమకాలీకరించబడుతుంది మరియు బ్యాకప్ చేయబడుతుంది. మా ఉత్పత్తులను మెరుగుపరచడంలో సహాయకరంగా ఉండటానికి పదం తరచుదనానికి సంబంధించిన గణాంక సమాచారం సేకరించవచ్చు. మొత్తం సమాచార సేకరణ మరియు వినియోగం "<a href="https://www.google.com/policies/privacy">"Google గోప్యతా విధానం"</a>"కి లోబడి ఉంటుంది."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"దయచేసి ఈ లక్షణాన్ని ప్రారంభించడానికి ఈ పరికరానికి Google ఖాతాను జోడించండి"</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">"భాష మార్పు కీ ఇతర ఇన్‌పుట్ పద్ధతులను కూడా కవర్ చేస్తుంది"</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">"స్లైడ్ సూచికను చూపు"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Shift లేదా గుర్తు కీల నుండి స్లైడ్ చేసేటప్పుడు దృశ్యమాన సంకేతాన్ని ప్రదర్శించు"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"వాయిస్ ఇన్‌పుట్ కీ"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"వాయిస్ ఇన్‌పుట్ పద్ధతులు ఏవీ ప్రారంభించబడలేదు. భాష &amp; ఇన్‌పుట్ సెట్టింగ్‌లను తనిఖీ చేయండి."</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="language_selection_title" msgid="3666971864764478269">"భాషలు"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"సహాయం &amp; అభిప్రాయం"</string>
+    <string name="select_language" msgid="5709487854987078367">"భాషలు"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"సేవ్ చేయడానికి మళ్లీ తాకండి"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"సేవ్ చేయడానికి ఇక్కడ తాకండి"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"నిఘంటువు అందుబాటులో ఉంది"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"కీబోర్డ్ థీమ్"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"ఖాతాలు మార్చండి"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ఖాతాలు ఏవీ ఎంచుకోబడలేదు"</string>
+    <string name="account_selected" msgid="2846876462199625974">"ప్రస్తుతం <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>ని ఉపయోగిస్తున్నారు"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"సరే"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"రద్దు చేయి"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"సైన్ అవుట్ చేయండి"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"ఉపయోగించడానికి ఖాతాను ఎంచుకోండి"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"ఆంగ్లం (యుకె)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"ఆంగ్లం (యుఎస్)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"స్పానిష్ (యుఎస్)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"హింగ్లీష్"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"సెర్బియన్ (లాటిన్)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"ఆంగ్లం (యుకె) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"ఆంగ్లం (యుఎస్) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"స్పానిష్ (యుఎస్) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"హింగ్లీష్ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"సెర్బియన్ (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (సాంప్రదాయకం)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (సిరిలిక్)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (లాటిన్)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (కాంపాక్ట్)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"భాష లేదు (ఆల్ఫాబెట్)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ఆల్ఫాబెట్ (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ఆల్ఫాబెట్ (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ఆల్ఫాబెట్ (కోల్‌మాక్)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ఆల్ఫాబెట్ (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"ఎమోజి"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"కీబోర్డ్ థీమ్"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"అనుకూల ఇన్‌పుట్ శైలులు"</string>
     <string name="add_style" msgid="6163126614514489951">"శైలిని జోడించండి"</string>
     <string name="add" msgid="8299699805688017798">"జోడించండి"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> కోసం ఈ ఫైల్‌ను నిజంగానే ఇన్‌స్టాల్ చేయాలా?"</string>
-    <string name="error" msgid="8940763624668513648">"లోపం ఏర్పడింది"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"కీని ఎక్కువసేపు నొక్కి ఉంచాల్సిన సమయంలో ఆలస్యం"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ఇప్పుడు మీరు <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">"లాంచర్‌లో అనువర్తన చిహ్నాన్ని ప్రదర్శించు"</string>
     <string name="app_name" msgid="6320102637491234792">"నిఘంటువు ప్రదాత"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"నిఘంటువు ప్రదాత"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"నిఘంటువు సేవ"</string>
diff --git a/java/res/values-th/strings-emoji-descriptions.xml b/java/res/values-th/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..86ab2c0
--- /dev/null
+++ b/java/res/values-th/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"เครื่องหมายลิขสิทธิ์"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"เครื่องหมายการค้าจดทะเบียน"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"เครื่องหมายอัศเจรีย์ 2 ตัว"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"เครื่องหมายอัศเจรีย์และคำถาม"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"สัญลักษณ์เครื่องหมายการค้า"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"แหล่งข้อมูล"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"ลูกศรชี้ซ้ายและขวา"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"ลูกศรชี้บนและล่าง"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"ลูกศรเฉียงบนซ้าย"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"ลูกศรเฉียงบนขวา"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"ลูกศรเฉียงล่างขวา"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"ลูกศรเฉียงล่างซ้าย"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"ลูกศรชี้ซ้ายงอเป็นตะขอ"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"ลูกศรชี้ขวางอเป็นตะขอ"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"นาฬิกา"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"นาฬิกาทราย"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"สามเหลี่ยมซ้อน 2 ชั้นปลายชี้ไปทางขวาสีดำ"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"สามเหลี่ยมซ้อน 2 ชั้นปลายชี้ไปทางซ้ายสีดำ"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"สามเหลี่ยมซ้อน 2 ชั้นปลายชี้ขึ้นสีดำ"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"สามเหลี่ยมซ้อน 2 ชั้นปลายชี้ลงสีดำ"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"นาฬิกาปลุก"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"นาฬิกาทรายที่ทรายกำลังไหล"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"ตัวอักษร M แบบละตินตัวพิมพ์ใหญ่มีวงกลมล้อมรอบ"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"สี่เหลี่ยมจัตุรัสเล็กสีดำ"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"สี่เหลี่ยมจัตุรัสเล็กสีขาว"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"สามเหลี่ยมปลายชี้ไปทางขวาสีดำ"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"สามเหลี่ยมปลายชี้ไปทางซ้ายสีดำ"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"สี่เหลี่ยมจัตุรัสขนาดกลางสีขาว"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"สี่เหลี่ยมจัตุรัสขนาดกลางสีดำ"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"สี่เหลี่ยมจัตุรัสเล็กปานกลางสีขาว"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"สี่เหลี่ยมจัตุรัสเล็กปานกลางสีดำ"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"พระอาทิตย์และรัศมีสีดำ"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"เมฆ"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"โทรศัพท์สีดำ"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"ช่องที่มีเครื่องหมายถูก"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"ร่มและหยดฝน"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"เครื่องดื่มร้อน"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"นิ้วชี้ชี้ขึ้นสีขาว"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"หน้ายิ้มสีขาว"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"ราศีเมษ"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"ราศีพฤษภ"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"ราศีเมถุน"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"ราศีกรกฎ"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"ราศีสิงห์"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"ราศีกันย์"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"ราศีตุลย์"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"ราศีพิจิก"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"ราศีธนู"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"ราศีมังกร"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"ราศีกุมภ์"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"ราศีมีน"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"ชุดไพ่รูปโพดำ"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"ชุดไพ่รูปดอกจิกสีดำ"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"ชุดไพ่รูปหัวใจสีดำ"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"ชุดไพ่รูปข้าวหลามตัดสีดำ"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"น้ำพุร้อน"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"สัญลักษณ์การรีไซเคิลสากลสีดำ"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"สัญลักษณ์รถเข็น"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"สมอ"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"ป้ายคำเตือน"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"สัญญาณแรงดันไฟฟ้าสูง"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"วงกลมสีขาวขนาดกลาง"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"วงกลมสีดำขนาดกลาง"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"ลูกฟุตบอล"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"เบสบอล"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"มนุษย์หิมะไม่มีหิมะ"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"ดวงอาทิตย์หลังเมฆ"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ราศีคนแบกงู"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"ห้ามเข้า"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"โบสถ์"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"น้ำพุ"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"ธงปักในหลุม"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"เรือใบ"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"เต็นท์"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"ปั๊มน้ำมัน"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"กรรไกรสีดำ"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"เครื่องหมายเลือกสีขาวแบบหนา"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"เครื่องบิน"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"ซองจดหมาย"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"ยกกำปั้น"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"ยกมือ"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"มือชู 2 นิ้ว"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"ดินสอ"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"หัวปากกาสีดำ"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"เครื่องหมายถูกแบบหนา"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"เครื่องหมายคูณแบบหนา"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"ประกายระยิบระยับ"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"ดอกจัน 8 แฉก"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"ดาว 8 แฉกสีดำ"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"เกล็ดหิมะ"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"ประกาย"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"เครื่องหมายกากบาท"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"เครื่องหมายกากบาทในกรอบสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"ตัวเครื่องหมายคำถามสีดำ"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"ตัวเครื่องหมายคำถามสีขาว"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"ตัวเครื่องหมายอัศเจรีย์สีขาว"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"เครื่องหมายอัศเจรีย์แบบหนา"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"หัวใจสีดำเข้ม"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"เครื่องหมายบวกแบบหนา"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"เครื่องหมายลบแบบหนา"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"เครื่องหมายหารแบบหนา"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"ลูกศรชี้ขวาสีดำ"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"เส้นม้วนเป็นห่วง"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"เส้นม้วนเป็นห่วง 2 ห่วง"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"ลูกศรโค้งขึ้นทางขวา"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"ลูกศรโค้งลงทางขวา"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"ลูกศรชี้ซ้ายสีดำ"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"ลูกศรขึ้นสีดำ"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"ลูกศรลงสีดำ"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"สี่เหลี่ยมจัตุรัสขนาดใหญ่สีดำ"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"สี่เหลี่ยมจัตุรัสขนาดใหญ่สีขาว"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"ดาวขนาดกลางสีขาว"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"วงกลมใหญ่หนา"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"ขีดคลื่น"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"เครื่องหมายบ่งบอกว่าคำพูดนี้มาจากเพลงหรือเป็นเพลง"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"ตัวอักษรหมายถึงแสดงความยินดีที่มีวงกลมล้อมรอบ"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"ตัวอักษรหมายถึงความลับที่มีวงกลมล้อมรอบ"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"ไพ่นกกระจอกรูปมังกรแดง"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"ไพ่โจกเกอร์สีดำ"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"กรุ๊ปเลือด A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"กรุ๊ปเลือด B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"กรุ๊ปเลือด O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"ที่จอดรถ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"กรุ๊ปเลือด AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"COOL ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"FREE ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"NEW ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"NG ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"UP และอัศเจรีย์ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"VS ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"ตัวอักษรคาตาคานะ \"ที่นี่\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"ตัวอักษรคาตาคานะ \"บริการ\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"ตัวอักษรแสดงความหมาย \"ไม่มีค่าบริการ\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"ตัวอักษรแสดงความหมาย \"ที่นั่งที่จองแล้ว\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"ตัวอักษรแสดงความหมาย \"ข้อห้าม\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"ตัวอักษรแสดงความหมาย \"ว่าง\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"ตัวอักษรแสดงความหมาย \"การยอมรับ\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"ตัวอักษรแสดงความหมาย \"เต็ม\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"ตัวอักษรแสดงความหมาย \"จ่ายแล้ว\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"ตัวอักษรแสดงความหมาย \"รายเดือน\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"ตัวอักษรแสดงความหมาย \"แอปพลิเคชัน\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"ตัวอักษรแสดงความหมาย \"ส่วนลด\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"ตัวอักษรแสดงความหมาย \"มีธุระ\" ในสี่เหลี่ยม"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"ตัวอักษรแสดงความหมาย \"ข้อได้เปรียบ\" ในวงกลม"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"ตัวอักษรแสดงความหมาย \"ยอมรับ\" ในวงกลม"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"ไซโคลน"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"หมอก"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"ร่มหุบ"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"ค่ำคืนที่มีดาว"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"ดวงอาทิตย์ขึ้นเหนือภูเขา"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"ดวงอาทิตย์ขึ้น"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"ทิวทัศน์เมืองในยามค่ำ"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"ดวงอาทิตย์ตกเหนือสิ่งปลูกสร้าง"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"รุ้ง"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"สะพานยามค่ำคืน"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"คลื่นน้ำ"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"ภูเขาไฟ"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"ทางช้างเผือก"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"แผนที่โลกทวีปยุโรป-แอฟริกา"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"แผนที่โลกทวีปอเมริกา"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"แผนที่โลกทวีปเอเชีย-ออสเตรเลีย"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"แผนที่โลกมีเส้นเมริเดียน"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"สัญลักษณ์วันเดือนดับ"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"สัญลักษณ์ดวงจันทร์เสี้ยวข้างขึ้น"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"สัญลักษณ์ดวงจันทร์ครึ่งดวงครั้งแรก"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"สัญลักษณ์ดวงจันทร์ค่อนดวงข้างขึ้น"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"สัญลักษณ์ดวงจันทร์เต็มดวง"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"สัญลักษณ์ดวงจันทร์ค่อนดวงข้างแรม"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"สัญลักษณ์ดวงจันทร์ครึ่งดวงครั้งสุดท้าย"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"สัญลักษณ์ดวงจันทร์เสี้ยวข้างแรม"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"ดวงจันทร์เสี้ยว"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"จันทร์ดับมีรูปหน้า"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"ดวงจันทร์ครึ่งดวงข้างขึ้นมีรูปหน้า"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"ดวงจันทร์ครึ่งดวงข้างแรมมีรูปหน้า"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"ดวงจันทร์เต็มดวงมีรูปหน้า"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"ดวงอาทิตย์มีรูปหน้า"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"ดาวส่องแสง"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"ดาวตก"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"เกาลัด"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"ต้นกล้า"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"ต้นสน"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"ต้นไม้ผลัดใบ"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"ต้นปาล์ม"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"ต้นกระบองเพชร"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"ดอกทิวลิป"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"ดอกซากุระ"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"ดอกกุหลาบ"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"ดอกชบา"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"ดอกทานตะวัน"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"ดอกไม้บาน"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"ฝักข้าวโพด"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"รวงข้าว"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"สมุนไพร"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"ใบโคลเวอร์ 4 แฉก"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"ใบเมเปิ้ล"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"ใบไม้ร่วง"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"ใบไม้ปลิวในสายลม"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"เห็ด"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"มะเขือเทศ"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"มะเขือยาว"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"องุ่น"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"เมลอน"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"แตงโม"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"ส้มเขียวหวาน"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"มะนาว"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"กล้วย"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"สับปะรด"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"แอปเปิ้ลแดง"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"แอปเปิ้ลเขียว"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"ลูกแพร์"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"ลูกพีช"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"เชอร์รี่"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"สตรอเบอร์รี่"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"แฮมเบอร์เกอร์"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"ชิ้นพิซซ่า"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"เนื้อหุ้มกระดูก"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"น่องไก่"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"ข้าวอบกรอบ"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"ข้าวปั้น"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"ข้าวสวย"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"ข้าวราดแกง"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"ชามอาหารยังร้อน"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"สปาเก็ตตี้"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"ขนมปัง"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"มันฝรั่งทอด"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"มันเทศเผา"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"ดังโกะ"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"โอเด้ง"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"ซูชิ"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"กุ้งทอด"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"แผ่นลูกชิ้นปลาลายขด"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"ซอฟต์ไอศกรีม"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"น้ำแข็งใส"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"ไอศกรีม"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"โดนัท"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"คุกกี้"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"ช็อกโกแลตแท่ง"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"ลูกกวาด"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"อมยิ้ม"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"คัสตาร์ด"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"โถน้ำผึ้ง"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"ชอร์ตเค้ก"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"ข้าวกล่อง"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"หม้อต้มอาหาร"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"การทำอาหาร"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"ส้อมและมีด"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"ถ้วยน้ำชาไม่มีหู"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"ขวดเหล้าสาเกและถ้วย"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"แก้วไวน์"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"แก้วค็อกเทล"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"เครื่องดื่มคลายร้อน"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"แก้วเบียร์"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"ชนแก้วเบียร์"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"ขวดนมเด็ก"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ริบบิ้น"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"กล่องของขวัญ"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"เค้กวันเกิด"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"โคมฟักทอง"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"ต้นคริสต์มาส"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"ซานตาคลอส"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"ดอกไม้ไฟ"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"ประกายดอกไม้ไฟ"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"ลูกโป่ง"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"พลุสายรุ้งสำหรับปาร์ตี้"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"ลูกบอลบรรจุกระดาษสี"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"ต้นทะนะบะตะ"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"ธงไขว้"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"เครื่องประดับไม้สน"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"ตุ๊กตาญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"ธงปลาคาร์ฟ"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"กระดิ่งลม"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"พิธีชมจันทร์"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"กระเป๋านักเรียน"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"หมวกรับปริญญา"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"ม้าหมุน"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"ชิงช้าสวรรค์"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"รถไฟเหาะ"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"เบ็ดตกปลาและปลา"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"ไมโครโฟน"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"กล้องถ่ายภาพยนตร์"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"โรงภาพยนตร์"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"หูฟัง"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"จานสี"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"หมวกทรงสูง"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"เต็นท์ละครสัตว์"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"ตั๋ว"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"สเลท"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"ศิลปะการแสดง"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"เกมวิดีโอ"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"เข้าเป้า"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"เครื่องหยอดเหรียญเล่นพนัน"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"บิลเลียด"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"ลูกเต๋า"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"โบว์ลิ่ง"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"ไพ่ดอกไม้"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"โน้ตเพลง"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"โน้ตเพลงหลายตัว"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"แซ็กโซโฟน"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"กีตาร์"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"คีย์บอร์ดเล่นเพลง"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"ทรัมเป็ต"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"ไวโอลิน"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"โน้ตเพลง"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"เสื้อใส่วิ่งมีแถบเฉียง"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"ไม้และลูกเทนนิส"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"สกีและรองเท้าสกี"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"บาสเก็ตบอลและห่วง"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"ธงตราหมากรุก"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"นักเล่นสโนว์บอร์ด"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"นักวิ่ง"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"นักโต้คลื่น"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ถ้วยรางวัล"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"การแข่งม้า"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"อเมริกันฟุตบอล"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"รักบี้"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"นักว่ายน้ำ"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"บ้าน"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"บ้านพร้อมสวน"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"อาคารสำนักงาน"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"ไปรษณีย์ญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"ไปรษณีย์ยุโรป"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"โรงพยาบาล"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"ธนาคาร"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ตู้เอทีเอ็ม"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"โรงแรม"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"โรงแรมสำหรับคู่รัก"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"ร้านสะดวกซื้อ"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"โรงเรียน"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ห้างสรรพสินค้า"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"โรงงาน"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"โคมไฟญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"ปราสาทญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"ปราสาทยุโรป"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"หนูนา"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"หนู"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"วัว"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"ควาย"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"วัว"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"เสือดาว"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"กระต่าย"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"แมว"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"มังกร"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"จระเข้"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"ปลาวาฬ"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"หอยทาก"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"งู"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"ม้า"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"แกะตัวผู้"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"แพะ"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"แกะ"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"ลิง"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"ไก่ตัวผู้"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"ไก่"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"สุนัข"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"หมู"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"หมูป่าตัวผู้"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ช้าง"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"ปลาหมึก"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"หอยโข่ง"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"แมลง"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"มด"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"ผึ้ง"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"แมลงเต่าทอง"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"ปลา"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"ปลาในเขตร้อน"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"ปลาปักเป้า"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"เต่า"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"ไข่ฟักตัว"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"ลูกเจี๊ยบ"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"ลูกเจี๊ยบหันหน้า"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"นก"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"เพนกวิน"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"โคอาลา"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"พุดเดิ้ล"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"อูฐหนอกเดียว"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"อูฐ 2 หนอก"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"ปลาโลมา"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"หน้าหนู"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"หน้าวัว"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"หน้าเสือ"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"หน้ากระต่าย"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"หน้าแมว"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"หน้ามังกร"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"ปลาวาฬพ่นน้ำ"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"หน้าม้า"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"หน้าลิง"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"หน้าสุนัข"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"หน้าหมู"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"หน้ากบ"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"หน้าหนูแฮมสเตอร์"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"หน้าหมาป่า"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"หน้าหมี"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"หน้าแพนด้า"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"จมูกหมู"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"รอยอุ้งเท้า"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"ตา"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"หู"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"จมูก"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"ปาก"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"ลิ้น"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"นิ้วชี้หลังมือสีขาวชี้ขึ้น"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"นิ้วชี้หลังมือสีขาวชี้ลง"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"นิ้วชี้หลังมือสีขาวชี้ไปทางซ้าย"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"นิ้วชี้หลังมือสีขาวชี้ไปทางขวา"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"เครื่องหมายกำปั้น"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"เครื่องหมายโบกมือ"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"เครื่องหมายทำท่า \"OK\""</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"เครื่องหมายยกนิ้วโป้งขึ้น"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"เครื่องหมายคว่ำนิ้วโป้งลง"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"เครื่องหมายปรบมือ"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"เครื่องหมายแบมือ"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"มงกุฎ"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"หมวกผู้หญิง"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"แว่นตา"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"เนกไท"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"เสื้อยืด"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"กางเกงยีนส์"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"เสื้อชุดสตรี"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"ชุดกิโมโน"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"บิกินี่"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"เสื้อผ้าสตรี"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"กระเป๋าสตางค์"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"กระเป๋าถือ"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"กระเป๋า"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"รองเท้าผู้ชาย"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"รองเท้านักกีฬา"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"รองเท้าส้นสูง"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"รองเท้าแตะผู้หญิง"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"รองเท้าบูทผู้หญิง"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"รอยเท้า"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"ภาพเงาคนจากหัวถึงช่วงหน้าอก"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"ภาพเงาคนหลายคนจากหัวถึงช่วงหน้าอก"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"เด็กชาย"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"เด็กหญิง"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"ผู้ชาย"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"ผู้หญิง"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"ครอบครัว"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"ผู้ชายและผู้หญิงจับมือกัน"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"ผู้ชาย 2 คนจับมือกัน"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"ผู้หญิง 2 คนจับมือกัน"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"เจ้าหน้าที่ตำรวจ"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"ผู้หญิงติดหูกระต่าย"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"เจ้าสาวมีผ้าคลุมหน้า"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"คนมีผมบลอนด์"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"ชายสวมหมวกแบบจีน"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"คนสวมผ้าโพกหัว"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"ผู้ชายอาวุโส"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"ผู้หญิงอาวุโส"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"ทารก"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"คนงานก่อสร้าง"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"เจ้าหญิง"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"ปีศาจญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"ปีศาจญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"ผี"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"ทูตสวรรค์น้อย"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"มนุษย์ต่างดาว"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"ปีศาจต่างดาว"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"ภูตน้อย"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"กะโหลกศีรษะ"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"ผู้ให้บริการข้อมูล"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"องครักษ์"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"นักเต้น"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"ลิปสติก"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"ยาทาเล็บ"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"การนวดหน้า"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"ตัดผม"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"ไฟหมุนหน้าร้านตัดผม"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"เข็มฉีดยา"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ยา"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"เครื่องหมายจูบ"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"จดหมายรัก"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"แหวน"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"หินอัญมณี"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"จูบ"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"ช่อดอกไม้"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"คู่รักและรูปหัวใจ"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"การแต่งงาน"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"หัวใจเต้น"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"หัวใจแตกสลาย"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"หัวใจ 2 ดวง"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"หัวใจเป็นประกาย"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"หัวใจพองโต"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"หัวใจมีลูกศร"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"หัวใจสีฟ้า"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"หัวใจสีเขียว"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"หัวใจสีเหลือง"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"หัวใจสีม่วง"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"หัวใจพาดริบบิ้น"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"หัวใจหมุน"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"ลายรูปหัวใจ"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"รูปเพชรมีจุดภายใน"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"หลอดไฟฟ้า"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"สัญลักษณ์ความโกรธ"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"ระเบิด"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"สัญลักษณ์การนอนหลับ"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"สัญลักษณ์การชนกัน"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"สัญลักษณ์เหงื่อกระเด็น"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"หยดน้ำ"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"สัญลักษณ์ยัติภาค"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"กองอุจจาระ"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"เกร็งกล้ามแขนส่วนบน"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"สัญลักษณ์วิงเวียน"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"บอลลูนคำพูด"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"บอลลูนความคิด"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"ดอกไม้สีขาว"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"สัญลักษณ์ร้อยเต็ม"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"ถุงเงิน"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"แลกเปลี่ยนเงินตรา"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"เครื่องหมายดอลลาร์แบบหนา"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"บัตรเครดิต"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ธนบัตรมีสัญลักษณ์เงินเยน"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ธนบัตรมีสัญลักษณ์เงินดอลลาร์"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"ธนบัตรมีสัญลักษณ์เงินยูโร"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"ธนบัตรมีสัญลักษณ์เงินปอนด์"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"เงินมีปีก"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"แผนภูมิมีแนวโน้มขาขึ้นและสัญลักษณ์เงินเยน"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"ที่นั่ง"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"คอมพิวเตอร์ส่วนบุคคล"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"กระเป๋าเอกสาร"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"ดิสก์ขนาดเล็ก"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"ฟลอปปี้ดิสก์"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"จานแสง"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"ดีวีดี"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"โฟลเดอร์ไฟล์"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"โฟลเดอร์ไฟล์เปิดอยู่"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"หน้ากระดาษม้วนขึ้น"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"หน้าหงายขึ้น"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"ปฏิทิน"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"ปฏิทินแบบฉีก"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"ดัชนีบัตร"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"แผนภูมิมีแนวโน้มขาขึ้น"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"แผนภูมิมีแนวโน้มขาลง"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"กราฟแท่ง"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"คลิปบอร์ด"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"หมุดปัก"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"หมุดปักหัวกลม"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"คลิปหนีบกระดาษ"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"ไม้บรรทัดตรง"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"ไม้ฉาก"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"แถบคั่นหนังสือ"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"สมุดบัญชีแยกประเภท"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"สมุดบันทึก"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"สมุดบันทึกมีลายที่ปก"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"หนังสือปิดอยู่"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"หนังสือเปิดอยู่"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"หนังสือสีเขียว"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"หนังสือสีฟ้า"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"หนังสือสีส้ม"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"กองหนังสือ"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"ป้ายชื่อ"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"ม้วนกระดาษ"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"บันทึก"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"เครื่องรับโทรศัพท์"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"เพจเจอร์"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"เครื่องแฟกซ์"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"จานดาวเทียม"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"ตู้ลำโพงกลางแจ้ง"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"โทรโข่งเชียร์"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"ถาดกล่องขาออก"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ถาดกล่องขาเข้า"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"พัสดุ"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"สัญลักษณ์อีเมล"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"ซองจดหมายเข้ามาใหม่"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"ซองจดหมายมีลูกศรชี้ลงอยู่ข้างบน"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"กล่องจดหมายปิดที่ธงคว่ำลง"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"กล่องจดหมายปิดที่ธงยกขึ้น"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"กล่องจดหมายเปิดที่ธงยกขึ้น"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"กล่องจดหมายเปิดที่ธงคว่ำลง"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"ตู้ไปรษณีย์"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"แตรไปรษณีย์"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"หนังสือพิมพ์"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"โทรศัพท์มือถือ"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"โทรศัพท์มือถือมีลูกศรชี้ไปทางขวาอยู่ด้านซ้าย"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"โหมดการสั่น"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"โทรศัพท์มือถือปิดเครื่อง"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"ไม่มีโทรศัพท์มือถือ"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"เสาอากาศมีแถบสัญญาณ"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"กล้องถ่ายรูป"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"กล้องวิดีโอ"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"โทรทัศน์"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"วิทยุ"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"วิดีโอเทป"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"ลูกศรบิดไปทางขวา"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"ลูกศรชี้ไปทางขวาและทางซ้ายตามเข็มนาฬิกาเป็นวงกลมเปิด"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"ลูกศรชี้ไปทางขวาและทางซ้ายตามเข็มนาฬิกาเป็นวงกลมเปิดที่มีเลข 1 ในวงกลม"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"ลูกศรชี้ลงและขึ้นตามเข็มนาฬิกาเป็นวงกลมเปิด"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"ลูกศรชี้ลงและขึ้นทวนเข็มนาฬิกาเป็นวงกลมเปิด"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"สัญลักษณ์ความสว่างต่ำ"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"สัญลักษณ์ความสว่างสูง"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"ลำโพงมีเส้นขีดทับ"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"ลำโพง"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ลำโพงมีคลื่นเสียง 1 คลื่น"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"ลำโพงมีคลื่นเสียง 3 คลื่น"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"แบตเตอรี่"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"ปลั๊กไฟ"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"แว่นขยายส่องไปทางซ้าย"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"แว่นขยายส่องไปทางขวา"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"กุญแจและปากกาหมึกซึม"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"กุญแจล็อกและลูกกุญแจ"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"ลูกกุญแจ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"กุญแจล็อก"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"กุญแจปลดล็อก"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"ระฆัง"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"ระฆังมีเส้นขีดทับ"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"ที่คั่นหนังสือ"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"สัญลักษณ์เชื่อมโยง"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ปุ่มตัวเลือก"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"ข้อความ \"BACK\" และลูกศรชี้ซ้ายอยู่ด้านบน"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"ข้อความ \"END\" และลูกศรชี้ซ้ายอยู่ด้านบน"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"ข้อความ \"ON\" พร้อมอัศเจรีย์และลูกศรชี้ซ้ายและขวาอยู่ด้านบน"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"ข้อความ \"SOON\" และลูกศรชี้ขวาอยู่ด้านบน"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"ข้อความ \"TOP\" และลูกศรชี้ขึ้นอยู่ด้านบน"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"สัญลักษณ์ห้ามผู้มีอายุต่ำกว่า 18 ปี"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"ปุ่มกดเลข 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"สัญลักษณ์การป้อนข้อมูลตัวอักษรละตินพิมพ์ใหญ๋"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"สัญลักษณ์การป้อนข้อมูลตัวอักษรละตินพิมพ์เล็ก"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"สัญลักษณ์การป้อนข้อมูลตัวเลข"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"สัญลักษณ์การป้อนเครื่องหมาย"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"สัญลักษณ์การป้อนข้อมูลตัวอักษรละติน"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"ไฟ"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"ไฟฉาย"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"ประแจ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"ค้อน"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"แป้นเกลียวและสลักเกลียว"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"มีดทำครัว"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"ปืนพก"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"กล้องจุลทรรศน์"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"กล้องโทรทรรศน์"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"ลูกแก้ว"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"ดาว 6 แฉกมีจุดตรงกลาง"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"สัญลักษณ์ญี่ปุ่นแทนการเริ่มต้น"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"สัญลักษณ์ตรีศูล"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"ปุ่มสี่เหลี่ยมสีดำ"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"ปุ่มสี่เหลี่ยมสีขาว"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"วงกลมสีแดงขนาดใหญ่"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"วงกลมสีฟ้าขนาดใหญ่"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"เพชรสีส้มขนาดใหญ่"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"เพชรสีฟ้าขนาดใหญ่"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"เพชรสีส้มขนาดเล็ก"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"เพชรสีฟ้าขนาดเล็ก"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"สามเหลี่ยมปลายชี้ขึ้นสีแดง"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"สามเหลี่ยมปลายชี้ลงสีแดง"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"สามเหลี่ยมเล็กปลายชี้ขึ้นสีแดง"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"สามเหลี่ยมเล็กปลายชี้ลงสีแดง"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"นาฬิกาบอกเวลา 1 นาฬิกา"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"นาฬิกาบอกเวลา 2 นาฬิกา"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"นาฬิกาบอกเวลา 3 นาฬิกา"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"นาฬิกาบอกเวลา 4 นาฬิกา"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"นาฬิกาบอกเวลา 5 นาฬิกา"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"นาฬิกาบอกเวลา 6 นาฬิกา"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"นาฬิกาบอกเวลา 7 นาฬิกา"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"นาฬิกาบอกเวลา 8 นาฬิกา"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"นาฬิกาบอกเวลา 9 นาฬิกา"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"นาฬิกาบอกเวลา 10 นาฬิกา"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"นาฬิกาบอกเวลา 11 นาฬิกา"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"นาฬิกาบอกเวลา 12 นาฬิกา"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"นาฬิกาบอกเวลา 1 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"นาฬิกาบอกเวลา 2 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"นาฬิกาบอกเวลา 3 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"นาฬิกาบอกเวลา 4 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"นาฬิกาบอกเวลา 5 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"นาฬิกาบอกเวลา 6 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"นาฬิกาบอกเวลา 7 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"นาฬิกาบอกเวลา 8 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"นาฬิกาบอกเวลา 9 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"นาฬิกาบอกเวลา 10 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"นาฬิกาบอกเวลา 11 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"นาฬิกาบอกเวลา 12 นาฬิกา 30 นาที"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ภูเขาฟูจิ"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"หอคอยโตเกียว"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"อนุสาวรีย์เทพีเสรีภาพ"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"ภาพเงาประเทศญี่ปุ่น"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"โมอาย"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"หน้ายิ้มเห็นฟัน"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"หน้ายิ้มยิงฟันและตายิ้ม"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"หน้าที่มีน้ำตาแห่งความสุข"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"หน้ายิ้มและอ้าปาก"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"หน้ายิ้มอ้าปากและมีตายิ้ม"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"หน้ายิ้มอ้าปากและเหงื่อตก"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"หน้ายิ้มอ้าปากและหยีตา"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"หน้ายิ้มมีวงรัศมี"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"หน้ายิ้มมีเขา"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"หน้าขยิบตา"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"หน้ายิ้มและตายิ้ม"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"หน้าได้ลิ้มรสอาหารอร่อย"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"หน้าผ่อนคลาย"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"หน้ายิ้มและตาเป็นรูปหัวใจ"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"หน้ายิ้มใส่แว่นกันแดด"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"หน้ายิ้มเยาะ"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"หน้าเมินเฉย"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"หน้าไร้อารมณ์"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"หน้ารู้สึกรำคาญ"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"หน้ามีเหงื่อตก"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"หน้าหม่นหมอง"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"หน้าสับสน"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"หน้าอึดอัด"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"หน้าทำปากจูบ"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"หน้าส่งจูบ"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"หน้าทำปากจูบและมีตายิ้ม"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"หน้าทำปากจูบและปิดตา"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"หน้าแลบลิ้น"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"หน้าแลบลิ้นและขยิบตา"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"หน้าแลบลิ้นและทำตาหยี"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"หน้าผิดหวัง"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"หน้าวิตกกังวล"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"หน้าโกรธ"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"หน้ามุ่ย"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"หน้าร้องไห้"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"หน้าเอาจริงเอาจัง"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"หน้าต้องการเอาชนะ"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"หน้าผิดหวังแต่ผ่อนคลาย"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"หน้าบึ้งอ้าปาก"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"หน้าแสดงความเจ็บปวด"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"หน้าหวาดกลัว"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"หน้าเหนื่อยล้า"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"หน้าง่วงนอน"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"หน้าเหน็ดเหนื่อย"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"หน้าบูดบึ้ง"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"หน้าร้องไห้เสียงดัง"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"หน้าและปากอ้า"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"หน้าจุ๊ปาก"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"หน้าอ้าปากและเหงื่อตก"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"หน้ากรีดร้องด้วยความกลัว"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"หน้าประหลาดใจ"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"หน้าแดง"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"หน้ากำลังนอนหลับ"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"หน้าวิงเวียน"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"หน้าไม่มีปาก"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"หน้าใส่หน้ากากอนามัย"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"หน้าแมวยิ้มและตายิ้ม"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"หน้าแมวมีน้ำตาแห่งความสุข"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"หน้าแมวยิ้มปากเปิด"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"หน้าแมวยิ้มและตาเป็นรูปหัวใจ"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"หน้าแมวยิ้มมีเลศนัย"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"หน้าแมวทำปากจูบและปิดตา"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"หน้าแมวไม่พอใจ"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"หน้าแมวร้องไห้"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"หน้าแมวเหนื่อยล้า"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"หน้าและท่าทางว่าไม่ดี"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"หน้าและท่าทางว่าตกลง"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"คนโค้งคำนับ"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"ลิงปิดตา"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"ลิงปิดหู"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"ลิงปิดปาก"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"คนที่มีความสุขและชูมือ 1 ข้าง"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"คนยกมือทั้ง 2 ข้างเพื่อเฉลิมฉลอง"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"คนหน้าบึ้ง"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"คนหน้ามุ่ย"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"คนพนมมือ"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"จรวด"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"เฮลิคอปเตอร์"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"รถไฟหัวรถจักรไอน้ำ"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"รถไฟราง"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"รถไฟความเร็วสูง"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"รถไฟความเร็วสูงหัวกระสุน"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"รถไฟ"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"รถไฟใต้ดิน"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"รถไฟฟ้า"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"สถานี"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"รถราง"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"รถไฟราง"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"รถประจำทาง"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"รถประจำทางที่กำลังจะมา"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"รถโดยสารไฟฟ้า"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"ป้ายรถประจำทาง"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"รถประจำทางขนาดเล็ก"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"รถพยาบาล"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"รถดับเพลิง"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"รถตำรวจ"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"รถตำรวจที่กำลังจะมา"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"แท็กซี่"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"แท็กซี่ที่กำลังจะมา"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"รถยนต์"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"รถที่กำลังจะมา"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"รถบ้าน"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"รถบรรทุกส่งของ"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"รถบรรทุกพ่วง"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"แทรกเตอร์"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"รถไฟรางเดี่ยว"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"ทางรถไฟบนภูเขา"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"รถรางลอยฟ้า"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"เคเบิลขึ้นเขา"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"เคเบิล"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"เรือ"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"เรือพาย"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"เรือเร็ว"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"สัญญาณไฟจราจรแนวนอน"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"ไฟจราจรแนวตั้ง"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"สัญลักษณ์ก่อสร้าง"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"ไฟหมุนบนรถตำรวจ"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"ธงสามเหลี่ยมบนเสา"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"ประตู"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"ป้ายห้ามเข้า"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"ป้ายสูบบุหรี่"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"สัญลักษณ์ห้ามสูบบุหรี่"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"ป้ายทิ้งขยะในที่ทิ้ง"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"ป้ายห้ามทิ้งขยะ"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"ป้ายน้ำดื่มได้"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"ป้ายน้ำดื่มไม่ได้"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"รถจักรยาน"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"ห้ามรถจักรยาน"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"นักขี่จักรยาน"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"นักขี่จักรยานภูเขา"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"คนเดินเท้า"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"ห้ามเดินเท้า"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"เด็กข้ามถนน"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"สัญลักษณ์ผู้ชาย"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"สัญลักษณ์ผู้หญิง"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"ห้องน้ำ"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"สัญลักษณ์เด็กทารก"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"ห้องน้ำ"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"ห้องส้วม"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"ที่อาบน้ำฝักบัว"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"ห้องอาบน้ำ"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"อ่างอาบน้ำ"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"จุดตรวจหนังสือเดินทาง"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"ศุลกากร"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"จุดรับกระเป๋า"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"จุดวางกระเป๋า"</string>
+</resources>
diff --git a/java/res/values-th/strings-talkback-descriptions.xml b/java/res/values-th/strings-talkback-descriptions.xml
index 5d70d71..f570911 100644
--- a/java/res/values-th/strings-talkback-descriptions.xml
+++ b/java/res/values-th/strings-talkback-descriptions.xml
@@ -25,13 +25,14 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"ไม่มีข้อความ"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> แก้ไข <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> เป็น <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> ทำการแก้ไขอัตโนมัติ"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"ไม่มีคำแนะนำ"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"อักขระที่ไม่รู้จัก"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"สัญลักษณ์เพิ่มเติม"</string>
     <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Shift"</string>
     <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"สัญลักษณ์"</string>
     <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Shift"</string>
-    <string name="spoken_description_delete" msgid="3878902286264983302">"นำออก"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"ลบ"</string>
     <string name="spoken_description_to_symbol" msgid="8244903740201126590">"สัญลักษณ์"</string>
     <string name="spoken_description_to_alpha" msgid="4081215210530031950">"ตัวอักษร"</string>
     <string name="spoken_description_to_numeric" msgid="4560261331530795682">"หมายเลข"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I ตัวใหญ่เติมจุดด้านบน"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"สัญลักษณ์ที่ไม่รู้จัก"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"อีโมจิที่ไม่รู้จัก"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"หน้าเบื่อ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"หน้าอาย"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"หน้าสวมแว่นกันแดด"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"หน้าประหลาดใจ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"หน้าทำปากจูบ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"หน้ามุ่ย"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"อักขระทางเลือกพร้อมใช้งาน"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"ปิดอักขระทางเลือกแล้ว"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"ข้อเสนอแนะทางเลือกพร้อมใช้งาน"</string>
diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml
index 43391a5..2dc653a 100644
--- a/java/res/values-th/strings.xml
+++ b/java/res/values-th/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"สั่นเมื่อกดปุ่ม"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"ส่งเสียงเมื่อกดปุ่ม"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"ป๊อปอัปเมื่อกดแป้น"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ค่ากำหนด"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"บัญชีและความเป็นส่วนตัว"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"ลักษณะที่ปรากฏและการจัดวาง"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"การป้อนข้อมูลด้วยท่าทาง"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"การแก้ไขข้อความ"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"ขั้นสูง"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"ธีม"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"เปิดใช้แป้นพิมพ์แยก"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"การซิงค์แป้นพิมพ์ของ Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"การซิงค์เปิดอยู่"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"ซิงค์พจนานุกรมส่วนตัวในอุปกรณ์ต่างๆ"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ซิงค์เลย"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"ลบข้อมูลระบบคลาวด์"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"ลบข้อมูลที่ซิงค์ออกจาก Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"ข้อมูลที่ซิงค์จะลบออกจากระบบคลาวด์ คุณแน่ใจไหม"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"ลบ"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"ยกเลิก"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"พจนานุกรมส่วนตัวของคุณจะซิงค์และสำรองข้อมูลไปยังเซิร์ฟเวอร์ Google ข้อมูลเชิงสถิติของความถี่ในการใช้คำอาจได้รับการเก็บรวบรวมเพื่อใช้ปรับปรุงผลิตภัณฑ์ของเรา การเก็บรวบรวมและการใช้งานข้อมูลทั้งหมดจะเป็นไปอย่างสอดคล้องกับ"<a href="https://www.google.com/policies/privacy">"นโยบายส่วนบุคคลของ Google"</a></string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"โปรดเพิ่มบัญชี Google ไปยังอุปกรณ์นี้เพื่อเปิดใช้คุณลักษณะนี้"</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">"แป้นสลับภาษาครอบคลุมวิธีการป้อนข้อมูลอื่นๆ ด้วย"</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">"แสดงสัญลักษณ์การเลื่อน"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"แสดงสัญลักษณ์ภาพขณะเลื่อนจากแป้น Shift หรือแป้นสัญลักษณ์"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"แป้นการป้อนข้อมูลด้วยเสียง"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"ไม่ได้เปิดใช้วิธีการป้อนข้อมูลด้วยเสียง ตรวจสอบภาษาและการตั้งค่าการป้อนข้อมูล"</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="language_selection_title" msgid="3666971864764478269">"ภาษา"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"ความช่วยเหลือและความคิดเห็น"</string>
+    <string name="select_language" msgid="5709487854987078367">"ภาษา"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"แตะอีกครั้งเพื่อบัน​​ทึก"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"แตะที่นี่เพื่อบันทึก"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"ชุดรูปแบบแป้นพิมพ์"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"สลับบัญชี"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"ไม่ได้เลือกบัญชี"</string>
+    <string name="account_selected" msgid="2846876462199625974">"ปัจจุบันใช้ <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ตกลง"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"ยกเลิก"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"ออกจากระบบ"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"เลือกบัญชีที่จะใช้"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"อังกฤษ (สหราชอาณาจักร)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"อังกฤษ (อเมริกัน)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"สเปน (สหรัฐอเมริกา)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ภาษาอังกฤษผสมกับฮินดู"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"เซอร์เบีย (ละติน)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"อังกฤษ (สหราชอาณาจักร) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"อังกฤษ (สหรัฐอเมริกา) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"สเปน (สหรัฐอเมริกา) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ภาษาอังกฤษผสมกับฮินดู (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"เซอร์เบีย (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ดั้งเดิม)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ซีริลลิก)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ละติน)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (แบบกะทัดรัด)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"ไม่มีภาษา (ตัวอักษรละติน)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"ตัวอักษร (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"ตัวอักษร (QWERTZ)"</string>
@@ -108,20 +121,11 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"ตัวอักษร (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"ตัวอักษร (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"อีโมจิ"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"ธีมแป้นพิมพ์"</string>
     <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="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>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"ต้องการติดตั้งไฟล์นี้สำหรับ <xliff:g id="LANGUAGE_NAME">%s</xliff:g> จริงหรือ"</string>
-    <string name="error" msgid="8940763624668513648">"เกิดข้อผิดพลาด"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"การหน่วงเวลาของการกดแป้นค้าง"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"ตอนนี้คุณสามารถพิมพ์ข้อมูลลงในแอปที่ชื่นชอบทั้งหมดด้วย <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">"แสดงไอคอนแอปพลิเคชันในตัวเรียกใช้งาน"</string>
     <string name="app_name" msgid="6320102637491234792">"ผู้ให้บริการพจนานุกรม"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"ผู้ให้บริการพจนานุกรม"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"บริการพจนานุกรม"</string>
@@ -180,8 +177,8 @@
     <string name="go_to_settings" msgid="3876892339342569259">"การตั้งค่า"</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="1583881200688185508">"ภาษาที่คุณเลือกในอุปกรณ์เคลื่อนที่มีพจนานุกรมที่สามารถใช้ได้&lt;br/&gt; เราขอแนะนำให้คุณ &lt;b&gt;ดาวน์โหลด&lt;/b&gt; พจนานุกรม <xliff:g id="LANGUAGE_NAME">%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="delete_dict" msgid="756853268088330054">"ลบ"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"ภาษาที่คุณเลือกในอุปกรณ์เคลื่อนที่มีพจนานุกรมที่สามารถใช้ได้&lt;br/&gt; เราขอแนะนำให้คุณ &lt;b&gt;ดาวน์โหลด&lt;/b&gt; พจนานุกรม <xliff:g id="LANGUAGE_NAME">%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>MB)"</string>
     <string name="do_not_download_over_metered" msgid="2176209579313941583">"ดาวน์โหลดผ่าน WiFi"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"มีพจนานุกรมให้ใช้งานสำหรับ <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
@@ -201,10 +198,10 @@
     <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"ทางลัดที่ไม่บังคับ"</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_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_settings_delete" msgid="110413335187193859">"ลบ"</string>
     <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
 </resources>
diff --git a/java/res/values-tl/strings-emoji-descriptions.xml b/java/res/values-tl/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..68f2c5d
--- /dev/null
+++ b/java/res/values-tl/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Simbolo ng copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Nakarehistrong simbolo"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Dobleng tandang padamdam"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Tandang padamdam at tandang pananong"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Simbolo ng trade mark"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Mapagkukunan ng impormasyon"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Arrow na pakaliwa at pakanan"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Arrow na pataas at pababa"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Arrow na nakaturo sa hilagang-kanluran"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Arrow na nakaturo sa hilagang-silangan"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Arrow na nakaturo sa timog-silangan"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Arrow na nakaturo sa timog-kanluran"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Pakaliwang arrow na may hook"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Pakanang arrow na may hook"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Relo"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Hourglass"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Itim na dobleng tatsulok na nakaturo pakanan"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Itim na dobleng tatsulok na nakaturo pakaliwa"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Itim na dobleng tatsulok na nakaturo pataas"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Itim na dobleng tatsulok na nakaturo pababa"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Alarm clock"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Hourglass na may dumadaloy na buhangin"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Malaking latin na titik m na nasa bilog"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Itim at maliit na parisukat"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Puti at maliit na parisukat"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Itim na tatsulok na nakaturo pakanan"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Itim na tatsulok na nakaturo pakaliwa"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Puti at katamtamang parisukat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Itim at katamtamang parisukat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Puting parisukat na may maliit na parisukat sa loob"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Itim na parisukat na may maliit na parisukat sa loob"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Itim na araw na may mga sinag"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Ulap"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Itim na telepono"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Ballot box na may check"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Payong na may mga patak ng ulan"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Mainit na inumin"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Puting hintuturo na nakaturo pataas"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Puti at nakangiting mukha"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Taurus"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Gemini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Scorpius"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Sagittarius"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Aquarius"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Pisces"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Itim na spade suit"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Itim na club suit"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Itim na heart suit"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Itim na diamond suit"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Mga hot spring"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Itim na simbolo ng universal recycling"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Simbolo ng wheelchair"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Angkla"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Simbolo ng babala"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Simbolo ng mataas na boltahe"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Katamtaman at puting bilog"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Katamtaman at itim na bilog"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Soccer ball"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Snowman na walang snow"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Araw sa likod ng ulap"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Bawal pumasok"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Simbahan"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fountain"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Bandila sa butas"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Sailboat"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Tent"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Fuel pump"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Itim na gunting"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Puti at makapal na check mark"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Eroplano"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Sobre"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Nakataas na kamao"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Nakataas na kamay"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Kamay na sumisimbolo ng panalo"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Lapis"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Itim na nib"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Makapal na check mark"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Makapal na multiplication x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Mga Sparkle"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Asterisk na may walong spoke"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Itim na bituin na may walong punto"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Snowflake"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Sparkle"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Markang krus"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Negatibong marka ng krus na nasa parisukat"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Ornament na itim na tandang pananong"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Ornament na puting tandang pananong"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Ornament na puting tandang padamdam"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Makapal na simbolo ng tandang padamdam"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Makapal at itim na puso"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Makapal na simbolo ng plus"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Makapal na simbolo ng minus"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Makapal na simbolo ng division"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Itim at pakanang arrow"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Curly loop"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Dobleng curly loop"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Arrow na tumuturo pakanan pagkatapos ay kumukurba pataaas"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Arrow na tumuturo pakanan pagkatapos ay kumukurba pababa"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Pakaliwa at itim na arrow"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Pataas at itim na arrow"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Pababa at itim na arrow"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Itim at malaking parisukat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Puti at malaking parisukat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Puti at katamtamang bituin"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Makapal at malaking bilog"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Wavy dash"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Part alternation mark"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ideograph ng pagbati na nasa bilog"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ideograph ng lihim na nasa bilog"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Pulang dragon sa tile ng mahjong"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Itim na joker sa baraha"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Blood type A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Blood type B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Blood type O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Paradahan"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Blood type AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"CL na nasa parisukat"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Cool na nasa parisukat"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Free na nasa parisukat"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"ID na nasa parisukat"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"New na nasa parisukat"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"N G na nasa parisukat"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"OK na nasa parisukat"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"SOS na nasa parisukat"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Up na may tandang padamdam na nasa parisukat"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"vs na nasa parisukat"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Katakana ng dito na nasa parisukat"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Katakana ng serbisyo na nasa parisukat"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ideograph ng walang singil na nasa parisukat"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ideograph ng nakareserbang upuan na nasa parisukat"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ideograph ng pagbabawal na nasa parisukat"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ideograph ng bakante na nasa parisukat"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ideograph ng pagtanggap na nasa parisukat"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Nasa parisukat na ideograph ng puno na"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Nasa parisukat na ideograph ng bayad na"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ideograph ng buwan-buwan na nasa parisukat"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ideograph ng application na nasa parisukat"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ideograph ng diskwento na nasa parisukat"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ideograph ng bukas ang negosyo na nasa parisukat"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ideograph ng bentahe na nasa bilog"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ideograph ng tanggapin na nasa bilog"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Bagyo"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Mahamog"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Nakasarang payong"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Gabi na may mga bituin"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Pagsikat ng araw sa mga bundok"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Pagsikat ng araw"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Lungsod sa dapit-hapon"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Paglubog ng araw sa mga gusali"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Bahaghari"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Tulay sa gabi"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Alon ng tubig"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Bulkan"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Milky way"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Europe-africa sa globo ng mundo"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Americas sa globo ng mundo"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Asia-australia sa globo ng mundo"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Globo na may mga meridian"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Simbolo ng new moon"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Simbolo ng waxing crescent moon"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Simbolo ng first quarter moon"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Simbolo ng waxing gibbous moon"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Simbolo ng full moon"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Simbolo ng waning gibbous moon"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Simbolo ng last quarter moon"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Simbolo ng waning crescent moon"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Crescent moon"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"New moon na may mukha"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"First quarter moon na may mukha"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Last quarter moon na may mukha"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Full moon na may mukha"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Araw na may mukha"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Nagniningning na bituin"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Bulalakaw"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kastanyas"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Punla"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Evergreen tree"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Deciduous tree"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palm tree"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cactus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Cherry blossom"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Rosas"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Gumamela"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Sunflower"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Blossom"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Mais"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Bigas"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Herb"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Four leaf clover"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Dahon ng maple"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Nalaglag na dahon"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Dahong tinatangay ng hangin"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Kabute"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Kamatis"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Ubas"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Melon"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Pakwan"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Tangerine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Lemon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Saging"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Pinya"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Pulang mansanas"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Berdeng mansanas"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Peras"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Peach"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Mga Cherry"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Strawberry"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Slice ng pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Laman sa buto"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Paa ng manok"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Rice cracker"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Rice ball"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Kanin"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Curry at kanin"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Umuusok na mangkok"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Tinapay"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"French fries"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Inihaw na kamote"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Pritong hipon"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Fish cake na may swirl na disenyo"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Soft ice cream"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Kinaskas na yelo"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Ice cream"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Doughnut"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Cookie"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Chocolate bar"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Candy"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Custard"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Honey pot"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Shortcake"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Bento box"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Kaldero ng pagkain"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Pagluluto"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Tinidor at kutsilyo"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tasa na walang hawakan"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Bote at tasa ng sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Wine glass"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cocktail glass"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropical drink"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Beer mug"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Pinagtunggang beer mug"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Baby bottle"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Ribbon"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Nakabalot ng regalo"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Birthday cake"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Jack-o-lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Christmas tree"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Father christmas"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Mga Paputok"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Lusis"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Lobo"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Party popper"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Confetti ball"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata tree"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Magkakrus na bandila"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Dekorasyong pine"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Mga Japanese doll"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Carp streamer"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Wind chime"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Seremonya ng pagtingin sa buwan"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"School satchel"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Graduation cap"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Carousel horse"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Ferris wheel"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Roller coaster"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Bingwit at isda"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikropono"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Movie camera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Cinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Headphone"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Artist palette"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Top hat"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Circus tent"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ticket"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Clapper board"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Performing arts"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video game"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Asintadong tira"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Slot machine"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Bilyar"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Game die"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Mga barahang may bulaklak"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nota ng musika"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Maraming nota ng musika"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Musical keyboard"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trumpeta"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Violin"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Musical score"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Running shirt na may sash"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Raketa at bola ng tennis"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ski at ski boot"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketball at hoop"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Chequered na bandila"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snowboarder"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Runner"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Surfer"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Trophy"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Karera ng kabayo"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"American football"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Rugby football"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Swimmer"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Pagtatayo ng bahay"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Bahay na may hardin"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Gusali ng opisina"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Post office sa Japan"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Post office sa Europe"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Ospital"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bangko"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Automated teller machine"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Hotel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Love hotel"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Convenience store"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Paaralan"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Department store"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Pabrika"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya lantern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japanese castle"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"European castle"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Daga"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Daga"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Ox"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Kalabaw"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Baka"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Kuneho"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Pusa"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Dragon"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Buwaya"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balyena"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Kuhol"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Ahas"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Kabayo"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Ram"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Kambing"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Tupa"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Unggoy"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Tandang"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Manok"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Aso"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Baboy"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Baboy-ramo"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Elepante"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Pugita"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiral shell"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Salaginto"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Langgam"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Bubuyog"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Salagubang"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Isda"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropical na isda"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Blowfish"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Pagong"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Napisang sisiw"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Maliit na sisiw"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Maliit na sisiw na nakaharap"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Ibon"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Penguin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Poodle"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Dromedary camel"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Bactrian camel"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Dolphin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mukha ng daga"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Mukha ng baka"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Mukha ng tigre"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Mukha ng kuneho"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Mukha ng pusa"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Mukha ng dragon"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Bumubugang balyena"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Mukha ng kabayo"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Mukha ng unggoy"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Mukha ng aso"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Mukha ng baboy"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Mukha ng palaka"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Mukha ng hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Mukha ng lobo"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Mukha ng oso"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Mukha ng panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Ilong ng baboy"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Mga bakas ng paa ng hayop"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Mga Mata"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Tainga"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Ilong"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Bibig"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Dila"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Puting hintuturo na nakaturo pataas"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Puting hintuturo na nakaturo pababa"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Puting hintuturo na nakaturo pakaliwa"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Puting hintuturo na nakaturo pakanan"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Simbolo ng kamao"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Simbolo ng kumakaway na kamay"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Simbolo ng kamay na Ok"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Simbolo ng thumbs up"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Simbolo ng thumbs down"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Simbolo ng pumapalakpak na kamay"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Simbolo ng bukas na kamay"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Korona"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Sumbrero ng babae"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Salamin sa mata"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kurbata"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T-shirt"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jeans"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Bestida"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Damit na pambabae"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Purse"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Handbag"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Pouch"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Sapatos na panlalaki"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Sapatos na pang-atleta"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Sapatos na mataas ang takong"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Sandal na pambabae"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Boots na pambabae"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Bakas ng paa"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Anino ng tao"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Mga anino ng tao"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Batang Lalaki"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Batang Babae"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Lalaki"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Babae"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Pamilya"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Lalaki at babae na magkahawak ang kamay"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Dalawang lalaki na magkahawak ang kamay"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Dalawang babae na magkahawak ang kamay"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Pulis"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Babaeng may bunny ears"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Ikakasal na babaeng may belo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Taong may blond na buhok"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Lalaking may gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Lalaking may turban"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Matandang lalaki"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Matandang babae"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Sanggol"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Construction worker"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prinsesa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japanese ogre"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japanese goblin"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Multo"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Anghel na sanggol"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Extraterrestrial alien"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Alien na halimaw"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Imp"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Bungo"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Tauhan sa information desk"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Guwardiya"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Mananayaw"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lipstick"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Nail polish"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Face massage"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Gupit"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Barber pole"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Iniksyon"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Pill"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Kiss mark"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Love letter"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Sing-sing"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Hiyas"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Halik"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bouquet"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Magkasintahang may puso"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Kasal"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Tumitibok na puso"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Biyak na puso"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Dalawang puso"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Nagniningning na puso"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Lumalaking puso"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Puso na may palaso"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Asul na puso"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Berdeng puso"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Dilaw na puso"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Purple na puso"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Pusong may ribbon"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Mga umiikot na puso"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Dekorasyong puso"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Hugis diamante na may tuldok sa loob"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Electric light bulb"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Simbolo ng galit"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Simbolo ng pagtulog"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Simbolo ng banggaan"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Simbolo ng tumataksik na pawis"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Patak"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Simbolong gitling"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Dumi"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Naka-flex na braso"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Simbolo ng nahihilo"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Speech balloon"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Balloon ng iniisip"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Puting bulaklak"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Simbolo ng isandaang puntos"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Money bag"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Palitan ng currency"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Makapal na simbolo ng dolyar"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Credit card"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Pera na may simbolo ng yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Pera na may simbolo ng dolyar"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Pera na may simbolo ng euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Pera na may simbolo ng pound"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Pera na may mga pakpak"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Chart na may pataas na trend at simbolo ng yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Upuan"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Personal computer"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Briefcase"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Minidisc"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Floppy disk"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optical disc"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Folder ng file"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Nakabukas na folder ng file"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Page na may curl"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Page na nakaharap"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Kalendaryo"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Tear-off na kalendaryo"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Index ng card"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Chart na may pataas na trend"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Chart na may pababang trend"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Bar chart"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Clipboard"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Pushpin"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Round pushpin"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Paperclip"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Straight ruler"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Triangular ruler"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Mga tab ng bookmark"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ledger"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Kwaderno"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Kwadernong may dekorasyon ang pabalat"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Nakasarang aklat"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Nakabukas na aklat"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Berdeng aklat"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Asul na aklat"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Orange na aklat"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Mga Aklat"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Badge ng pangalan"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Scroll"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Memo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Receiver ng telepono"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Pager"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Fax machine"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Satellite antenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Public address loudspeaker"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Cheering megaphone"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Outbox tray"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Inbox tray"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Package"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Simbolo ng e-mail"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Papasok na sobre"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Sobre na may pababang arrow sa itaas"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Nakasarang mailbox na may nakaababang flag"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Nakasarang mailbox na may nakataas na flag"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Nakabukas na mailbox na may nakataas na flag"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Nakabukas na mailbox na may nakababang flag"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Postbox"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Postal horn"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Pahayagan"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobile phone"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobile phone na may pakanang arrow sa kaliwa"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Vibration mode"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"I-off ang mobile phone"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Walang mga mobile phone"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Antenna na may mga bar"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Camera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Video camera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Telebisyon"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radyo"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Mga naka-twist na pakanang arrow"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Mga pakanan at pakaliwang arrow sa pakanang oryentasyon na bumubuo ng bilog"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Mga pakanan at pakaliwang arrow sa pakanang oryentasyon na bumubuo ng bilog na may overlay na numerong isa na nasa bilog"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Mga pababa at pataas na arrow sa pakanang oryentasyon na bumubuo ng bilog"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Mga pababa at pataas na arrow sa pakaliwang oryentasyon na bumubuo ng bilog"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Simbolo ng mababang brightness"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Simbolo ng mataas na brightness"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Speaker na may stroke ng pagkansela"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Speaker"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Speaker na may isang sound wave"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Speaker na may tatlong sound wave"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Baterya"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Electric plug"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Magnifying glass na nakaturo pakaliwa"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Magnifying glass na nakaturo pakanan"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Lock na may ink pen"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Nakasarang lock na may susi"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Susi"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Lock"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Nakabukas na lock"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Bell"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Bell na may stroke ng pagkansela"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Bookmark"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Simbolo ng link"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radio button"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Back na may pakaliwang arrow sa itaas"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"End na may pakaliwang arrow sa itaas"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"On na may tandang padamdam na may pakaliwa at pakanang arrow sa itaas"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Soon na may pakanang arrow sa itaas"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Top na may pataas na arrow sa itaas"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Simbolo ng walang mas bata sa labinwalong taong gulang"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Keycap ten"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Simbolo ng pag-input para sa malalaking latin na titik"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Simbolo ng pag-input para sa maliliit na latin na titik"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Simbolo ng pag-input para sa mga numero"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simbolo ng pag-input para sa mga simbolo"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Simbolo ng pag-input para sa mga latin na titik"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Apoy"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Electric torch"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Wrench"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Martilyo"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Nut at bolt"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Baril"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Microscope"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Telescope"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Crystal ball"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Bituing may anim na punto na may tuldok sa gitna"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Japanese na simbolo para sa baguhan"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Emblem ng trident"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Button na itim na parisukat"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Button na puting parisukat"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Malaking pulang bilog"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Malaking asul na bilog"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Malaking orange na diamante"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Malaking asul na diamante"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Maliit na orange na diamante"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Maliit na asul na diamante"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Pulang tatsulok na nakaturo pataas"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Pulang tatsulok na nakaturo pababa"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Maliit na pulang tatsulok na nakaturo pataas"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Maliit na pulang tatsulok na nakaturo pababa"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Ala una sa orasan"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Alas dos sa orasan"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Alas tres sa orasan"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Alas kuwatro sa orasan"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Alas singko sa orasan"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Alas sais sa orasan"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Alas kuwatro sa orasan"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Alas otso sa orasan"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Alas nuwebe sa orasan"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Alas diyes sa orasan"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Alas onse sa orasan"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Alas dose sa orasan"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Ala una y medya sa orasan"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Alas dos y medya sa orasan"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Alas tres y medya sa orasan"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Alas kuwatro y medya sa orasan"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Alas singko y medya sa orasan"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Alas sais y medya sa orasan"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Alas siyete y medya sa orasan"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Alas otso y medya sa orasan"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Alas nuwebe y medya sa orasan"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Alas diyes y medya sa orasan"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Alas onse y medya sa orasan"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Alas dose y medya sa orasan"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Mount fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo tower"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Statue of liberty"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Anino ng japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Nakangising mukha"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Nakangising mukha na may masasayang mata"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Mukha na may mga luha ng kasiyahan"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Nakangiting mukha na may nakabukas na bibig"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Nakangiting mukha na may nakabukas na bibig at masasayang mata"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Nakangiting mukha na may nakabukas na bibig at malamig na pawis"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Nakangiting mukha na may nakabukas na bibig at mga nakapikit na mata"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Nakangiting mukha na may halo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Nakangiting mukha na may mga sungay"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Kumikindat na mukha"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Nakangiting mukha na may masasayang mata"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Mukha na numanamnam ng masarap na pagkain"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Guminhawang mukha"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Nakangiting mukha na may mga matang hugis-puso"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Nakangiting mukha na may salamin"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Nakangising mukha"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Mukha na walang emosyon"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Mukha na walang emosyon"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Mukha na hindi natutuwa"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Mukha na may malamig na pawis"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Nag-iisip na mukha"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Nalilitong mukha"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Naguguluhang mukha"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Humahalik na mukha"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Mukha na humahalik"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Humahalik na mukha na may masasayang mata"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Humahalik na mukha na may mga nakapikit na mata"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Mukha na nakadila"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Mukha na nakadila at kumikindat"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Mukha na nakadila at nakapikit ang mga mata"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Nabigong mukha"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Nag-aalalang mukha"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Nagagalit na mukha"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Naghihimutok na mukha"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Umiiyak na mukha"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Nagsisikap na mukha"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Mukha ng nagtagumpay"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Nabigo ngunit guminhawang mukha"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Nakasimangot na mukha na may nakabukas na bibig"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Nasasaktang mukha"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Natatakot na mukha"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Pagod na mukha"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Inaantok na mukha"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Pagod na mukha"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Nakangiwing mukha"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Mukha na umiiyak nang todo"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Mukha na may nakabukas na bibig"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Naghihintay na mukha"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Mukha na may nakabukas na bibig at malamig na pawis"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Mukha na sumisigaw sa takot"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Nagulat na mukha"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Nahihiyang mukha"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Natutulog na mukha"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Nahihilong mukha"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Mukha na walang bibig"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Mukha na may medical mask"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Nakangising mukha ng pusa na may masasayang mata"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Mukha ng pusa na may mga luha ng kasiyahan"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Nakangiting mukha ng pusa na may nakabukas na bibig"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Nakangiting mukha ng pusa na may mga mata na hugis-puso"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Mukha ng pusa na nakangiti"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Humahalik na mukha ng pusa na may mga nakapikit na mata"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Naghihimutok na mukha ng pusa"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Umiiyak na mukha ng pusa"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Pagod na mukha ng pusa"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Mukha na sumesenyas na hindi pwede"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Mukha na sumesenyas na ok"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Taong yumuyuko nang todo"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Unggoy na ayaw makakita ng masamang bagay"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Unggoy na ayaw makarinig ng masamang bagay"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Unggoy na ayaw magsabi ng masamang bagay"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Masayang tao na nagtataas ng isang kamay"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Taong nagtataas ng dalawang kamay bilang selebrasyon"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Nakasimangot na tao"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Naghihimutok na tao"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Tao na nakatiklop ang mga kamay"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Rocket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helicopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Steam locomotive"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Railway car"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"High-speed na tren"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"High-speed na tren na may bullet nose"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Light rail"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Istasyon"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tram"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tram car"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Bus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Paparating na bus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleybus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Sakayan ng bus"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Ambulansya"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Fire engine"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Sasakyan ng pulis"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Paparating na sasakyan ng pulis"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Paparating na taxi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Sasakyan"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Paparating na sasakyan"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Recreational vehicle"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Delivery truck"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Articulated lorry"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktora"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Monorail"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Mountain railway"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Suspension railway"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Mountain cableway"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Aerial tramway"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Barko"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Bangka"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Speedboat"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Pahalang na ilaw-trapiko"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Patayong ilaw-trapiko"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Simbolo ng konstruksyon"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Umiikot na ilaw ng mga sasakyan ng pulis"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Tatsulok na bandila sa poste"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Pinto"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Simbolong bawal pumasok"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Simbolo ng pwedeng manigarilyo"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Simbolo ng bawal manigarilyo"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Simbolo ng itapon ang basura sa tamang lugar"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Simbolo ng huwag magkalat"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Simbolo ng naiinom na tubig"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Simbolo ng hindi naiinom na tubig"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bisikleta"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Bawal ang mga bisikleta"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Nagbibisikleta"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Mountain bicyclist"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Tumatawid"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Bawal tumawid"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Tawiran ng mga bata"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Simbolo ng mga lalaki"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Simbolo ng mga babae"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Restroom"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Simbolo ng sanggol"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Palikuran"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Inodoro"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Shower"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Paliguan"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bathtub"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kailangan ng pasaporte"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Customs"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Kuhaan ng bagahe"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Naiwang bagahe"</string>
+</resources>
diff --git a/java/res/values-tl/strings-talkback-descriptions.xml b/java/res/values-tl/strings-talkback-descriptions.xml
index f601ad4..1d06d20 100644
--- a/java/res/values-tl/strings-talkback-descriptions.xml
+++ b/java/res/values-tl/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Walang tekstong inilagay"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"Itinatama ng <xliff:g id="KEY_NAME">%1$s</xliff:g> ang <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> sa <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"Nagsasagawa ang <xliff:g id="KEY_NAME">%1$s</xliff:g> ng auto-correction"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Walang suhestyon"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Hindi alam na character"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Marami pang simbolo"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Capital I, tuldok sa itaas"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Hindi alam na simbolo"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Hindi alam na emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Tinatamad na mukha"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Nahihiya na mukha"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Mukha na nakasuot ng salamin"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Nagulat na mukha"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Humahalik na mukha"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Nakasimangot na mukha"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Available ang mga alternatibong character"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Dini-dismiss ang mga alternatibong character"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Available ang mga alternatibong suhestyon"</string>
diff --git a/java/res/values-tl/strings.xml b/java/res/values-tl/strings.xml
index 8282678..0f8f785 100644
--- a/java/res/values-tl/strings.xml
+++ b/java/res/values-tl/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Mag-vibrate sa keypress"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Tumunog sa keypress"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Mag-popup sa keypress"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Mga Kagustuhan"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Mga Account &amp; Privacy"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Hitsura &amp; Mga Layout"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Pagta-type Gamit ang Galaw"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Pagwawasto ng text"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Advanced"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"I-enable ang split keyboard"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Pag-sync ng Google Keyboard"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Naka-on ang pag-sync"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"I-sync ang iyong personal na diksyunaryo sa mga device"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"I-sync ngayon"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"I-delete ang cloud data"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Dine-delete ang iyong naka-sync na data sa Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Ide-delete sa cloud ang iyong na-sync na data. Sigurado ka ba?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"I-delete"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Kanselahin"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Masi-sync at maba-back up ang iyong personal na dictionary sa mga server ng Google. Maaaring kolektahin ang istatistikal na impormasyon ng dalas ng salita upang makatulong na pahusayin ang aming mga produkto. Susunod ang pagkolekta at paggamit ng lahat ng impormasyon sa "<a href="https://www.google.com/policies/privacy">"Patakaran sa Privacy ng Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Mangyaring magdagdag ng Google account sa device na ito upang i-enable ang feature na ito"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Lipat iba paraan ng input"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Saklaw din ng key ng pagpalit ng wika ang ibang paraan ng input"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Key ng panlipat ng wika"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Ipakita kapag maraming wika ng input na pinagana"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Ipakita ang indicator ng slide"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Magpakita ng visual cue kapag nag-i-slide sa Shift o Symbol key"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Balewala antala key popup"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Walang antala"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Pangunahing diksyunaryo"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Magpakita ng mga suhestiyon ng pagwawasto"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Ipakita ang mga iminumungkahing salita habang nagta-type"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Palaging ipakita"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Ipakita sa portrait na mode"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Palaging itago"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"I-block nakakapanakit na salita"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Huwag magmungkahi ng mga maaaring nakakapanakit na salita"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Awtomatiko pagwasto"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Voice input key"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Walang naka-enable na pamamaraan ng pag-input ng boses. Suriin ang mga setting ng Pag-input ng wika."</string>
     <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Magpadala ng feedback"</string>
-    <string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Mga Wika"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Tulong at feedback"</string>
+    <string name="select_language" msgid="5709487854987078367">"Mga Wika"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pinduting muli upang i-save"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Pumindot dito upang mag-save"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Tema ng keyboard"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Lumipat ng account"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Walang mga account na pinili"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Kasalukuyang ginagamit ang <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Kanselahin"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Mag-sign out"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Pumili ng account na gagamitin"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Ingles (UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Ingles (Estados Unidos)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serbian (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingles (UK) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingles (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Traditional)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Cyrillic)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Compact)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Walang wika (Alpabeto)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alpabeto (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alpabeto (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alpabeto (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alpabeto (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Tema ng keyboard"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Custom style ng input"</string>
     <string name="add_style" msgid="6163126614514489951">"Dagdag style"</string>
     <string name="add" msgid="8299699805688017798">"Idagdag"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Paganahin"</string>
     <string name="not_now" msgid="6172462888202790482">"Hindi ngayon"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Umiiral na ang parehong estilo ng input: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Tagal ng vibration ng keypress"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Volume ng tunog ng keypress"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Magbasa ng panlabas na file ng diksyunaryo"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Walang mga file ng diksyunaryo sa folder na Mga Download"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Pumili ng file ng diksyunaryo na ii-install"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Talagang ii-install ang file na ito para sa <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Nagkaroon ng error"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Key long press delay"</string>
     <string name="button_default" msgid="3988017840431881491">"Default"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Maligayang pagdating sa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"gamit ang Gesture na Pag-type"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Ngayon, mata-type mo na ang lahat ng paborito mong apps gamit ang <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Mag-configure ng mga karagdagang wika"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Tapos na"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Ipakita ang icon ng app"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Ipakita ang icon ng application sa launcher"</string>
     <string name="app_name" msgid="6320102637491234792">"Provider ng Diksyunaryo"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Provider ng Diksyunaryo"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Serbisyo ng Diksyunaryo"</string>
diff --git a/java/res/values-tr/strings-emoji-descriptions.xml b/java/res/values-tr/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..58a43ac
--- /dev/null
+++ b/java/res/values-tr/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Telif hakkı işareti"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Tescil işareti"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Çift ünlem işareti"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Ünlemli soru işareti"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Ticari marka işareti"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Bilgi kaynağı"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Sol ve sağ ok"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Yukarı ve aşağı ok"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Kuzey batı oku"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Kuzey doğu oku"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Güney doğu oku"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Güney batı oku"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Kancalı sol ok"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Kancalı sağ ok"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Kol saati"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Kum saati"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Sağa bakan siyah çift üçgen"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Sola bakan siyah çift üçgen"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Yukarı bakan siyah çift üçgen"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Aşağı bakan siyah çift üçgen"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Çalar saat"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Kumu akan kum saati"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Daire içinde büyük M harfi"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Küçük siyah kare"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Beyaz küçük kare"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Sağa bakan siyah üçgen"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Sola bakan siyah üçgen"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Beyaz orta boy kare"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Siyah orta boy kare"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Beyaz orta boy küçük kare"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Siyah orta boy küçük kare"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Parlayan siyah güneş"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Bulut"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Siyah telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Onay işaretli kutu"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Yağmur damlaları ve şemsiye"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Sıcak içecek"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Yukarı işaret eden beyaz işaret parmağı"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Beyaz gülen yüz"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Koç"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Boğa"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"İkizler"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Yengeç"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Aslan"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Başak"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Terazi"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Akrep"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Yay"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Oğlak"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Kova"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Balık"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Siyah maça"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Siyah sinek"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Siyah kupa"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Siyah karo"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Sıcak kaynak"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Siyah genel geri dönüşüm simgesi"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Tekerlekli sandalye simgesi"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Çapa"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Dikkat işareti"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Yüksek voltaj işareti"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Orta boy beyaz daire"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Orta boy siyah daire"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futbol topu"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beyzbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Karsız kardan adam"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Bulutun arkasında güneş"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Yılancı"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Girilmez"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Kilise"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Fıskiye"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Delikteki bayrak"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Yelkenli"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Çadır"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Yakıt pompası"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Siyah makas"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Büyük beyaz onay işareti"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Uçak"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Zarf"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Havadaki yumruk"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Havadaki el"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Zafer işareti"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Kalem"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Siyah kelam ucu"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Büyük onay işareti"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Büyük çarpı işareti"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Pırıltılar"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Sekizli yıldız"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Sekizli siyah yıldız"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Kar tanesi"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Parıltı"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Çarpı işareti"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Siyah kare içinde beyaz çarpı işareti"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Siyah dekoratif soru işareti"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Beyaz dekoratif soru işareti"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Beyaz dekoratif ünlem işareti"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Büyük ünlem işareti"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Ağır kara yürek"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Büyük artı işareti"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Büyük eksi işareti"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Büyük bölme işareti"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Siyah sağ ok"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Kıvrımlı döngü"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Çift kıvrımlı döngü"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Sağa ve ardından yukarı giden ok"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Sağa ve ardından aşağı giden ok"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Siyah sol ok"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Siyah yukarı ok"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Siyah aşağı ok"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Siyah büyük kare"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Beyaz büyük kare"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Beyaz orta boy yıldız"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Büyük daire"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Dalga işareti"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Sırayı belirten işaret"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Daire içinde tebrik işareti"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Daire içinde gizli işareti"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Mahjong taşı kızıl ejderha"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"İskambil kartı siyah joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Kan grubu A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Kan grubu B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Kan grubu O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Park yeri"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Kan grubu AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Kare içinde CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Kare içinde havalı"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Kare içinde özgür"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Kare içinde kimlik"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Kare içinde yeni"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Kare içinde NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Kare içinde OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Kare içinde SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Kare içinde ünlem ile birlikte yukarı işareti"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Kare içinde vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Kare içinde katakana burada"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Kare içinde katakana hizmet"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Kare içinde ücretsiz işareti"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Kare içinde ayrılmış koltuk işareti"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Kare içinde yasak işareti"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Kare içinde boş işareti"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Kare içinde kabul işareti"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Kare içinde dolu işareti"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Kare içinde ödendi işareti"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Kare içinde aylık işareti"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Kare içinde uygulama işareti"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Kare içinde indirim işareti"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Kare içinde çalışıyor işareti"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Daire içinde avantaj işareti"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Daire içinde kabul işareti"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Siklon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Sisli"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Kapalı şemsiye"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Yıldızlı gece"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Dağların üzerinden gün doğuşu"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Gün doğuşu"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Akşam üstü şehir manzarası"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Binaların üzerinden gün batışı"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Gökkuşağı"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Gece vakti köprü"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Su dalgası"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Yanardağ"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Samanyolu"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Dünya avrupa-afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Dünya amerika kıtası"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Dünya asya-avustralya"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Dünya boylamlar"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Hilal simgesi"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Hilalden sonraki evrede ay simgesi"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"İlk dördün ay simgesi"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Şişkin ay simgesi"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Dolunay simgesi"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Küçülen ay simgesi"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Son dördün ay simgesi"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Küçülen hilal simgesi"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Hilal"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Yüzü olan yani ay"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Yüzü olan ilk dördün ay"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Yüzü olan son dördün ay"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Yüzü olan dolunay"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Yüzü olan güneş"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Parlayan yıldız"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Kayan yıldız"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kestane"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Fide"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Yaprak dökmeyen ağaç"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Yaprak döken ağaç"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palmiye ağacı"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktüs"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Lale"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Kiraz çiçeği"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Gül"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Amber çiçeği"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Ayçiçeği"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Ağaç çiçeği"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Mısır başağı"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Pirinç başağı"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Ot"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Dört yapraklı yonca"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Akçaağaç yaprağı"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Düşen yaprak"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Rüzgarda yaprak"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Mantar"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Domates"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Patlıcan"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Üzüm"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Kavun"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Karpuz"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandalina"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Muz"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Kırmızı elma"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Yeşil elma"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Armut"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Şeftali"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Kiraz"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Çilek"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pizza dilimi"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Kemikli et"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Tavuk butu"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Pirinç krakeri"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Pirinç köftesi"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Pilav"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Körili pilav"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Çanak"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Ekmek"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Patates kızartması"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Kızarmış tatlı patates"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Suşi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Karides tava"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Rulo balık köftesi"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Yumuşak dondurma"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Meyveli buz"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Dondurma"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Halka çörek"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Çerez"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Çubuk çikolata"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Şeker"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lolipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Krema"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Bal kabı"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Kurabiye"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Japon Bento paketi"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Yiyecek kasesi"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Yemek pişirme"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Çatal ve bıçak"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Kulpsuz çay fincanı"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Sake şişesi ve fincanı"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Şarap bardağı"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Kokteyl bardağı"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropikal içecek"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Bira bardağı"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Bira bardağı tokuşturma"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Biberon"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Kurdele"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Paketli hediye"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Doğum günü pastası"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Balkabağından fener"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Noel ağacı"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Noel baba"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Havai fişekler"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Maytap"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Balon"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Parti konfetisi"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfeti topu"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata ağacı"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Çapraz bayraklar"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Çam süslemesi"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Japon bebekler"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Sazan balığı şekilli flama"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Rüzgar çanı"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Ay izleme töreni"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Okul çantası"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Mezuniyet kepi"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Atlıkarınca"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Dönme dolap"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Lunapark hız treni"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Kamış olta ve balık"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Film kamerası"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Sinema"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Kulaklık"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Ressam paleti"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Silindir şapka"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Sirk çadırı"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Bilet"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Film çekim tahtası"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Gösteri sanatları"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video oyunu"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Tam isabet"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Kumar makinesi"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Bilardo"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Oyun zarı"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Çiçekli oyun kartları"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Müzik notası"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Birden fazla müzik notası"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksafon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Müzik klavyesi"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Keman"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Partisyon"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Kuşaklı koşu tişörtü"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tenis raketi ve topu"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Kayak ve kayak ayakkabısı"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basket topu ve pota"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Damalı bayrak"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Kar kayakçısı"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Koşucu"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Sörfçü"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Kupa"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"At yarışı"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikan futbolu"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ragbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Yüzücü"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Ev inşaatı"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Bahçeli ev"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Ofis binası"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Japon postanesi"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Avrupa postanesi"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Hastane"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Banka"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"ATM"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Otel"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Aşk oteli"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Bakkal"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Okul"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Alışveriş merkezi"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Fabrika"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya feneri"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Japon kalesi"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Avrupa kalesi"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Sıçan"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Fare"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Öküz"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Manda"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"İnek"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopar"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Tavşan"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Kedi"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Ejderha"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Timsah"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Balina"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Salyangoz"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Yılan"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"At"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Koç"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Keçi"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Koyun"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Maymun"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Horoz"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Tavuk"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Köpek"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Domuz"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Yaban domuzu"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Fil"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Ahtapot"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Spiral deniz kabuğu"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Böcek"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Karınca"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Bal arısı"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Uğur böceği"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Balık"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropikal balık"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Balon balığı"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Kaplumbağa"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Yumurtadan çıkan civciv"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Civciv"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Öne bakan civciv"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Kuş"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Penguen"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Kaniş"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Hecin devesi"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Çift hörgüçlü deve"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Yunus"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Fare yüzü"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"İnek yüzü"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Kaplan yüzü"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Tavşan yüzü"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Kedi yüzü"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Ejderha yüzü"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Su püskürten balina"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"At yüzü"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Maymun yüzü"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Köpek yüzü"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Domuz yüzü"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Kurbağa yüzü"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Hamster yüzü"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Kurt yüzü"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Ayı yüzü"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda yüzü"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Domuz burnu"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Pati izleri"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Gözler"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Kulak"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Burun"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Ağız"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Dil"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Yukarıyı işaret eden beyaz parmak"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Aşağıyı işaret eden beyaz parmak"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Solu işaret eden beyaz parmak"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Sağı işaret eden beyaz parmak"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Yumruk işareti"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"El sallama işareti"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Tamam işareti"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Beğendim işareti"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Beğenmedim işareti"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Alkış işareti"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Açık eller işareti"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Taç"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Kadın şapkası"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Gözlük"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Kravat"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Tişört"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Kot pantolon"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Elbise"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Kadın elbiseleri"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Cüzdan"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"El çantası"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Kese"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Erkek ayakkabısı"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Spor ayakkabısı"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Yüksek topuklu ayakkabı"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Kadın sandaleti"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Kadın çizmesi"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Ayak izleri"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Büst silüeti"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Büst silüetleri"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Erkek çocuk"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Kız çocuk"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Erkek"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Kadın"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Aile"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Erkek ve kadın el ele"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"İki erkek el ele"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"İki kadın el ele"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Polis memuru"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Tavşan kulaklı kadın"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Duvaklı gelin"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Sarışın kişi"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Gua pi mao şapkalı adam"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Sarıklı adam"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Yaşlı adam"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Yaşlı kadın"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Bebek"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"İnşaat işçisi"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Prenses"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Japon canavarı"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Japon cini"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Hayalet"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Bebek melek"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Uzaylı"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Uzaylı canavar"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Küçük şeytan"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Kafatası"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Danışma masası görevlisi"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Muhafız"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Dansçı"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Ruj"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Tırnak cilası"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Yüz masajı"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Saç kesme"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Berber işareti"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Şırınga"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Hap"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Öpücük izi"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Aşk mektubu"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Zil"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Mücevher"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Öpücük"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Buket"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Kalpli çift"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Düğün"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Çarpan kalp"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Kırık kalp"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"İki kalp"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Parlayan kalp"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Büyüyen kalp"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Oklu kalp"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Mavi kalp"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Yeşil kalp"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Sarı kalp"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Mor kalp"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Kurdeleli kalp"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Dönen kalpler"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Kalpli süsleme"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"İçi noktalı elmas şekli"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Ampul"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Kızgınlık simgesi"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Uyuma simgesi"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Çarpışma simgesi"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Su gibi terleme simgesi"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Damlacık"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Hızla koşma simgesi"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Pislik yığını"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Sıkılmış pazılar"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Şaşkın simgesi"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Konuşma balonu"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Düşünce balonu"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Beyaz çiçek"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Yüz puan simgesi"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Para çantası"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Döviz bozdurma"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Koyu renk dolar işareti"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredi kartı"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Yen işaretli kağıt para"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Dolar işaretli kağıt para"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Avro işaretli kağıt para"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Sterlin işaretli kağıt para"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Kanatlı para"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Yukarı giden grafik ve yen işareti"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Koltuk"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Kişisel bilgisayar"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Evrak çantası"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Mini disk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disket"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optik disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Dosya klasörü"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Dosya klasörü aç"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Kıvrık sayfa"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Yukarı bakan sayfa"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Takvim"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Yapraklı takvim"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kart fihristi"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Yukarı giden grafik"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Aşağı giden grafik"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Çubuk grafik"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Pano"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Raptiye"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Yuvarlak başlı raptiye"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Ataş"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Düz cetvel"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Üçgen cetvel"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Yer işaretleri"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ana Defter"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Not Defteri"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Süslü kapaklı not defteri"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Kapalı kitap"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Açık kitap"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Yeşil kitap"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Mavi kitap"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Turuncu kitap"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Kitaplar"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"İsim rozeti"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Kaydırma"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Not"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefon alıcısı"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Çağrı Cihazı"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faks cihazı"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Uydu anteni"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Megafon"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Neşeli megafon"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Giden kutusu"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Gelen kutusu"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Paket"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-posta simgesi"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Gelen zarf"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Üstünde aşağı ok bulunan zarf"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"İşareti indirilmiş kapalı posta kutusu"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"İşareti kaldırılmış kapalı posta kutusu"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"İşareti kaldırılmış açık posta kutusu"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"İşareti indirilmiş açık posta kutusu"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Posta kutusu"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Posta borusu"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Gazete"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Cep telefonu"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Solunda sağ ok bulunan cep telefonu"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Titreşim modu"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Cep telefonu kapalı"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Cep telefonu yasak"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Çubuklu anten"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Video kamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizyon"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radyo"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Video Kaset"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Bükülü sağ oklar"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Saat yönünde sağ ve sol açık daire oklar"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"İçinde 1 rakamı olan daire ve saat yönünde sağ ve sol açık daire oklar"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Saat yönünde aşağı ve yukarı açık daire oklar"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Saat yönünün aksine aşağı ve yukarı açık daire oklar"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Düşük parlaklık simgesi"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Yüksek parlaklık simgesi"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Hoparlör sesi kapalı"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Hoparlör"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Tek ses dalgalı hoparlör"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Üç ses dalgalı hoparlör"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Pil"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektrik fişi"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Sola bakan büyüteç"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Sağa bakan büyüteç"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Dolma kalem ucu ve kilit"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Anahtar ve kapalı kilit"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Anahtar"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Kilit"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Açık kilit"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Zil"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Zil sesi kapalı"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Yer işareti"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Bağlantı simgesi"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radyo düğmesi"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Sol geri ok"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Sol bitiş oku"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Üstünde sağ ve sol ok bulunan, ünlem işaretli açık yazısı"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Üstünde sağ ok bulunan yakında yazısı"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Üstünde yukarı ok bulunan yukarı işareti"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18 yaşından küçükler giremez işareti"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Klavye tuşu 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Latin büyük harf giriş simgesi"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Latin küçük harf giriş simgesi"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Rakam giriş simgesi"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Simgeler için giriş simgesi"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Latin harfi giriş simgesi"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Ateş"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Pilli fener"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"İngiliz anahtarı"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Çekiç"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Cıvata ve somun"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Bıçak"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Tabanca"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristal küre"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Ortası noktalı, altı köşeli yıldız"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Acemi anlamında Japon simgesi"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Üç çatallı amblem"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Siyah kare düğmesi"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Beyaz kare düğmesi"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Büyük kırmızı daire"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Büyük mavi daire"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Büyük turuncu baklava şekli"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Büyük mavi baklava şekli"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Küçük turuncu baklava şekli"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Küçük mavi baklava şekli"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Yukarıya işaret eden kırmızı üçgen"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Aşağıya işaret eden kırmızı üçgen"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Yukarıya işaret eden küçük kırmızı üçgen"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Aşağıya işaret eden küçük kırmızı üçgen"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Saat bir"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Saat iki"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Saat üç"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Saat dört"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Saat beş"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Saat altı"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Saat yedi"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Saat sekiz"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Saat dokuz"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Saat on"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Saat on bir"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Saat on iki"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Saat bir buçuk"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Saat iki buçuk"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Saat üç buçuk"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Saat dört buçuk"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Saat beş buçuk"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Saat altı buçuk"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Saat yedi buçuk"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Saat sekiz buçuk"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Saat dokuz buçuk"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Saat on buçuk"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Saat on bir buçuk"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Saat yarım"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji dağı"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokyo kulesi"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Özgürlük heykeli"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Japonya silüeti"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai heykeli"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Sırıtan yüz"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Gözleri gülen, sırıtan yüz"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Mutluluk gözyaşı döken yüz"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Ağzı açık gülen yüz"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Ağzı açık, gözleri gülen yüz"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Soğuk soğuk terleyen, ağzı açık, gözleri gülen yüz"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Gözleri sıkı kapalı, ağzı açık, gülen yüz"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Başı haleli gülen yüz"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Boynuzlu gülen yüz"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Göz kırpan yüz"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Gözleri gülen yüz"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Lezzetli yemeğin tadını çıkaran yüz"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Rahatlamış yüz"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Gözleri kalp şeklinde gülen yüz"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Gözlüklü gülen yüz"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Yapmacık gülen yüz"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Duygusuz yüz"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"İfadesiz yüz"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Keyifsiz yüz"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Soğuk soğuk terleyen yüz"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Düşünceli yüz"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Şaşkın yüz"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Afallamış yüz"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Öpen yüz"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Öpücük gönderen yüz"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Gözleri gülen, öpen yüz"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Gözleri kapalı öpen yüz"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Dili dışarıda yüz"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Dili dışarıda göz kırpan yüz"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Dili dışarıda, gözleri sımsıkı kapalı yüz"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Üzgün yüz"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Endişeli yüz"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Kızgın yüz"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Asık yüz"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Ağlayan yüz"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Azimli yüz"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Zafer kazanmış yüz"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Üzgün ancak rahatlamış yüz"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Ağzı açık hoşnutsuz yüz"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Üzüntülü yüz"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Korkmuş yüz"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Yorgun yüz"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Uykulu yüz"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Bitkin yüz"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Ekşi yüz"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Bağıra çağıra ağlayan yüz"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Ağzı açık yüz"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Susmuş yüz"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Soğuk soğuk terleyen, ağzı açık yüz"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Korkuyla bağıran yüz"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Çok şaşırmış yüz"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Kızarmış yüz"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Uyuyan yüz"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Sersemlemiş yüz"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Ağzı olmayan yüz"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Tıbbi maskeli yüz"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Gülen gözlü, sırıtan kedi yüzü"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Mutluluk gözyaşları döken kedi yüzü"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Ağzı açık, gülen kedi yüzü"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Gözleri kalp şeklinde gülen kedi yüzü"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Acı acı gülen kedi yüzü"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Gözleri kapalı, öpen kedi yüzü"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Somurtmuş kedi yüzü"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Ağlayan kedi yüzü"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Yorgun kedi yüzü"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"İyi değil hareketi yapan yüz"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Onaylayan ifadeye sahip yüz"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Başıyla abartılı şekilde onaylayan kişi"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Görmeyen maymun"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Duymayan maymun"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Konuşmayan maymun"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Mutlu şekilde bir elini kaldırmış kişi"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Kutlama için ellerini kaldırmış kişi"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Hoşnutsuz kişi"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Somurtkan yüzlü kişi"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Ellerini birleştirmiş kişi"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Roket"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Helikopter"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Buharlı lokomotif"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Vagon"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Yüksek hızlı tren"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Mermi burunlu, yüksek hızlı tren"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tren"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Hafif raylı sistem"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"İstasyon"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvay"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tramvay vagonu"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Otobüs"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Gelen otobüs"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Troleybüs"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Otobüs durağı"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibüs"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Cankurtaran"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"İtfaiye"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Polis arabası"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Gelen polis arabası"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Gelen taksi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Otomobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Gelen otomobil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Eğlence taşıtı"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Kamyon"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Tır"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktör"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Tek raylı sistem"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Dağ demiryolu"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Hava ray sistemi"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Teleferik"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Hava tramvayı"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Gemi"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Tekne"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Hız teknesi"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Yatay trafik ışığı"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Dikey trafik ışığı"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"İnşaat işareti"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Polis arabası ışığı"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Üçgen konum işareti"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Kapı"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Girilmez işareti"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Sigara içilir işareti"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Sigara içilmez simgesi"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Çöpe atınız işareti"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Yere çöp atmayınız işareti"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"İçilebilir su işareti"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"İçilemez su işareti"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Bisiklet"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Bisiklet giremez"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Bisikletçi"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Dağ bisikletçisi"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Yaya"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Yaya giremez"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Okul geçidi"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Erkekler için işareti"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Kadınlar için işareti"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Tuvalet"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Bebek işareti"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Tuvalet"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Tuvalet"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Duş"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Banyo"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Küvet"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasaport kontrolü"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Gümrük"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Bagaj alma yeri"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Kayıp bagaj"</string>
+</resources>
diff --git a/java/res/values-tr/strings-talkback-descriptions.xml b/java/res/values-tr/strings-talkback-descriptions.xml
index a810eda..cd72c8a 100644
--- a/java/res/values-tr/strings-talkback-descriptions.xml
+++ b/java/res/values-tr/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Metin girilmedi"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g>, <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> kelimesini <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> olarak düzeltir"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> otomatik düzeltme yapar"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Öneri yok"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Bilinmeyen karakter"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Üst karakter"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Diğer simgeler"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Büyük Harf I, üst noktalı"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Bilinmeyen simge"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Bilinmeyen emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Sıkılmış yüz"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Utanmış yüz"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Güneş gözlüğü takan yüz"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Şaşırmış yüz"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Öpen yüz"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Çatık kaşlı yüz"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Alternatif karakterler kullanılabilir"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Alternatif karakterler yoksayılır"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Alternatif öneriler kullanılabilir"</string>
diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml
index d48ab7b..8f84ca9 100644
--- a/java/res/values-tr/strings.xml
+++ b/java/res/values-tr/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tuşa basıldığında titret"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Tuşa basıldığında ses çıkar"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Tuşa basıldığında pop-up aç"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Tercihler"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Hesaplar ve Gizlilik"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Görünüm ve Düzenler"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Hareketle Yazma"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Metin düzeltme"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Gelişmiş"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Tema"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Bölünmüş klavyeyi etkinleştir"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google Klavye Senkronizasyonu"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Senkronizasyon açık"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Kişisel sözlüğünüzü cihazlar arasında senkronize edin"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Şimdi senkronize et"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Bulut verilerini sil"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Senkronize edilmiş verilerinizi Google\'dan siler"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Senkronize edilmiş verileriniz buluttan silinecek. Emin misiniz?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Sil"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"İptal"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Kişisel sözlüğünüz senkronize edilecek ve Google sunucularına yedeklenecektir. Ürünlerimizi iyileştirmeye yardımcı olması için kelime sıklığına ilişkin istatistiksel bilgiler toplanabilir. Tüm bilgilerin toplanması ve kullanımı "<a href="https://www.google.com/policies/privacy">"Google\'ın Gizlilik Politikası"</a>"\'na uygun olarak gerçekleştirilir."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Bu özelliği etkinleştirmek için cihaza bir Google Hesabı ekleyin"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Diğer giriş yöntemine geç"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Dil geçiş tuşu diğer giriş yöntemlerini de kapsar"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Dil değiştirme tuşu"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Birden fazla giriş dili etkin olduğunda göster"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Kaydırma göstergesini aç"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Üst Karakter veya Sembol tuşlarından kaydırırken görsel ipucu ver"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tuş popup\'ının kapatılmasını geciktirme"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Gecikme yok"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Varsayılan"</string>
@@ -54,7 +59,7 @@
     <string name="use_personalized_dicts" msgid="5167396352105467626">"Kişisel öneriler"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> uygulamasını iyileştir"</string>
     <string name="use_double_space_period" msgid="8781529969425082860">"Çift boşlukla nokta ekleme"</string>
-    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Boşluk çubuğuna iki kez vurmak nokta ve ardından bir boşluk ekler"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Boşluk çubuğuna iki kez dokunmak nokta ve ardından bir boşluk ekler"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Otomatik olarak büyük harf yap"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"Her cümlenin ilk kelimesini büyük harf yap"</string>
     <string name="edit_personal_dictionary" msgid="3996910038952940420">"Kişisel sözlük"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Ana sözlük"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Düzeltme önerilerini göster"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Yazarken, önerilen kelimeleri görüntüle"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Her zaman göster"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Dikey modda göster"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Her zaman gizle"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Rahatsız edici kelimeleri engelle"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Rahatsız edici olabilecek kelimeleri önerme"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Otomatik düzeltme"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Ses girişi tuşu"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Hiçbir ses girişi yöntemi etkinleştirilmedi. Dil ve giriş ayarlarını kontrol edin."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Geri bildirim gönder"</string>
-    <string name="select_language" msgid="3693815588777926848">"Giriş dilleri"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Diller"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Yardım ve geri bildirim"</string>
+    <string name="select_language" msgid="5709487854987078367">"Diller"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Kaydetmek için tekrar dokunun"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Kaydetmek için buraya dokunun"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Klavye teması"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Hesap değiştir"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Hiçbir hesap seçilmedi"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Şu anda <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> kullanılıyor"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"Tamam"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"İptal"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Oturumu kapat"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Kullanmak için bir hesap seçin"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"İngilizce (BK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"İngilizce (ABD)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"İspanyolca (ABD)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hingilizce"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Sırpça (Latin alfabesi)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"İngilizce (İngiltere) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"İngilizce (ABD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"İspanyolca (ABD) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hingilizce (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Sırpça (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Geleneksel)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kiril)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Kompakt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Dil yok (Alfabe)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabe (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabe (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabe (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabe (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Klavye teması"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Özel giriş stilleri"</string>
     <string name="add_style" msgid="6163126614514489951">"Stil ekle"</string>
     <string name="add" msgid="8299699805688017798">"Ekle"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Etkinleştir"</string>
     <string name="not_now" msgid="6172462888202790482">"Şimdi değil"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Aynı giriş stili zaten var: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tuşa uzun basma gecikmesi"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Tuşa basma titreşim süresi"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Tuşa basma ses seviyesi"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Harici sözlük dosyasını oku"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"İndirilenler klasöründe sözlük dosyası yok"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Yüklemek için bir sözlük dosyası seçin"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> için bu dosya gerçekten yüklensin mi?"</string>
-    <string name="error" msgid="8940763624668513648">"Bir hata oluştu"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tuşa uzun basma gecikmesi"</string>
     <string name="button_default" msgid="3988017840431881491">"Varsayılan"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> uygulamasına hoş geldiniz"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Hareketle Yazmayı içerir"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Artık <xliff:g id="APPLICATION_NAME">%s</xliff:g> ile tüm favori uygulamalarınızda yazabilirsiniz."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Ek dilleri yapılandırın"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Tamamlandı"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Uygulama simgesini göster"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Uygulama simgesini başlatıcıda göster"</string>
     <string name="app_name" msgid="6320102637491234792">"Sözlük Sağlayıcı"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Sözlük Sağlayıcı"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Sözlük Hizmeti"</string>
diff --git a/java/res/values-uk/strings-emoji-descriptions.xml b/java/res/values-uk/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..ca3aef3
--- /dev/null
+++ b/java/res/values-uk/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Знак \"Авторське право\""</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Знак \"Зареєстровано\""</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Подвійний знак оклику"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Знак оклику та знак запитання"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Знак торговельної марки"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Інформація"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Стрілка ліворуч-праворуч"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Стрілка вгору-вниз"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Стрілка, що вказує на північний захід"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Стрілка, що вказує на північний схід"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Стрілка, що вказує на південний схід"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Стрілка, що вказує на південний захід"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Стрілка ліворуч із гачком"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Стрілка праворуч із гачком"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Годинник"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Пісочний годинник"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Два чорні трикутники, направлені праворуч"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Два чорні трикутники, направлені ліворуч"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Два чорні трикутники, направлені вгору"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Два чорні трикутники, направлені вниз"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Будильник"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Пісочний годинник із піском, який сиплеться"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Велика латинська буква M у колі"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Малий чорний квадрат"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Малий білий квадрат"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Чорний трикутник, направлений праворуч"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Чорний трикутник, направлений ліворуч"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Середній білий квадрат"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Середній чорний квадрат"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Не дуже малий білий квадрат"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Не дуже малий чорний квадрат"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Чорне сонце з променями"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Хмара"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Чорний телефон"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Поле виборчого бюлетеня з позначкою"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Парасолька з краплями дощу"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Гарячий напій"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Білий вказівний палець, спрямований угору"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Біле всміхнене обличчя"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Овен"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Телець"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Близнюки"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Рак"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Лев"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Діва"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Терези"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Скорпіон"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Стрілець"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Козеріг"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Водолій"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Риби"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Масть \"чорна піка\""</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Масть \"чорна трефа\""</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Масть \"чорна чирва\""</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Масть \"чорна бубна\""</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Гарячі джерела"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Чорний міжнародний символ утилізації"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Символ інвалідного візка"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Якір"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Попереджувальний знак"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Знак \"Висока напруга\""</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Середнє біле коло"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Середнє чорне коло"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Футбольний м’яч"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Бейсбольний м’яч"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Сніговик без снігу"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Сонце за хмарою"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Змієносець"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"В’їзд заборонено"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Церква"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Фонтан"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Прапорець на полі для гольфу"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Вітрильник"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Намет"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Паливний насос"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Чорні ножиці"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Жирний білий прапорець"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Літак"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Конверт"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Піднятий кулак"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Піднята рука"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Жест \"Перемога\""</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Олівець"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Чорне перо"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Жирний прапорець"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Жирний знак множення \"x\""</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Блиск"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Восьмикутна зірка"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Чорна восьмикутна зірка"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Сніжинка"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Іскра"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Хрестик"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Білий хрестик у квадраті на чорному фоні"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Чорний знак запитання"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Білий знак запитання"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Білий знак оклику"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Символ жирного знаку оклику"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Велике чорне серце"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Жирний знак плюса"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Жирний знак мінуса"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Жирний знак ділення"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Чорна стрілка праворуч"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Закручена петля"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Подвійна закручена петля"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Стрілка праворуч і вгору"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Стрілка праворуч і вниз"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Чорна стрілка ліворуч"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Чорна стрілка вгору"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Чорна стрілка вниз"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Великий чорний квадрат"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Великий білий квадрат"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Середня біла зірка"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Велике жирне коло"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Хвилясте тире"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Японський знак початку частини пісні"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ієрогліф \"Вітання\" в колі"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Ієрогліф \"Таємниця\" в колі"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Плитка \"Червоний дракон\" у грі в маджонг"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Гральна карта \"Чорний джокер\""</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Друга група крові"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Третя група крові"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Перша група крові"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Автомобільна стоянка"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Четверта група крові"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Квадратний значок очищення"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Квадратний значок \"Круто\""</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Квадратний значок \"Безкоштовно\""</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Квадратний значок \"Ідентифікація\""</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Квадратний значок \"Новий\""</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Квадратний значок \"Погано\""</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Квадратний значок \"O’кей\""</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Квадратний значок \"СОС\""</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Квадратний значок \"Оновлення\" зі знаком оклику"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Квадратний значок \"Проти\""</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Квадратний значок \"Тут\", катакана"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Квадратний значок \"Сервіс\", катакана"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Ієрогліф \"Безкоштовно\" у квадраті"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Ієрогліф \"Місце заброньовано\" у квадраті"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ієрогліф \"Заборонено\" у квадраті"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Ієрогліф \"Вакансія\" у квадраті"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ієрогліф \"Прийнято\" у квадраті"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ієрогліф \"Повна зайнятість\" у квадраті"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Ієрогліф \"Оплачено\" у квадраті"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Ієрогліф \"Щомісячно\" у квадраті"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Ієрогліф \"Додаток\" у квадраті"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Ієрогліф \"Знижка\" у квадраті"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Ієрогліф \"Працює\" у квадраті"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Ієрогліф \"Перевага\" в колі"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ієрогліф \"Прийняти\" в колі"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Циклон"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Туман"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Закрита парасолька"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Зоряна ніч"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Схід сонця над горами"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Схід сонця"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Місто в сутінках"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Схід сонця над будинками"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Веселка"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Міст уночі"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Хвиля"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Вулкан"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Чумацький шлях"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Глобус, Європа й Африка"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Глобус, Америка"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Глобус, Азія та Австралія"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Глобус із меридіанами"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Символ молодого місяця"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Символ молодого півмісяця"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Символ місяця в першій чверті"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Символ зростаючого місяця"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Символ повного місяця"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Символ спадаючого місяця"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Символ місяця в останній чверті"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Символ старого місяця"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Півмісяць"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Новий місяць з обличчям"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Місяць у першій чверті з обличчям"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Місяць в останній чверті з обличчям"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Повний місяць з обличчям"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Сонце з обличчям"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Зірка, що сяє"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Метеор"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Каштан"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Саджанець"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Вічнозелене дерево"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Листяне дерево"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Пальма"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Кактус"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Тюльпан"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Вишневий цвіт"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Троянда"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Гібіскус"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Соняшник"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Цвіт"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Качан кукурудзи"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Колосся рису"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Трава"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Чотирилиста конюшина"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Кленовий листок"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Опалий листок"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Листя, що кружляє за вітром"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Гриб"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Помідор"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Баклажан"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Виноград"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Диня"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Кавун"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Мандарин"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Лимон"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Банан"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ананас"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Червоне яблуко"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Зелене яблуко"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Груша"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Персик"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Вишні"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Полуниця"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Гамбургер"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Шматок піци"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"М’ясо на кістці"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Ніжка птиці"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Рисовий крекер"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Рисова кулька"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Варений рис"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Рис із карі"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Миска з локшиною"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Спагеті"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Хліб"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Картопля фрі"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Смажений батат"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Данго"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Оден"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Суші"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Смажені креветки"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Рибна котлета у формі рулету"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"М’яке морозиво"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Льодова стружка"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Морозиво"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Пончик"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Печиво"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Плитка шоколаду"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Цукерка"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Льодяник"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Заварний крем"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Горщик із медом"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Тістечко"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Упаковка бенто"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Горщик з їжею"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Куховарство"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Виделка та ніж"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Чайна чашка без вушка"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Пляшка та чашка для саке"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Келих для вина"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Бокал для коктейлю"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Тропічний напій"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Кухоль для пива"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Кухлі з пивом, що цокаються"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Пляшечка для немовляти"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Стрічка"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Запакований подарунок"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Торт на день народження"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Ліхтар-гарбуз"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Ялинка"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Дід Мороз"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Феєрверки"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Бенгальський вогонь"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Повітряна кулька"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Хлопавка"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Кулька з конфеті"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Танабата, гілка тандзаку"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Схрещені прапорці"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Прикраси на ялинку"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Японські ляльки"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Транспарант із карпами"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Китайські дзвіночки"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Церемонія вшанування місяця"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Шкільний ранець"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Академічна шапочка"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Коник із каруселі"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Колесо огляду"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Американські гірки"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Вудка та риба"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Мікрофон"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Кінокамера"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Кінотеатр"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Навушники"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Палітра художника"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Циліндр"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Цирковий намет"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Квиток"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Нумератор із хлопавкою"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Театральне мистецтво"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Відеогра"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Пряме попадання"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Ігровий автомат"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Більярд"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Гральний кубик"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Боулінг"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Гральні карти ханафуда"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Музична нота"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Декілька музичних нот"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Саксофон"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Гітара"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Музична клавіатура"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Труба"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Скрипка"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Партитура"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Футболка зі стрічкою"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Тенісна ракетка та м’ячик"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Лижа й лижний черевик"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Баскетбольний м’яч і кільце"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Картатий прапорець"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Сноубордист"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Бігун"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Серфінгіст"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Трофей"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Кінні перегони"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Американський футбол"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Регбі"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Плавець"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Будинок"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Будинок із садом"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Офісна будівля"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Японська пошта"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Європейська пошта"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Лікарня"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Банк"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Банкомат"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Готель"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Готель для закоханих"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Цілодобовий магазин"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Школа"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Універмаг"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Фабрика"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Ліхтар ідзакая"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Японський замок"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Європейський замок"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Щур"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Миша"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Бик"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Буйвол"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Корова"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Леопард"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Кролик"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Кіт"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Дракон"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Крокодил"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Кит"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Равлик"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Змія"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Кінь"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Баран"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Коза"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Вівця"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Мавпа"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Півень"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Курка"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Собака"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Свиня"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Кабан"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Слон"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Восьминіг"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Спіральна мушля"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Жук"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Мураха"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Медоносна бджола"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Сонечко"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Риба"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Тропічна риба"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Риба-собака"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Черепаха"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Курча, яке прокльовується з яйця"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Курча"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Курча анфас"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Птах"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Пінгвін"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Коала"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Пудель"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Одногорбий верблюд"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Двогорбий верблюд"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Дельфін"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Миша"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Корова"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Тигр"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Кріль"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Кіт"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Дракон"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Кит із фонтаном"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Кінь"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Мавпа"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Собака"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Свиня"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Жаба"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Хом’як"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Вовк"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Ведмідь"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Панда"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Свиняче рильце"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Сліди лап"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Очі"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Вухо"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Ніс"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Рот"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Язик"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Біла рука з вказівним пальцем угору з тильної сторони"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Біла рука з вказівним пальцем униз із тильної сторони"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Біла рука з вказівним пальцем ліворуч із тильної сторони"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Біла рука з вказівним пальцем праворуч із тильної сторони"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Знак кулака"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Знак руки, яка махає"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Знак руки, яка показує \"ОК\""</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Знак \"Подобається\""</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Знак \"Не подобається\""</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Знак \"Оплески\""</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Знак \"Відкриті руки\""</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Корона"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Жіночий капелюшок"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Окуляри"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Краватка"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Футболка"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Джинси"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Сукня"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Кімоно"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Бікіні"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Жіночий одяг"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Гаманець"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Жіноча сумка"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Чохол"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Чоловіче взуття"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Спортивне взуття"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Туфелька на високому підборі"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Жіночі сандалі"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Жіночі чоботи"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Сліди ніг"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Силует бюсту"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Силуети бюстів"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Хлопець"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Дівчина"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Чоловік"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Жінка"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Сім’я"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Чоловік та жінка тримаються за руки"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Двоє чоловіків тримаються за руки"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Двоє жінок тримаються за руки"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Офіцер поліції"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Жінка з кролячими вухами"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Наречена з фатою"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Людина зі світлим волоссям"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Чоловік у круглій шапочці"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Чоловік у тюрбані"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Літній чоловік"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Літня жінка"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Немовля"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Будівельник"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Принцеса"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Японський людожер"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Японський гоблін"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Привид"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Янголятко"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Прибулець із космосу"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Прибулець-монстр"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Чортеня"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Череп"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Працівник довідкового бюро"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Охоронець"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Танцівник"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Губна помада"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Лак для нігтів"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Масаж обличчя"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Стрижка"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Шлагбаум"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Шприц"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Таблетка"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Відбиток губ"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Любовний лист"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Перстень"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Дорогоцінний камінь"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Поцілунок"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Букет"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Пара із серцем"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Весілля"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Пульсуюче серце"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Розбите серце"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Два серця"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Серце, що блищить"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Серце, що збільшується"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Серце зі стрілою"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Синє серце"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Зелене серце"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Жовте серце"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Фіолетове серце"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Серце зі стрічкою"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Серця, що обертаються"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Декор у вигляді серця"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Контур діаманта з крапкою всередині"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Електрична лампочка"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Символ гніву"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Бомба"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Символ сну"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Символ зіткнення"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Краплі поту"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Крапля"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Символ ривка"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Купка екскрементів"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Зігнутий біцепс"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Символ запаморочення"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Хмаринка з текстом"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Хмаринка з думками"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Біла квітка"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Символ \"Сто очок\""</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Мішок із грошима"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Обмін валют"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Символ важкого долара"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Кредитна картка"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Банкнота із символом єни"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Банкнота із символом долара"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Банкнота із символом євро"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Банкнота із символом фунта"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Гроші з крилами"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Висхідна діаграма із символом єни"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Сидіння"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Персональний комп’ютер"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Портфель"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Міні-диск"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Дискета"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Оптичний диск"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD-диск"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Папка з файлами"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Відкрита папка"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Сторінка із завитком"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Сторінка лицевою стороною"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Календар"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Відривний календар"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Картотека"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Висхідна діаграма"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Низхідна діаграма"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Гістограма"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Папка із зажимом для паперу"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Канцелярська кнопка"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Кругла канцелярська кнопка"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Скріпка"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Пряма лінійка"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Косинець"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Закладки"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Реєстр"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Записник"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Записник із декоративною обкладинкою"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Закрита книга"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Відкрита книга"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Зелена книга"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Синя книга"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Оранжева книга"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Книги"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Бейдж з іменем"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Сувій"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Записка"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Телефонна слухавка"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Пейджер"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Факс"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Супутникова антена"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Гучномовець"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Рупор"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Лоток для вихідної пошти"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Лоток для вхідної пошти"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Пакет"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Символ електронної пошти"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Вхідний конверт"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Конверт зі стрілкою вниз угорі"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Закрита поштова скринька з опущеним прапорцем"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Закрита поштова скринька з піднятим прапорцем"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Відкрита поштова скринька з піднятим прапорцем"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Відкрита поштова скринька з опущеним прапорцем"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Поштова скринька"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Поштовий ріжок"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Газета"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Мобільний телефон"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Мобільний телефон зі стрілкою праворуч зліва"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Режим вібрації"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Мобільний телефон вимкнено"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Мобільні телефони заборонено"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Антена з індикатором рівня сигналу"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Камера"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Відеокамера"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Телебачення"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Радіо"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Відеокасета"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Перехрещені стрілки праворуч"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Кругові стрілки ліворуч та праворуч, які вказують напрям за годинниковою стрілкою"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Кругові стрілки ліворуч та праворуч, які вказують напрям за годинниковою стрілкою, і накладена на них цифра один"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Кругові стрілки вгору та вниз, які вказують напрям за годинниковою стрілкою"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Кругові стрілки вгору та вниз, які вказують напрям проти годинникової стрілки"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Символ малої яскравості"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Символ великої яскравості"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Перекреслений динамік"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Динамік"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Динамік з однією звуковою хвилею"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Динамік із трьома звуковими хвилями"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Акумулятор"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Вилка електроприладу"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Лупа, повернута ліворуч"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Лупа, повернута праворуч"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Замок із чорнильним пером"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Закритий замок із ключем"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ключ"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Замок"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Відкритий замок"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Дзвоник"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Перекреслений дзвоник"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Закладка"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Символ ланки"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Перемикач"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Слово \"назад\" зі стрілкою ліворуч зверху"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Слово \"кінець\" зі стрілкою ліворуч зверху"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Слово \"увімкнено\" зі знаком оклику та стрілкою праворуч-ліворуч зверху"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Слово \"незабаром\" зі стрілкою праворуч зверху"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Слово \"угору\" зі стрілкою вгору зверху"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Символ \"Вхід до 18 років заборонено\""</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Поверхня клавіші \"10\""</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Символ введення великих латинських літер"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Символ введення малих латинських літер"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Символ введення цифр"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Знак вводу символів"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Символ введення латинських літер"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Вогонь"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Кишеньковий ліхтарик"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Гайковий ключ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Молоток"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Гайка та болт"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Японський кухонний ніж"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Пістолет"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Мікроскоп"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Телескоп"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Кришталева куля"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Шестикутна зірка з крапкою посередині"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Японський символ \"Початківець\""</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Тризуб"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Чорна квадратна кнопка"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Біла квадратна кнопка"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Велике червоне коло"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Велике синє коло"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Великий оранжевий діамант"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Великий синій діамант"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Малий оранжевий діамант"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Малий синій діамант"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Червоний трикутник, спрямований угору"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Червоний трикутник, спрямований униз"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Малий червоний трикутник, спрямований угору"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Малий червоний трикутник, спрямований униз"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Годинник, який показує першу годину"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Годинник, який показує другу годину"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Годинник, який показує третю годину"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Годинник, який показує четверту годину"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Годинник, який показує п’яту годину"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Годинник, який показує шосту годину"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Годинник, який показує сьому годину"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Годинник, який показує восьму годину"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Годинник, який показує дев’яту годину"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Годинник, який показує десяту годину"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Годинник, який показує одинадцяту годину"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Годинник, який показує дванадцяту годину"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Годинник, який показує першу годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Годинник, який показує другу годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Годинник, який показує третю годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Годинник, який показує четверту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Годинник, який показує п’яту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Годинник, який показує шосту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Годинник, який показує сьому годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Годинник, який показує восьму годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Годинник, який показує дев’яту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Годинник, який показує десяту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Годинник, який показує одинадцяту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Годинник, який показує дванадцяту годину тридцять хвилин"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Гора Фудзі"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Токійська вежа"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Статуя Свободи"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Обриси Японії"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Кам’яна статуя моаї"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Обличчя, що сміється"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Усміхнене обличчя з примруженими очима"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Обличчя зі сльозами радості"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Усміхнене обличчя з відкритим ротом"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Усміхнене обличчя з відкритим ротом і примруженими очима"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Усміхнене обличчя з відкритим ротом і холодним потом"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Усміхнене обличчя з відкритим ротом і заплющеними очима"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Усміхнене обличчя з німбом"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Усміхнене обличчя з ріжками"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Обличчя, яке підморгує"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Усміхнене обличчя з примруженими очима"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Обличчя, яке насолоджується смачною їжею"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Обличчя з виразом полегшення"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Усміхнене обличчя з очима у формі сердець"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Усміхнене обличчя із сонцезахисними окулярами"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Обличчя із самовдоволеною посмішкою"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Нейтральне обличчя"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Обличчя без емоцій"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Незадоволене обличчя"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Обличчя з потом"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Задумливе обличчя"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Спантеличене обличчя"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Збентежене обличчя"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Обличчя, що цілує"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Обличчя, що надсилає повітряний поцілунок"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Обличчя, що цілує, з примруженими очима"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Обличчя, що цілує, із заплющеними очима"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Обличчя з висунутим язиком"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Обличчя, що підморгує, з висунутим язиком"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Обличчя з висунутим язиком і заплющеними очима"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Розчароване обличчя"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Стурбоване обличчя"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Сердите обличчя"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Насуплене обличчя"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Обличчя, що плаче"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Уперте обличчя"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Обличчя з виразом тріумфу"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Розчароване обличчя з виразом полегшення"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Насуплене обличчя з відкритим ротом"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Страждальне обличчя"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Налякане обличчя"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Зморене обличчя"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Сонне обличчя"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Стомлене обличчя"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Обличчя, яке кривляється"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Обличчя, яке гірко ридає"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Обличчя з відкритим ротом"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Обличчя, яке принишкло"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Обличчя з відкритим ротом і холодним потом"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Обличчя, яке кричить від страху"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Здивоване обличчя"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Обличчя з рум’янцем"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Обличчя, яке спить"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Запаморочене обличчя"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Обличчя без рота"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Обличчя з пов’язкою"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Кіт, який сміється, з примруженими очима"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Кіт зі сльозами радості"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Усміхнений кіт із відкритим ротом"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Усміхнений кіт з очима у формі сердець"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Котяча морда з кривою усмішкою"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Кіт, який цілує, із заплющеними очима"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Насуплений кіт"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Кіт, який плаче"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Стомлений кіт"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Обличчя з жестом \"Погано\""</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Обличчя з жестом \"O’кей\""</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Людина, яка низько кланяється"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Мавпа, яка закриває лапами очі"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Мавпа, яка закриває лапами вуха"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Мавпа, яка закриває лапами рот"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Щаслива людина з піднятою рукою"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Людина з піднятими догори руками на знак перемоги"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Нахмурена людина"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Людина з насупленим обличчям"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Людина зі складеними руками"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Ракета"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Вертоліт"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Паротяг"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Вагон"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Швидкісний потяг"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Швидкісний потяг із кулеподібним носом"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Потяг"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Метро"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Електропоїзд"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Станція"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Трамвай"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Вагон трамвая"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Автобус"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Автобус, який наближається"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Тролейбус"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Автобусна зупинка"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Мікроавтобус"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Автомобіль швидкої допомоги"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Пожежний автомобіль"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Патрульний автомобіль"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Патрульний автомобіль, що наближається"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Таксі"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Таксі, що наближається"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Автомобіль"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Автомобіль, що наближається"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Житловий трейлер"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Автофургон"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Автопоїзд"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Трактор"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Монорейкова залізниця"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Гірська залізниця"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Підвісна залізниця"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Гірський фунікулер"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Підвісна канатна дорога"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Корабель"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Весловий човен"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Швидкохідний катер"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Горизонтальний світлофор"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Вертикальний світлофор"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Знак \"Будівництво\""</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Патрульний автомобіль з проблисковими вогнями"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Трикутний прапорець на ніжці"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Двері"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Знак \"В’їзд заборонено\""</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Символ \"Місце для паління\""</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Символ \"Паління заборонено\""</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Символ \"Викидайте сміття в урну\""</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Символ \"Не смітити\""</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Символ \"Питна вода\""</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Символ \"Непридатна для пиття вода\""</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Велосипед"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Рух на велосипеді заборонено"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Велосипедист"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Гірський велосипедист"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Пішохід"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Рух пішоходів заборонено"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Діти на дорозі"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Символ \"Чоловік\""</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Символ \"Жінка\""</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Убиральня"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Символ \"Немовля\""</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Туалет"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Санвузол"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Душ"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Приймати ванну"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Ванна"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Паспортний контроль"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Митниця"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Пункт отримання багажу"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Камера зберігання"</string>
+</resources>
diff --git a/java/res/values-uk/strings-talkback-descriptions.xml b/java/res/values-uk/strings-talkback-descriptions.xml
index 80e4710..700ba50 100644
--- a/java/res/values-uk/strings-talkback-descriptions.xml
+++ b/java/res/values-uk/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Текст не введено"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> виправляє слово \"<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>\" на \"<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>\""</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> автоматично виправляє"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Немає пропозицій"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Невідомий символ"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Більше символів"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Велика I, крапка вгорі"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Невідомий символ"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Невідомий смайл Emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Обличчя, що нудьгує"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Збентежене обличчя"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Обличчя в окулярах"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Здивоване обличчя"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Обличчя, що цілує"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Насуплене обличчя"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Доступні альтернативні символи"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Альтернативні символи відхилено"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Доступні альтернативні пропозиції"</string>
diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml
index c59bed6..4d21599 100644
--- a/java/res/values-uk/strings.xml
+++ b/java/res/values-uk/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Вібр. при натисканні клавіш"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Звук при натиску клав."</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Сплив. при нат.клав."</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Параметри"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Облік. записи й конфіденційність"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Вигляд і розкладка"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Введення тексту жестами"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Виправлення тексту"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Додатково"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Тема"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Увімкнути розділену клавіатуру"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Синхронізувати Клавіатуру Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Синхронізацію ввімкнено"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Синхронізувати особистий словник на різних пристроях"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Синхронізувати"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Видалити дані з хмари"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Видаляє з Google ваші синхронізовані дані"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Видалити з хмари синхронізовані дані?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Видалити"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Скасувати"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Ваш особистий словник буде синхронізовано із серверами Google. Ми можемо збирати статистичні дані про частоту пошуку слів, щоб покращити наші продукти. Ці дані збираються та використовуються відповідно до "<a href="https://www.google.com/policies/privacy">"Політики конфіденційності Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Щоб увімкнути функцію, додайте на пристрій обліковий запис Google"</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">"Клавіша зміни мови дозволяє змінювати методи введення"</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">"Показати індикатор переходу"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Показувати сигнал під час переходу від клавіш символів чи Shift"</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>
@@ -62,10 +67,7 @@
     <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_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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Ключ голосового вводу"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Способи голосового вводу не ввімкнено. Перейдіть у налаштування \"Мова та введення\"."</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="language_selection_title" msgid="3666971864764478269">"Мови"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Довідка й відгуки"</string>
+    <string name="select_language" msgid="5709487854987078367">"Мови"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Торкніться знову, щоб зберегти"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Торкніться тут, щоб зберегти"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Тема клавіатури"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Змінити обліковий запис"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Не вибрано облікових записів"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Зараз використовується <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ОК"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Скасувати"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Вийти"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Виберіть обліковий запис"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Англійська (Великобританія)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Англійська (США)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"іспанська (США)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Хінґліш"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"сербська (латиниця)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Англійська (Британія) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Англійська (США) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Іспанська (США) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Хінґліш (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"сербська (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (традиційна)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (кирилиця)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (латиниця)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (компактна)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Стандартна (латиниця)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Латиниця (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Латиниця (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Латиниця (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Латиниця (ПК)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Cмайли Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Тема клавіатури"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Персональні стилі введення"</string>
     <string name="add_style" msgid="6163126614514489951">"Додати стиль"</string>
     <string name="add" msgid="8299699805688017798">"Додати"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"Справді встановити цей файл для такої мови: <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Сталася помилка"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Затримка довгого натискання"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Тепер ви можете вводити текст у всіх своїх улюблених програмах за допомогою <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">"Відображати піктограму програми на панелі запуску"</string>
     <string name="app_name" msgid="6320102637491234792">"Постачальник словника"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Постачальник словника"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Служба словника"</string>
diff --git a/java/res/values-ur-rPK/strings-emoji-descriptions.xml b/java/res/values-ur-rPK/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..e6bbdcf
--- /dev/null
+++ b/java/res/values-ur-rPK/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"کاپی رائٹ کا نشان"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"رجسٹرڈ کا نشان"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"دوہرا فجائیہ نشان"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"فجائیہ سوالیہ نشان"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"ٹریڈ مارک کا نشان"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"معلومات کا ماخذ"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"دائیں بائیں تیر کا نشان"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"اوپر نیچے تیر کا نشان"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"شمال مغرب تیر کا نشان"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"شمال مشرق تیر کا نشان"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"جنوب مشرق تیر کا نشان"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"جنوب مغرب تیر کا نشان"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"ہک کے ساتھ بائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"ہک کے ساتھ دائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"گھڑی"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"ریت گھڑی"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"سیاہ دائیں اشارہ کرنے والا دوہرا مثلث"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"سیاہ بائیں اشارہ کرنے والا دوہرا مثلث"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"سیاہ اوپر اشارہ کرنے والا دوہرا مثلث"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"سیاہ نیچے اشارہ کرنے والا دوہرا مثلث"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"الارم گھڑی"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"سرکتی ریت کے ساتھ ریت گھڑی"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"‏مدور لاطینی بڑا حرف m"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"سیاہ چھوٹا مربع"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"سفید چھوٹا مربع"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"سیاہ دائیں اشارہ کرنے والا مثلث"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"سیاہ بائیں اشارہ کرنے والا مثلث"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"سفید متوسط مربع"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"سیاہ متوسط مربع"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"سفید متوسط چھوٹا مربع"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"سیاہ متوسط چھوٹا مربع"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"شعاعوں والا سیاہ سورج"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"بادل"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"سیاہ ٹیلی فون"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"چیک کے ساتھ بیلیٹ باکس"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"بارش کے قطروں کے ساتھ چھتری"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"گرم مشروب"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"سفید اوپر اشارہ کرنے والا انگشت شہادت"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"سفید مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"برج حمل"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"برج ثور"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"برج جوزا"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"برج سرطان"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"برج اسد"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"برج سنبلہ"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"برج میزان"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"برج عقرب"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"برج قوس"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"برج جدی"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"برج دلو"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"برج حوت"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"سیاہ اسپیڈ سوٹ"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"سیاہ کلب سوٹ"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"سیاہ ہارٹ سوٹ"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"سیاہ ڈائمنڈ سوٹ"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"گرم جھرنے"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"سیاہ یونیورسل ری سائیکلنگ کی علامت"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"پہیے والی کرسی کی علامت"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"لنگر"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"انتباہی نشان"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"زیادہ وولٹیج کا نشان"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"اوسط سفید دائرہ"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"اوسط سیاہ دائرہ"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"ساکر کی گیند"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"بیس بال"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"برف کے بغیر برفانی پتلا"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"بادل کے پیچھے سورج"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"ستاروں کا جھرمٹ"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"داخلہ ممنوع ہے کی علامت"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"چرچ"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"فوارہ"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"سوراخ میں پرچم"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"بادبانی کشتی"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"خیمہ"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"فیول پمپ"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"سیاہ قینچیاں"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"سفید بھاری چیک کا نشان"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"ہوائی جہاز"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"لفافہ"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"اٹھا ہوا مکہ"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"اٹھا ہوا ہاتھ"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"فتح والا ہاتھ"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"پنسل"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"سیاہ نب"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"بھاری چیک کا نشان"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"‏بھاری ضرب x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"پھلجھڑیاں"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"آٹھ آڑا ستارہ"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"آٹھ نکیلا سیاہ ستارہ"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"برف کا گالا"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"پھلجھڑی"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"کراس کا نشان"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"منفی مربع کراس کا نشان"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"سیاہ سوالیہ نشان زیور"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"سفید سوالیہ نشان زیور"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"سفید فجائیہ نشان زیور"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"بھاری فجائیہ نشان کی علامت"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"کافی سیاہ دل"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"بھاری جمع کا نشان"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"بھاری منفی کا نشان"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"بھاری تقسیم کا نشان"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"سیاہ دائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"خمیدہ لوپ"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"دوہرا خیمدہ لوپ"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"دائیں طرف اشارہ کرنے والا پھر اوپر مڑنے والا تیر کا نشان"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"دائیں طرف اشارہ کرنے والا پھر نیچے مڑنے والا تیر کا نشان"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"بائیں طرف سیاہ تیر کا نشان"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"اوپر کی طرف سیاہ تیر کا نشان"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"نیچے کی طرف سیاہ تیر کا نشان"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"سیاہ بڑا مربع"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"سفید بڑا مربع"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"سفید اوسط ستارہ"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"بھاری بڑا دائرہ"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"لہردار ڈیش"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"جزوی ردوبدل کا نشان"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"مدور آئیڈیوگراف مبارک باد"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"مدور آئیڈیوگراف راز"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"مہجونگ ٹائل سرخ اژدہا"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"تاش کا کالا جوکر"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"‏خون کی قسم A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"‏خون کی قسم B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"‏خون کی قسم O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"گاڑی کھڑی کرنے کا احاطہ"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"‏خون کی قسم AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"‏مربع کی علامت میں تحریر CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"‏مربع کی علامت میں تحریر cool"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"‏مربع کی علامت میں تحریر free"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"‏مربع کی علامت میں تحریر ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"‏مربع کی علامت میں تحریر new"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"‏مربع کی علامت میں تحریر N G"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"‏مربع کی علامت میں تحریر OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"‏مربع کی علامت میں تحریر SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"‏مربع کی علامت میں تحریر up!‎"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"‏مربع کی علامت میں تحریر vs"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"‏مربع کی علامت میں تحریر katakana"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"‏مربع کی علامت میں تحریر katakana سروس"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"مربع کی علامت میں تحریر آئیڈیوگراف بلا معاوضہ"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"مربع کی علامت میں تحریر آئیڈیوگراف محفوظ کردہ سیٹ"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"مربع کی علامت میں تحریر آئیڈیوگراف ممانعت"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"مربع کی علامت میں تحریر آئیڈیوگراف اسامی"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"مربع کی علامت میں تحریر آئیڈیوگراف قبولیت"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"مربع کی علامت میں تحریر آئیڈیوگراف مکمل تصرف"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"مربع کی علامت میں تحریر آئیڈیوگراف ادا شدہ"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"مربع کی علامت میں تحریر آئیڈیوگراف ماہانہ"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"مربع کی علامت میں تحریر آئیڈیوگراف ایپلیکیشن"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"مربع کی علامت میں تحریر آئیڈیوگراف ڈسکاؤنٹ"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"مربع کی علامت میں تحریر آئیڈیوگراف کاروبار جاری"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"مدور آئیڈیو گراف فائدہ"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"مدور آئیڈیو گراف قبولیت"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"طوفان"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"دھندلا"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"بند چھتری"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"ستاروں والی رات"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"پہاڑوں پر طلوع آفتاب"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"طلوع آفتاب"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"شام کے دھندلکے میں شہر کا نظارہ"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"عمارتوں پر غروب آفتاب"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"قوس قزح"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"رات میں پل"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"پانی کی لہر"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"آتش فشاں"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"کہکشاں"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"کرّہ ارض یوروپ افریقہ"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"کرّہ ارض امریکاز"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"کرّہ ارض ایشیا آسٹریلیا"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"نصف النہار کے ساتھ کرّہ"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"نئے چاند کی علامت"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"بڑھتے ہوئے ہلالی چاند کی علامت"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"پہلی چوتھائی کے چاند کی علامت"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"بڑھتے ہوئے نیم بریں چاند کی علامت"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"پورے چاند کی علامت"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"گھٹتے ہوئے نیم بریں چاند کی علامت"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"آخری چوتھائی چاند کی علامت"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"گھٹتے ہوئے ہلالی چاند کی علامت"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"ہلالی چاند"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"چہرے کے ساتھ نیا چاند"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"چہرے کے ساتھ پہلی چوتھائی کا چاند"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"چہرے کے ساتھ آخری چوتھائی کا چاند"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"چہرے کے ساتھ پورا چاند"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"چہرے کے ساتھ سورج"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"روشن ستارہ"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"شہاب ثاقب"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"شاہ بلوط"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"تخمی درخت"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"سدا بہار درخت"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"پت جھڑ کا درخت"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"کھجور کا درخت"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"ناگ پھنی"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"گل لالہ"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"چیری بلوسم"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"گلاب"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"گل خیرو"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"سورج مکھی"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"بلوسم"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"مکئی کی بالی"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"چاول کی بالی"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"ہرب"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"چار پتی کی سہ شاخہ"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"میپل کا پتا"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"گری ہوئی پتی"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"ہوا میں اڑنے والی پتی"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"مشروم"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"ٹماٹر"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"بینگن"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"انگور"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"خربوزہ"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"تربوز"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"طنجوی نارنگی"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"لیموں"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"کیلا"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"انناس"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"لال سیب"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"ہرا سیب"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"ناشپاتی"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"آڑو"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"چیریز"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"اسٹرابیری"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"ہیمبرگر"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"پیزا کا ٹکڑا"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"ہڈی کا گوشت"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"پولٹری کی ٹانگ"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"چاول کا خستہ"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"چاول کا گولہ"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"پکا ہوا چاول"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"کڑھی اور چاول"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"دخانی ڈونگا"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"اسپاگٹی"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"روٹی"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"فرینچ فرائیز"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"بھنا ہوا شکر قند"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"ڈنگو"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"اوڈین"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"سشی"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"بھنا ہوا جھینگا"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"گرداب کے ڈیزائن والا مچھلی کیک"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"نرم آئس کریم"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"تراشیدہ برف"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"آئس کریم"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"ڈونٹ"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"کوکی"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"چاکلیٹ بار"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"قندی"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"لالی پاپ"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"کسٹرڈ"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"شہد کا برتن"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"کیک کا ٹکڑا"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"بینٹو باکس"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"کھانے کا برتن"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"کھانا پکانا"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"کانٹا اور چھری"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"بغیر ہینڈل کے چائے کی پیالی"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"جاپانی شراب کی بوتل اور پیالی"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"وائن کا گلاس"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"کاک ٹیل کا گلاس"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"حاری مشروب"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"بیئر کا مگ"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"کھنکتے ہوئے بیئر کے مگ"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"بچے کی بوتل"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"ربن"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"لپٹا ہوا تحفہ"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"سالگرہ کا کیک"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"جیکو لالٹین"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"کرسمس کا درخت"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"فادر کرسمس"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"آتش بازی"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"آتش بازی کی پھل جھڑی"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"غبارہ"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"پارٹی پوپر"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"شیرینی کا گولہ"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"تناباتا کا درخت"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"خط کشیدہ پرچم"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"صنوبر کی سجاوٹ"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"جاپانی گڑیاں"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"سیم ماہی کا جھنڈا"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"ہوا کی جھنکار"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"چاند دیکھنے کی تقریب"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"اسکول کا بستہ"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"گریجویشن کی ٹوپی"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"جھولے کا گھوڑا"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"ہنڈولا"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"رولر کوسٹر"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"بنسی اور مچھلی"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"مائکروفون"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"مووی کیمرا"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"سنیما"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"ہیڈفون"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"فنکار کی تختی"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"اوپری ٹوپ"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"سرکس کا خیمہ"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"ٹکٹ"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"تالی تختہ"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"پرفارمنگ آرٹس"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"ویڈیو گیم"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"راست ضرب"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"سلاٹ مشین"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"بلیئرڈز"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"گیم ڈائی"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"باؤلنگ"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"پھول تاش"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"غنائی نوٹ"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"متعدد غنائی نوٹس"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"سیکسوفون"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"گٹار"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"غنائی کی بورڈ"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"نفیری"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"وائلن"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"غنائی اسکور"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"کمربند والی رواں شرٹ"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"ٹینس ریکیٹ اور گیند"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"اسکی اور اسکی بوٹ"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"باسکٹ بال اور ہوپ"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"چار خانہ دار پرچم"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"اسنو بورڈر"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"دوڑنے والا"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"موج تختے کا سوار"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"ٹرافی"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"گھڑ دوڑ"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"امریکی فٹبال"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"رگبی فٹبال"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"تیراک"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"گھر کی عمارت"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"باغ کے ساتھ گھر"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"دفتر کی عمارت"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"جاپانی ڈاک خانہ"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"یوروپی ڈاک خانہ"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"ہسپتال"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"بینک"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"آٹومیٹڈ ٹیلر مشین"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"ہوٹل"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"محبت کا ہوٹل"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"سہولت بخش اسٹور"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"اسکول"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"ڈپارٹمنٹ اسٹور"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"فیکٹری"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"ازاکایا لالٹین"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"جاپانی قلعہ"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"یوروپی قلعہ"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"چوہا"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"موش"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"بیل"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"ہندوستانی بھینس"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"گائے"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"چیتا"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"خرگوش"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"بلی"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"ڈریگن"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"مگرمچھ"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"وہیل"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"گھونگھا"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"سانپ"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"گھوڑا"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"مینڈھا"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"بکری"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"بھیڑ"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"بندر"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"مرغا"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"مرغ"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"کتا"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"سور"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"جنگلی سور"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"ہاتھی"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"اَکٹوپس"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"پیچدار گھونگھا"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"کھٹمل"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"چیونٹی"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"شہد کی مکھی"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"بھونرا"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"مچھلی"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"حاری مچھلی"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"بلوفش"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"کچھوا"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"انڈے سے نکلتا چوزہ"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"بے بی چک"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"سامنے کے رخ کا بچے کا رخسار"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"پرندہ"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"پینگوئن"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"کوآلا"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"پوڈل"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"یک کوہانی اونٹ"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"دو کوہانی اونٹ"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"ڈولفن"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"موش کا چہرہ"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"گائے کا چہرہ"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"باگھ کا چہرہ"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"خرگوش کا چہرہ"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"ڈریگن کا چہرہ"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"پھنکارنے والی وہیل"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"گھوڑے کا چہرہ"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"بندر کا چہرہ"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"کتے کا چہرہ"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"سور کا چہرہ"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"مینڈک کا چہرہ"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"موش کا چہرہ"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"بھیڑیے کا چہرہ"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"بھالو کا چہرہ"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"پانڈا کا چہرہ"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"سور کی ناک"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"پنجے کے چھاپ"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"آنکھیں"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"کان"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"ناک"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"منھ"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"زبان"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"سفید اوپر اشارہ کرنے والا الٹے ہاتھ کا اشاریہ"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"سفید نیچے اشارہ کرنے والا الٹے ہاتھ کا اشاریہ"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"سفید بائیں اشارہ کرنے والا الٹے ہاتھ کا اشاریہ"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"سفید دائیں اشارہ کرنے والا الٹے ہاتھ کا اشاریہ"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"مکہ بند ہاتھ کا نشان"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"لہراتے ہاتھ کا نشان"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"صحیح ہاتھ کا نشان"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"اظہار پسندیدگی کا نشان"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"اظہار ناپسندیدگی کا نشان"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"تالی بجاتے ہاتھوں کا نشان"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"کھلے ہاتھوں کا نشان"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"تاج"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"عورت کی ٹوپ"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"عینکیں"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"نکٹائی"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"ٹی شرٹ"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"جینس"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"لباس"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"چوغہ"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"بکنی"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"عورت کے کپڑے"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"پرس"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"ہینڈبیگ"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"پاؤچ"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"مردانہ جوتا"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"ایتھلیٹک جوتا"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"اونچی ایڑی کا جوتا"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"زنانہ سینڈل"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"زنانہ بوٹس"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"پیروں کے نشانات"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"یک رخی خاکہ میں جسمانی دھڑ"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"یک رخی خاکے میں جسمانی دھڑ"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"لڑکا"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"لڑکی"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"مرد"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"عورت"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"خاندان"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"ہاتھ پکڑے ہوئے مرد اور عورت"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"ہاتھ پکڑے ہوئے دو مرد"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"ہاتھ پکڑے ہوئے دو عورتیں"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"پولیس افسر"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"بنی کانوں والی عورت"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"گھونگھٹ والی دلہن"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"سنہرے بال والا شخص"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"لمبی مونچھوں والا والا آدمی"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"پگڑی والا آدمی"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"بڑی عمر کا آدمی"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"بڑی عمر کی عورت"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"بچہ"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"تعمیراتی کارکن"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"شہزادی"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"جاپانی دیو"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"جاپانی آسیب"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"بھوت"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"بچہ فرشتہ"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"غیر ارضی اجنبی مخلوق"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"اجنبی عفریت"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"شیطان کا بچہ"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"کھوپڑی"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"معلوماتی ڈیسک کا شخص"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"پہرہ دار"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"رقاصہ"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"لپ اسٹک"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"نیل پالش"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"چہرے کا مساج"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"بال کٹوانا"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"نائی کا کھمبا"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"سرنج"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"ٹکیہ"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"بوسے کا نشان"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"محبت نامہ"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"انگوٹھی"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"قیمتی پتھر"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"بوسہ"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"گلدستہ"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"دل والا جوڑا"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"شادی"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"دھڑکتا دل"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"ٹوٹا ہوا دل"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"دو دل"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"چمکنے والا دل"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"بڑھتا ہوا دل"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"تیر کے نشان والا دل"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"نیلا دل"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"ہرا دل"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"پیلا دل"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"جامنی دل"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"ربن والا دل"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"گھومتا ہوا دل"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"دل کی سجاوٹ"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"ہیرے کی شکل جس کے اندر ایک نکتہ ہو"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"بجلی کی روشنی کا بلب"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"غصہ کی علامت"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"بم"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"سونے کی علامت"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"ٹکر کی علامت"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"چھینٹ اڑانے والے پسینے کی علامت"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"چھوٹا قطرہ"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"ڈیش کی علامت"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"گندگی کا ڈھیر"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"جھکے ہوئے دو سروں والے پٹھے"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"چکر کی علامت"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"خطابی غبارہ"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"فکری غبارہ"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"سفید پھول"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"سو پوائنٹس کی علامت"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"رقم کا تھیلا"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"کرنسی کا تبادلہ"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"بھاری ڈالر کا نشان"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"کریڈٹ کارڈ"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"ین کے نشان والا بینک نوٹ"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"ڈالر کے نشان کے ساتھ بینک نوٹ"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"یورو کے نشان والا بینک نوٹ"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"پونڈ کے نشان والا بینک نوٹ"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"پروں کے ساتھ رقم"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"اوپر کی طرف رجحان اور ین کے نشان والا چارٹ"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"نشست"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"پرسنل کمپیوٹر"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"بریف کیس"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"منی ڈسک"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"فلاپی ڈسک"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"آپٹکل ڈسک"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"فائل فولڈر"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"فائل فولڈر کھولیں"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"پیچدار صفحہ"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"اوپر کے رخ والا صفحہ"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"کیلنڈر"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"قابل تراشہ کیلنڈر"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"کارڈ کا اشاریہ"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"اوپر کی طرف رجحان والا چارٹ"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"نیچے کی طرف رجحان والا چارٹ"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"بار چارٹ"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"کلپ بورڈ"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"پش پن"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"گول پش پن"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"پیپر کلپ"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"سیدھا رولر"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"مثلث نما رولر"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"بُک مارک کے ٹیبز"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"لیجر"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"نوٹ بک"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"آرائشی کور والی نوٹ بک"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"بند کتاب"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"کھلی کتاب"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"ہری کتاب"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"نیلی کتاب"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"نارنجی کتاب"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"کتابیں"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"نام کا بلّا"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"اسکرول کریں"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"میمو"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"ٹیلی فون کا ریسیور"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"پیجر"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"فیکس مشین"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"سٹیلائٹ انٹینا"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"عوامی خطاب کا لاؤڈ اسپیکر"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"خوش کن میگا فون"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"آؤٹ باکس ٹرے"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"ان باکس ٹرے"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"پیکیج"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"ای میل کی علامت"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"موصول ہونے والا لفافہ"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"لفافہ جس کے اوپر نیچے کے رخ میں تیر کا نشان ہو"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"گرے ہوئے پرچم والا بند میل باکس"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"اٹھے ہوئے پرچم والا بند میل باکس"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"اٹھے ہوئے پرچم والا کھلا میل باکس"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"گرے ہوئے پرچم والا کھلا میل باکس"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"پوسٹ باکس"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"ڈاک کا ہارن"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"اخبار"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"موبائل فون"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"موبائل فون کے بائیں جانب دائیں طرف والا تیر کا نشان"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"ارتعاش کی وض‏ع"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"موبائل فون آف"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"کوئی موبائل فونز نہیں ہیں"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"سلاخوں والا انٹینا"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"کیمرا"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"ویڈیو کیمرا"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"ٹیلی ویژن"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"ریڈیو"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"ویڈیو کیسیٹ"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"موڑے ہوئے دائیں طرف تیر کے نشانات"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"گھڑی کی سمت میں دائیں اور بائیں طرف کھلے مدور تیر کے نشانات"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"گھڑی کی سمت میں دائیں اور بائیں طرف کھلے مدور تیر کے نشانات نیز ایک مدور استرکاری"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"گھڑی کی سمت میں اوپر اور نیچے کھلے مدور تیر کے نشانات"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"خلاف گھڑی کی سمت میں نیچے اور اوپر کھلے مدور تیر کے نشانات"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"کم چمک کی علامت"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"زیادہ چمک کی علامت"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"منسوخی کے اسٹروک والا اسپیکر"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"اسپیکر"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"ایک صوتی لہر والا اسپیکر"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"تین صوتی لہروں والا اسپیکر"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"بیٹری"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"بجلی کا پلگ"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"بائیں جانب جھکا میگنفائنگ گلاس"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"دائیں جانب جھکا میگنفائنگ گلاس"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"روشنائی والے قلم کے ساتھ تالا"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"کلید والا بند تالا"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"کلید"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"تالا"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"کھلا تالا"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"گھنٹی"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"منسوخی کے اسٹروک والی گھنٹی"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"بُک مارک"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"لنک کی علامت"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"ریڈیو بٹن"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"پیچھے کے اوپر بائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"اختتام کے اوپر بائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"فجائیہ نشان کے ساتھ آن کے اوپر دائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"جلد کے اوپر دائیں طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"ٹاپ کے اوپر اوپر کی طرف تیر کا نشان"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"اٹھارہ سال سے کم کو اجازت نہیں کا نشان"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"کی کیپ دس"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"لاطینی بڑے حروف کیلئے ان پٹ کی علامت"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"لاطینی چھوٹے حروف کیلئے ان پٹ کی علامت"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"اعداد کیلئے ان پٹ کی علامت"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"علامات کیلئے ان پٹ علامت"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"لاطینی حروف کیلئے ان پٹ کی علامت"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"آگ"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"الیکٹرک مشعل"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"رینچ"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"ہتھوڑا"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"نٹ اور بولٹ"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"ہوچو"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"پستول"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"خورد بین"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"دور بین"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"بلوریں گیند"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"درمیانی نقطے کے ساتھ چھ کونوں والا ستارہ"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"مبتدی کیلئے جاپانی علامت"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"ترشول کا نشان"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"سیاہ مربع بٹن"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"سفید مربع بٹن"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"بڑا سرخ دائرہ"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"بڑا نیلا دائرہ"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"بڑا نارنجی ہیرا"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"بڑا نیلا ہیرا"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"چھوٹا نارنجی ہیرا"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"چھوٹا نیلا ہیرا"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"اوپر اشارہ کرنے والا سرخ مثلث"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"نیچے اشارہ کرنے والا سرخ مثلث"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"اوپر اشارہ کرنے والا چھوٹا سرخ مثلث"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"نیچے اشارہ کرنے والا چھوٹا سرخ مثلث"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"گھڑی کا رخ ایک بجے"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"گھڑی کا رخ دو بجے"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"گھڑی کا رخ تین بجے"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"گھڑی کا رخ چار بجے"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"گھڑی کا رخ پانچ بجے"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"گھڑی کا رخ چھ بجے"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"گھڑی کا رخ سات بجے"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"گھڑی کا رخ آٹھ بجے"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"گھڑی کا رخ نو بجے"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"گھڑی کا رخ دس بجے"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"گھڑی کا رخ گیارہ بجے"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"گھڑی کا رخ بارہ بجے"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"گھڑی کا رخ ایک تیس"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"گھڑی کا رخ دو تیس"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"گھڑی کا رخ تین تیس"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"گھڑی کا رخ چار تیس"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"گھڑی کا رخ پانچ تیس"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"گھڑی کا رخ چھ تیس"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"گھڑی کا رخ سات تیس"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"گھڑی کا رخ آٹھ تیس"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"گھڑی کا رخ نو تیس"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"گھڑی کا رخ دس تیس"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"گھڑی کا رخ گیارہ تیس"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"گھڑی کا رخ بارہ تیس"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"ماؤنٹ فیوجی"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"ٹوکیو ٹاور"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"مجسمۂ آزادی"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"جاپان کا یک رخی خاکہ"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"مویائی"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"کھسیانی ہنسی والا چہرہ"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"مسکراتی آنکھوں کے ساتھ ہنستا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"خوشی کے آنسوؤں والا چہرہ"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"کھلے منہ والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"کھلے منہ اور مسکراتی آنکھوں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"کھلے منہ اور ٹھنڈے پسینے والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"کھلے منہ اور سختی سے بند آنکھوں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"ہالہ والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"سینگوں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"پلک جھپکاتا چہرہ"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"مسکراتی آنکھوں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"مزیدار کھانے کا ذائقہ دینے والا چہرہ"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"پرسکون چہرہ"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"دل کی شکل کی آنکھوں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"دھوپ چشموں والا مسکراتا چہرہ"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"بناوٹی مسکراہٹ والا چہرہ"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"غیر جانبدار چہرہ"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"اظہار سے عاری چہرہ"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"اداس چہرہ"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"ٹھنڈے پسینے والا چہرہ"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"متفکر چہرہ"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"الجھا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"بے ترتیب چہرہ"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"چومنے والا چہرہ"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"بوسہ اچھالنے والا چہرہ"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"مسکراتی آنکھوں کے ساتھ چومنے والا چہرہ"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"بند آنکھوں کے ساتھ چومنے والا چہرہ"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"باہر نکلی زبان والا چہرہ"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"باہر نکلی زبان اور پلک جھپکتی آنکھ والا چہرہ"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"باہر نکلی زبان اور سختی سے بند آنکھوں والا چہرہ"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"مایوس چہرہ"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"فکرمند چہرہ"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"ناراض چہرہ"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"لٹکا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"روتا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"مستقل مزاج چہرہ"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"فتح کی ہیئت والا چہرہ"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"مایوس لیکن پرسکون چہرہ"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"کھلے منہ والا رنجیدہ چہرہ"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"غمزدہ چہرہ"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"خوفزدہ چہرہ"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"افسردہ چہرہ"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"خوابیدہ چہرہ"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"تھکا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"مضحکہ خیز چہرہ"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"زور سے رونے والا چہرہ"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"کھلے منہ والا چہرہ"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"مخفی چہرہ"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"کھلے منہ اور ٹھنڈے پسینے والا چہرہ"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"خوف سے چلانے والا چہرہ"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"حیران چہرہ"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"سرخی آمیز چہرہ"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"سوتا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"چکراتا ہوا چہرہ"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"بغیر منہ والا چہرہ"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"طبی ماسک والا چہرہ"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"مسکراتی آنکھوں کے ساتھ کھسیانی بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"خوشی کے آنسوؤں کے ساتھ بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"کھلے منہ کے ساتھ مسکراتی بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"دل کی شکل والی آنکھوں کے ساتھ مسکراتی بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"خمیدہ مسکراہٹ کے ساتھ بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"بند آنکھوں کے ساتھ چومنے والی بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"لٹکا ہوا بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"رونے والی بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"افسردہ بلی کا چہرہ"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"اچھے انداز سے عاری چہرہ"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"ٹھیک ہے انداز والا چہرہ"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"پوری طرح سے جھکا ہوا شخص"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"برا نہ دیکھنے والا بندر"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"برا نہ سننے والا بندر"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"برا نہ بولنے والا بندر"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"ایک ہاتھ اٹھائے ہوئے خوش شخص"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"جشن میں دونوں ہاتھ اٹھاتا ہوا شخص"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"رنجیدہ شخص"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"لٹکے ہوئے چہرے والا شخص"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"باندھے ہوئے ہاتھوں والا شخص"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"راکٹ"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"ہیلی کاپٹر"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"بھاپ انجن"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"ریلوے کار"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"ہائی اسپیڈ ٹرین"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"بلیٹ جیسی ناک والی ہائی اسپیڈ ٹرین"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"ٹرین"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"میٹرو"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"ہلکی ریل"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"اسٹیشن"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"ٹرام"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"ٹرام کار"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"بس"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"آنے والی بس"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"ٹرالی بس"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"بس اسٹاپ"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"منی بس"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"ایمبولینس"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"فائر انجن"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"پولیس کار"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"آنے والی پولیس کار"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"ٹیکسی"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"آنے والی ٹیکسی"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"آٹو موبائل"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"آنے والا آٹوموبائل"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"تفریحی گاڑی"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"ڈیلیوری ٹرک"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"جوڑوں سے بنی ہوئی لاری"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"ٹریکٹر"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"مونو ریل"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"ماؤنٹین ریلوے"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"معلق ریلوے"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"ماؤنٹین کیبل وے"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"ایریل ٹرام وے"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"بحری جہاز"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"ناؤ"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"اسپیڈ بوٹ"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"افقی ٹریفک لائٹ"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"عمودی ٹریفک کی روشنی"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"تعمیراتی نشان"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"پولیس کاروں کی گھومتی روشنی"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"چوکی پر مثلث نما پرچم"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"دروازہ"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"داخلہ ممنوع کا نشان"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"سگریٹ نوشی کی علامت"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"سگریٹ نوشی منع ہے کی علامت"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"گندگی کو اس کی جگہ میں ڈالیں کی علامت"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"گندگی نہ پھیلائیں کی علامت"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"برتن میں ڈالے جا سکنے والے پانی کی علامت"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"برتن میں نہ ڈالے جا سکنے والے پانی کی علامت"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"سائیکل"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"سائیکلوں کی اجازت نہیں"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"سائیکل سوار"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"پہاڑی سائیکل سوار"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"پیدل چلنے والے"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"پیدل چلنے والوں کی اجازت نہیں کی علامت"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"سڑک پار کرنے والے بچے"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"مردوں کی علامت"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"خواتین کی علامت"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"بیت الخلاء"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"بچے کی علامت"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"ٹوائلٹ"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"طہارت خانہ"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"شاور"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"غسل"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"باتھ ٹب"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"پاسپورٹ کنٹرول"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"کسٹمز"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"سامان کا دعوی"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"چھوٹا ہوا سامان"</string>
+</resources>
diff --git a/java/res/values-ur-rPK/strings-talkback-descriptions.xml b/java/res/values-ur-rPK/strings-talkback-descriptions.xml
index 5820372..fac64cc 100644
--- a/java/res/values-ur-rPK/strings-talkback-descriptions.xml
+++ b/java/res/values-ur-rPK/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"کوئی متن درج نہیں کیا گیا"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> کو ٹھیک کر کے <xliff:g id="CORRECTED_WORD">%3$s</xliff:g> کر دیتی ہے"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> خود کار اصلاح کو انجام دیتی ہے"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"کوئی تجویز نہیں"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"نامعلوم حرف"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"مزید علامات"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"‏بڑی I، اوپر ڈاٹ"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"نامعلوم علامت"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"‏نامعلوم emoji"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"اکتایا ہوا چہرہ"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"شرمندہ چہرہ"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"دھوپ کا چشمہ پہنا ہوا چہرہ"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"حیران چہرہ"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"چومنے والا چہرہ"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"تیوری چڑھایا ہوا چہرہ"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"متبادل حروف دستیاب ہیں"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"متبادل حروف کو مسترد کر دیا گیا ہے"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"متبادل تجاویز دستیاب ہیں"</string>
diff --git a/java/res/values-ur-rPK/strings.xml b/java/res/values-ur-rPK/strings.xml
index 8439cb5..074b702 100644
--- a/java/res/values-ur-rPK/strings.xml
+++ b/java/res/values-ur-rPK/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"کلید دبانے پر وائبریٹ کریں"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"کلید دبانے پر آواز"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"کلید دبانے پر پاپ اپ"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"ترجیحات"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"اکاؤنٹس اور رازداری"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"ظہور اور لے آؤٹس"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"اشارہ جاتی ٹائپنگ"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"متن کی اصلاح"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"جدید ترین"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"تھیم"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"الگ ہونے والا کی بورڈ فعال کریں"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"‏Google کی بورڈ کی مطابقت پذیری"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"مطابقت پذیری آن کر دی گئی"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"سبھی آلات پر اپنی ذاتی لغت کی مطابقت پذیری کریں"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"ابھی مطابقت پذیری کریں"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"کلاؤڈ ڈیٹا حذف کریں"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"‏Google سے آپ کے مطابقت پذیر ڈیٹا کو حذف کر دیتا ہے"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"آپ کا مطابقت پذیر ڈيٹا کلاؤڈ سے حذف ہو جائے گا۔ کیا آپ تیار ہیں؟"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"حذف کریں"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"منسوخ کریں"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"‏آپ کی ذاتی لغت کی مطابقت پذیری کی جائے گی اور Google سرورز میں اس کا بیک اپ لیا جائے گا۔ ہمارے پروڈکٹس کو بہتر بنانے میں مدد کرنے کیلئے الفاظ کی فریکوئنسی کے اعداد و شمار کی معلومات کو جمع کیا جا سکتا ہے۔ سبھی معلومات کی جمع آوری اور استعمال "<a href="https://www.google.com/policies/privacy">"Google کی رازداری کی پالیسی"</a>" کے مطابق ہوگا۔"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"‏یہ خصوصیت فعال کرنے کیلئے اس آلہ پر ایک Google اکاؤنٹ شامل کریں"</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">"زبان سوئچ کرنے کی کلید اندراج کے دیگر طریقوں کا بھی احاطہ کرتی ہے"</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">"سلائیڈ انڈیکیٹر کو دکھائیں"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"‏Shift یا علامت کلیدوں سے سلائیڈ کرتے ہوئے بصری اشارہ ڈسپلے کریں"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"صوتی ان پٹ کلید"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"کوئی صوتی اندراج کے طریقے فعال نہیں ہیں۔ زبان اور ان پٹ ترتیبات کو چیک کریں۔"</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="language_selection_title" msgid="3666971864764478269">"زبانیں"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"مدد اور تاثرات"</string>
+    <string name="select_language" msgid="5709487854987078367">"زبانیں"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"محفوظ کرنے کیلئے دوبارہ ٹچ کریں"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"محفوظ کرنے کیلئے یہاں ٹچ کریں"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"لغت دستیاب ہے"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"کی بورڈ تھیم"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"اکاؤنٹس سوئچ کریں"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"کوئی اکاؤنٹس منتخب نہیں کیے گئے"</string>
+    <string name="account_selected" msgid="2846876462199625974">"فی الحال <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g> استعمال کیا جا رہا ہے"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"ٹھیک ہے"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"منسوخ کریں"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"سائن آؤٹ کریں"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"استعمال کرنے کیلئے ایک اکاؤنٹ منتخب کریں"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"انگریزی (برطانیہ)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"انگریزی (امریکہ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"ہسپانوی (امریکہ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"ہنگلش"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"سربیائی (لاطینی)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"انگریزی (برطانیہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"انگریزی (امریکہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"ہسپانوی (امریکہ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"ہنگلش (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"سربیائی (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (روایتی)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (سیریلک)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (لاطینی)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (کمپیکٹ)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"کوئی زبان نہیں (الفابیٹ)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"‏حروف تہجی (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"‏حروف تہجی (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"‏حروف تہجی (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"‏حروف تہجی (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"کی بورڈ تھیم"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"حسب ضرورت ان پٹ اسٹائلز"</string>
     <string name="add_style" msgid="6163126614514489951">"اسٹائل شامل کریں"</string>
     <string name="add" msgid="8299699805688017798">"شامل کریں"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> کیلئے واقعی اس فائل کو انسٹال کریں؟"</string>
-    <string name="error" msgid="8940763624668513648">"ایک خرابی پیش آگئی"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"کلید کو دیر تک دبانے کی تاخیر"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"اب آپ <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">"لانچر میں ایپلیکیشن آئیکن کو ڈسپلے کریں"</string>
     <string name="app_name" msgid="6320102637491234792">"لغت فراہم کنندہ"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"لغت فراہم کنندہ"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"لغت سروس"</string>
diff --git a/java/res/values-uz-rUZ/strings-action-keys.xml b/java/res/values-uz-rUZ/strings-action-keys.xml
index 1bb617c..547388d 100644
--- a/java/res/values-uz-rUZ/strings-action-keys.xml
+++ b/java/res/values-uz-rUZ/strings-action-keys.xml
@@ -20,19 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for label_go_key (4033615332628671065) -->
-    <skip />
-    <!-- no translation found for label_next_key (5586407279258592635) -->
-    <skip />
-    <!-- no translation found for label_previous_key (1421141755779895275) -->
-    <skip />
-    <!-- no translation found for label_done_key (7564866296502630852) -->
-    <skip />
-    <!-- no translation found for label_send_key (482252074224462163) -->
-    <skip />
+    <string name="label_go_key" msgid="4033615332628671065">"OK"</string>
+    <string name="label_next_key" msgid="5586407279258592635">"Keyingi"</string>
+    <string name="label_previous_key" msgid="1421141755779895275">"Avvalgi"</string>
+    <string name="label_done_key" msgid="7564866296502630852">"Tayyor"</string>
+    <string name="label_send_key" msgid="482252074224462163">"Yuborish"</string>
     <string name="label_search_key" msgid="7965186050435796642">"Qidiruv"</string>
-    <!-- no translation found for label_pause_key (2225922926459730642) -->
-    <skip />
-    <!-- no translation found for label_wait_key (5891247853595466039) -->
-    <skip />
+    <string name="label_pause_key" msgid="2225922926459730642">"Pauza"</string>
+    <string name="label_wait_key" msgid="5891247853595466039">"Kutish"</string>
 </resources>
diff --git a/java/res/values-uz-rUZ/strings-appname.xml b/java/res/values-uz-rUZ/strings-appname.xml
new file mode 100644
index 0000000..8bc9cc1
--- /dev/null
+++ b/java/res/values-uz-rUZ/strings-appname.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<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 klaviaturasi (AOSP)"</string>
+    <string name="spell_checker_service_name" msgid="1254221805440242662">"Android imlo tekshirgichi (AOSP)"</string>
+    <string name="english_ime_settings" msgid="5760361067176802794">"Android klaviaturasi sozlamalari (AOSP)"</string>
+    <string name="android_spell_checker_settings" msgid="6123949487832861885">"Android imlo tekshirgichi sozlamalari (AOSP)"</string>
+</resources>
diff --git a/java/res/values-uz-rUZ/strings-config-important-notice.xml b/java/res/values-uz-rUZ/strings-config-important-notice.xml
new file mode 100644
index 0000000..3b27169
--- /dev/null
+++ b/java/res/values-uz-rUZ/strings-config-important-notice.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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="use_personalized_dicts_summary" msgid="590432261305469627">"Qurilma siz ko‘p yozgan ma’lumotlarni eslab qoladi"</string>
+</resources>
diff --git a/java/res/values-uz-rUZ/strings-emoji-descriptions.xml b/java/res/values-uz-rUZ/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..b1869e5
--- /dev/null
+++ b/java/res/values-uz-rUZ/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Mualliflik huquqi belgisi"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Ro‘yxatga olingan belgisi"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Qo‘sh undov belgisi"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Undov va so‘roq belgisi"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Savdo belgisi"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Ma’lumot"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Chapga va o‘ngga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Tepaga-pastga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Shimoli g‘arbga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Shimoli sharqqa qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Janubi sharqqa qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Janubi g‘arbga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Orqasida ilmog‘i bor chapga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Orqasida ilmog‘i bor o‘ngga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Qo‘l soati"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Qumsoat"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"O‘ngga qaragan qora qo‘sh uchburchak"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Chapga qarab turgan qora qo‘sh uchburchak"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Yuqoriga qaragan qora qo‘sh uchburchak"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Pastga qaragan qora qo‘sh uchburchak"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Uyg‘otkich soat"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Qum tushayotgan qumsoat"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Aylana ichida lotincha M harfi"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Qora kichkina kvadratcha"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Oq kichik kvadratcha"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"O‘ngga qaragan qora uchburchak"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Chapga qarab turgan qora uchburchak"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Oq o‘rtacha kvadrat"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Qora o‘rtacha kvadrat"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Oq o‘rtacha kichik kvadratcha"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Qora o‘rtacha kichik kvadratcha"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Nur taratayotgan qora quyosh"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Bulut"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Qora telefon"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Ichi belgilangan belgilash katakchasi"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Soyabon va yomg‘ir tomshilari"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Issiq ichimlik"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Ko‘rsatkich barmog‘i yuqoriga qarab turgan oq qo‘l"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Oq kulayotgan yuz"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Qo‘y"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Buzoq"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Egizaklar"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Qisqichbaqa"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Arslon"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Parizod"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Tarozi"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Chayon"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"O‘qotar"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Tog‘ echkisi"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Qovg‘a"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Baliq"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Qora qarg‘a kartasi"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Qora chillik kartasi"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Qora tappon kartasi"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Qora g‘ishtin kartasi"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Issiq buloq"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Qora universal qayta ishlash belgisi"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Nogironlar aravasi belgisi"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Langar"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Ogohlantiruvchi belgi"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Yuqori kuchlanish belgisi"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"O‘rtacha oq aylana"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"O‘rtacha qora doira"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Futbol to‘pi"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Beysbol"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Qorsiz qorbobo"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Bulut ortida quyosh"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Ilon tashuvchi"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Kirish mumkin emas"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Cherkov"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Favvora"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Teshikka o‘rnatilgan bayroq"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Yelkanli kema"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Chodir"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Yonilg‘i nasosi"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Qora qaychi"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Belgilash uchun oq katta belgi"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Samolyot"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Konvert"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Ko‘tarilgan musht"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Ko‘tarilgan qo‘l"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"V (victory – g‘alaba) harfini ko‘rsatib turgan qo‘l"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Qalam"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Qora pero"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Belgilash uchun to‘q belgi"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"To‘q X (ko‘paytiruv) belgisi"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Uchqunlar"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Sakkiz kegayli yulduzcha"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Sakkiz qirrali qora yulduz"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Qor parchasi"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Uchqun"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Xoch belgisi"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Qora kvadrat ichida oq xoch belgisi"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Naqshinkor qora so‘roq belgisi"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Naqshinkor oq savol belgisi"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Naqshinkor oq undov belgisi"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"To‘q undov belgisi"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"To‘q qora yurak"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"To‘q qo‘shuv belgisi"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"To‘q ayiruv belgisi"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"To‘q bo‘luv belgisi"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"O‘ngga qaragan qora ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Halqa"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Qo‘sh jingalak halqa"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Avval o‘ngga, keyin qayrilib yuqoriga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Avval o‘ngga, keyin qayrilib pastga qaragan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Chapga qaragan qora ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Yuqoriga qaragan qora ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Pastga qaragan qora ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Katta qora kvadrat"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Katta oq kvadrat"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"O‘rtacha oq yulduzcha"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Juda katta aylana"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"To‘lqinli chiziq"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Ovoz almashinuvi belgisi"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Aylana ichida iyeroglif yozuvidagi tabriklash belgisi"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Aylana ichida ieyroglif yozuvidagi maxfiy belgisi"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Majong toshidagi qizil ajdar"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"O‘yin kartasidagi qora joker"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A (II) qon guruhi"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B (III) qon guruhi"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"O (I) qon guruhi"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"To‘q kvadrat ichida P harfi"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB (IV) qon guruhi"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Kvadrat ichida CL harf birikmasi"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Kvadrat ichida COOL (ajoyib) yozuvi"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Kvadrat ichida FREE (bepul) yozuvi"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Kvadrat ichida ID (identifikator) yozuvi"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Kvadrat ichida NEW (yangi) yozuvi"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Kvadrat ichida N G (yaxshi emas) yozuvi"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Kvadrat ichida OK yozuvi"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Kvadrat ichida SOS (yordam) yozuvi"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Kvadrat ichida UP! (tepaga) yozuvi"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Kvadrat ichida VS (qarshi belgisi) yozuvi"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Kvadrat ichida katakana yozuvidagi KOKO (bu yerda) belgisi"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Kvadrat ichida katakana yozuvidagi SA (xizmat) belgisi"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Kvadrat ichida iyeroglif yozuvidagi “bepul” belgisi"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Kvadrat ichida iyeroglif yozuvidagi “band qilingan joy” belgisi"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Kvadrat ichida iyeroglif yozuvidagi “taqiqlangan” belgisi"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Kvadrat ichida iyeroglif yozuvidagi “bo‘sh” belgisi"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Kvadrat ichida iyeroglif yozuvidagi “tasdiqlash” belgisi"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Kvadrat ichida iyeroglif yozuvidagi “to‘la” belgisi"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Kvadrat ichida egalik qilish iyeroglifi"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Kvadrat ichida iyeroglif yozuvidagi “har oy” belgisi"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Kvadrat ichida iyeroglif yozuvidagi “ilova” belgisi"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Kvadrat ichida iyeroglif yozuvidagi “chegirma” belgisi"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Kvadrat ichida iyeroglif yozuvidagi “biznesda” belgisi"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Aylana ichida iyeroglif yozuvidagi “afzallik” belgisi"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Aylana ichida iyeroglif yozuvidagi “qabul qilish” belgisi"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"To‘fon"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Tumanli"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Yopiq soyabon"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Yulduzli tun"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Tog‘lar ortidan quyosh chiqishi"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Quyosh chiqishi"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Qosh qoraygandagi shahar manzarasi"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Binolar ortiga quyoshning botishi"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Kamalak"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Tundagi ko‘prik"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Suv to‘lqini"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Vulqon"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Somon yo‘li"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Globusda Yevropa va Afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Amerika tasvirlangan globus"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Globusda Osiyo va Avstraliya"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Meridian chiziqli globus"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Yangi oy ramzi"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Kattalashib boruvchi yarim oy ramzi"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Birinchi chorakdagi oy ramzi"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Kattalashib borayotgan qavariq oy ramzi"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"To‘lin oy ramzi"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Kichiklashib borayotgan qavariq oy"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"So‘nggi chorakdagi oy ramzi"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Kichiklashib borayotgan yarim oy ramzi"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Oy"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Ichida yuz tasvirlangan yangi oy"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Ichida yuz tasvirlangan birinchi chorakdagi oy"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Ichida yuz tasvirlangan so‘nggi chorakdagi oy"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Ichida yuz tasvirlangan to‘lin oy"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Ichida yuz tasvirlangan quyosh"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Porlayotgan yulduz"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Uchayotgan yulduz"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Kashtan yong‘og‘i"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Ko‘chat"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Archa"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Bargli daraxt"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Palma daraxti"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Kaktus"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Lola"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Gilos guli"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Atirgul"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Xitoy atirguli"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Kungaboqar"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Gul"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Makkajo‘xori dumbuli"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Sholi boshog‘i"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"O‘simlik"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"To‘rt yaproqli beda bargi"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Zarang bargi"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Xazon bargi"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Shamolda uchayotgan barg"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Qo‘ziqorin"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Pomidor"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Baqlajon"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Uzum"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Qovun"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Tarvuz"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Mandarin"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Limon"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Banan"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Ananas"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Qizil olma"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Ko‘k olma"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Nok"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Shaftoli"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Giloslar"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Qulupnay"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Gamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Pitsa bo‘lagi"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Suyakdagi go‘sht"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Parranda oyog‘i"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Guruchli pishiriq"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Yumaloqlangan guruch"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Pishirilgan guruch"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Guruchli karri"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Issiq lag‘mon"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Spagetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Non"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Qovurilgan fri-kartoshka"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Jigarli batat"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Sixdagi dengiz taomi"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Qovurilgan qisqichbaqa"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Girdob ko‘rinishidagi baliqli tort"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Yumshoq muzqaymoq"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Qirilgan muz"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Muzqaymoq"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Yog‘da ko‘pchib pishgan kulcha"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Pishiriq"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Shokolad bo‘lagi"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Konfet"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Obakidandon"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Tuxum va sutdan qilingan krem"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Asalli xum"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"To‘rt bo‘lagi"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Xonachali taom qutisi"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Bir qozon ovqat"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Taom tayyorlash"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Sanchqi va pichoq"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Tutqichsiz piyola"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Ko‘za va piyola"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Bir stakan vino"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Jomdagi kokteyl"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Tropik ichimlik"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Pivo qadahi"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Pivo stakanlarini bir-biriga urishtirish"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Chaqoloqlar suv idishi"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Lenta"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"O‘ralgan sovg‘a"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Tug‘ilgan kun torti"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Shamchiroqli oshqovoq"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Rojdestvo archasi"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Santa-Klaus"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Mushakbozlik"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Bengal olovi"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Havo shari"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Poqildoq"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Konfetti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Tanabata daraxti"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Bir-birini kesib o‘tgan bayroqlar"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Qarag‘ay bezagi"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Yapon qo‘g‘irchoqlari"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Zog‘orabaliq shaklida vimpel"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Shamol qo‘ng‘irog‘i"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Oy ko‘rish marosimi"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Maktab xaltasi"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Akademik bosh kiyim"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Ot o‘yini"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Charxpalak"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"G‘ildiratma hayinchak"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Qarmoq va baliq"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Mikrofon"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Kinokamera"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Kinoteatr"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Quloqchin"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Palitra"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Silindr shlyapa"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Sirk chodiri"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Chipta"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Poqildoqli numerator"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Teatr niqoblari"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Video o‘yin"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Mo‘ljalni urish"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"O‘yin avtomati"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Billiard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Shoshqol toshi"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Bouling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Gulli o‘yin kartalari"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Musiqiy nota"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Bir nechta musiqiy nota"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saksofon"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Gitara"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Musiqiy klaviatura"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Truba (karnaysimon musiqa asbobi)"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Skripka"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Musiqa kaliti"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Yuguruvchining maykasi"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Tennis raketkasi va koptokchasi"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Chang‘i va chang‘i oyoq kiyimi"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Basketbol to‘pi va halqa"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Katak-katak bayroq"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Snoubordchi"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Yuguruvchi"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Serfingchi"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Kubok"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Otchopar"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Amerikancha futbol"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Regbi"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Suzuvchi"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Uy"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Bog‘li uy"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Ofis binosi"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Yapon pochtamti"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Yevropa pochtamti"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Shifoxona"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Bank"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Bankomat"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Mehmonxona"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Sevgi mehmonxonasi"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Navbatchi do‘kon"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Maktab"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Univermag"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Zavod"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Izakaya fonusi"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Yapon qasri"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Yevropa qasri"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Kalamush"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Sichqon"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Buqa"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Buyvol"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Sigir"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Leopard"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Quyon"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Mushuk"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Ajdar"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Timsoh"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Kit"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Shilliq qurt"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Ilon"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Ot"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Qo‘chqor"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Echki"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Qo‘y"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Maymun"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Xo‘roz"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Jo‘ja"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"It"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Cho‘chqa"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Erkak cho‘chqa"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Fil"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Sakkizoyoq"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Chig‘anoq"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Taxtakana"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Chumoli"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Asalari"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Urg‘ochi qo‘ng‘iz"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Baliq"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Tropik baliq"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Qorni katta baliq"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Toshbaqa"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Tuxumdan chiqayotgan jo‘ja"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Jo‘ja"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Oldiga qarab turgan jo‘ja"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Qush"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Pingvin"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Pudel"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Bir o‘rkachli tuya"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Ikki o‘rkachli tuya"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Delfin"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Sichqon yuzi"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Sigirning boshi"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Yo‘lbars yuzi"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Quyon yuzi"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Mushukning boshi"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Ajdar yuzi"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Favvora hosil qilayotgan kit"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Ot yuzi"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Maymun yuzi"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Itning boshi"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Cho‘chqa yuzi"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Qurbaqa yuzi"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Og‘maxonning boshi"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Bo‘ri yuzi"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Ayiq yuzi"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Panda yuzi"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Cho‘chqa burni"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Panja izlari"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Ko‘zlar"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Quloq"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Burun"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Og‘iz"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Til"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Ko‘rsatkich barmog‘i orqa tomoni bilan yuqoriga qarab turgan oq qo‘l"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Ko‘rsatkich barmog‘i orqa tomoni bilan pastga qarab turgan oq qo‘l"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Ko‘rsatkich barmog‘i orqa tomoni bilan chapgaga qarab turgan oq qo‘l"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Ko‘rsatkich barmog‘i orqa tomoni bilan o‘ngga qarab turgan oq qo‘l"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Musht belgisi"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Shapaloq belgisi"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Qo‘lda qilingan OK belgisi"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Bosh barmoq tepaga qaragan belgi"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Bosh barmoq pastga qaragan belgi"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Qarsaklar"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Ochiq qo‘llar belgisi"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Toj"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Ayollar shlyapasi"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Ko‘zoynak"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Bo‘yinbog‘"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Futbolka"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Jinsi"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Libos"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Ayollar kiyimlari"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Hamyon"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Ayollar qo‘l sumkasi"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Kichik sumka"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Erkaklar tuflisi"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Krossovka"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Baland poshnali tufli"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Ayollar shippagi"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Ayollar etigi"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Oyoq izlari"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Bosh va yelkaning kontur chizig‘i"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Kontur suratli byustlar"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"O‘g‘il bola"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Qiz bola"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Erkak"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Ayol"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Oila"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Qo‘l ushlashib turgan erkak va ayol"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Qo‘l ushlashib turgan ikki erkak"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Qo‘l ushlashib turgan ikki ayol"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Politsiya xodimi"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Quyon quloqli ayol"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"To‘y romolidagi kelin"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Malla soch odam"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"An’anaviy xitoy bosh kiyimidagi erkak"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Salla kiygan erkak"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Qarir erkak"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Qari ayol"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Chaqaloq"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Quruvchi"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Malika"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Yapon odamxo‘ri"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Yapon ajinasi"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Arvoh"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Chaqaloq farishta"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"O‘zga sayyoralik"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"O‘zga sayyoralik maxluq"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Shayton"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Bosh suyagi"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Ma’lumotxona xodimi"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Qo‘riqchi"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Raqqos"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Lab bo‘yog‘i"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Tirnoq uchun lok"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Yuzni uqalash"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Soch qisqartirish"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Sartaroshlar ustuni"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Doripurkagich (shprits)"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Hapdori"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Bo‘sa belgisi"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Sevgi maktubi"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Uzuk"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Qimmatbaho tosh"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Bo‘sa olish"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Guldasta"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Juftlik va yurak"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Nikoh to‘yi"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Urayotgan yurak"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Singan yurak"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Ikkita yurak"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Chaqnayotgan yurak"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Kattalashayotgan yurak"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Yurak va kamon o‘qi"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Havorang yurak"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Yashil yurak"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Sariq yurak"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Binafsharang yurak"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Yurak va lenta"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Aylnayaotgan yuraklar"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Yurak bezagi"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Markazida nuqtasi bor romb"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Porlab turgan elektr lampa"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Jahl belgisi"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bomba"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Uyquga oid"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"To‘qnashuv belgisi"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Dona-dona ter"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Tomchi"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Zo‘r berish belgisi"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Tezak uyumi"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Baquvvat muskullar"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Bosh aylanish"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Nutq buluti"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"O‘y-xayol buluti"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Oq gul"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"100 ball belgisi"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Pul xalta"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Valyuta ayirboshlash"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Og‘ir dollar belgisi"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Kredit karta"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Iyena belgili banknota"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Dollar belgili banknota"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Yevro belgili banknota"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Funt-sterling belgili banknota"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Qanoti bor pul dastasi"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"O‘suvchi trend chizmasi va iyena belgisi"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"O‘rindiq"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Shaxsiy kompyuter"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Portfel"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Mini-disk"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Disketa"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Optik disk"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Fayl jildi"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Ochiq fayl jildi"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Gajakli sahifa"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Oldiga qarab turgan sahifa"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Taqvim"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Yirtiladigan taqvim"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Kartoteka"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"O‘suvchi trend chizmasi"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Kamayib boruvchi grafik"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Ustunli grafik"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Jild-planshet"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Kanselyariya bosma mixi"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Yumaloq bosma mix"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Qistirgich"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Chizg‘ich"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Uchburchak chizg‘ich"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Xatcho‘p oynalari"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ro‘yxatga olish kitobi"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Daftar"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Bezakli muqovali daftar"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Yopiq kitob"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Ochiq kitob"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Yashil kitob"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Havorang kitob"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"To‘q sariq kitob"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Kitoblar"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Ism yoziladigan nishon"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"O‘ralgan xat"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Qayd"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Telefon go‘shagi"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Peyjer"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Faks apparati"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Sun’iy yo‘ldoshli antenna"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"E’lon qiluvchi karnay"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Ovozni kuchaytiruvchi karnay"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Chiquvchi xat qutisi"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Kiruvchi xat qutisi"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"O‘ralgan sovg‘a"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"E-pochta belgisi"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Kiruvchi konvert"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Tepasida pastga qaragan ko‘rsatkichli chizig‘i bor konvert"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Pastga qaragan bayroqli yopiq pochta qutisi"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Bayroqchasi ko‘tarilgan yopiq pochta qutisi"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Yuqoriga ko‘tarilgan bayroqli ochiq pochta qutisi"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Pastga qaragan bayroqli ochiq pochta qutisi"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Pochta qutisi"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Shoxsimon nay"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Gazeta"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Mobil telefon"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Mobil telefon va uning chap tomonida unga qarab turgan ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Tebranish rejimi"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Mobil telefon o‘chirilgan"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Mobil telefondan foydalanish taqiqlanadi"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Signal darajasi ko‘rinib turgan antenna belgisi"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Kamera"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Videokamera"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Televizor"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Radio"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videokasseta"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Qayrilib bir-birini kesib o‘tgan va o‘ngga qaragan ikki ko‘rsatkichli chiziq"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Soat mili yo‘nalishda o‘ngga va chapga qarab turgan ochiq aylana ko‘rsatkichli chiziqlari"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Ostida aylana ichida 1 raqami bor hamda soat mili yo‘nalishida o‘ngga va chapga qaragan ochiq aylana chiziqlari"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Soat mili yo‘nalishda yuqoriga va pastga qarab turgan ochiq aylana ko‘rsatkichli chiziqlari"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Soat miliga teskari yo‘nalishda pastga va tepaga qaragan ochiq aylana chiziqlari"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Kam yorqinlik belgisi"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Yuqori darajadagi yorqinlik belgisi"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Taqiqlovchi chizig‘i bor karnay"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Karnay"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Bitta ovoz to‘lqinli karnay"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Uchta ovoz to‘lqinli karnay"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Batareya"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Elektr kabel sanchqisi"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Chapga qaragan lupa"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"O‘ngga qaragan lupa"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Siyoh ruchkali qulf"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Yopiq qulf va kalit"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Kalit"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Qulf"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Ochiq qulf"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Qo‘ng‘iroq"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Taqiqlovchi chizig‘i bor qo‘ng‘iroq"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Xatcho‘p"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Link belgisi"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Radio tugma"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Tepasida chapga qaragan ko‘rsatkichli chizig‘i bor BACK (orqaga) yozuvi"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Tepasida chapga qaragan ko‘rsatkichli chizig‘i bor END (oxiri) yozuvi"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Tepasida chapga va o‘ngga qaragan ko‘rsatkichli chizig‘i bor ON! yozuvi"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Tepasida o‘ngga qaragan ko‘rsatkichli chizig‘i bor SOON (tez kunda) yozuvi"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Tepasida yuqoriga qaraganda ko‘rsatkichli chizig‘i bor TOP (yuqoriga) yozuvi"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18 yoshga to‘lmaganlar uchun taqiqlanadi belgisi"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Ustiga 10 soni yozilgan tugma"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Lotincha bosh harflar uchun matn kiritish belgisi"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Lotincha kichik harflar uchun matn kiritish belgisi"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Raqamlar uchun matn kiritish belgisi"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Belgilar uchun matn kiritish belgisi"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Lotincha harflar uchun matn kiritish belgisi"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Olov"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Elektr fonar"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Gayka kaliti"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Bolg‘a"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Gayka va murvat"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Xanjar"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"To‘pponcha"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Mikroskop"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Teleskop"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Kristall donasi"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"O‘rtasida nuqtasi bor olti qirrali yulduz"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Boshlovchi darajasini bildiruvchi yaponcha belgi"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Uch ayrili nayza"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Qora kvadratli tugma"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Oq kvadrat tugma"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Katta qizil doira"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Katta havorang doira"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Katta to‘q sariq romb"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Katta havorang romb"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Kichkina to‘q sariq romb"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Kichkina havorang romb"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Yuqoriga qarab turgan qizil uchburchak"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Pastga qarab turgan qizil uchburchak"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Yuqoriga qarab turgan kichik qizil uchburchak"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Pastga qarab turgan kichik qizil uchburchak"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Birni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Ikkini ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Uchni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"To‘rtni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Beshni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Oltini ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Yettini ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Sakkizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"To‘qqizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"O‘nni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"O‘n birni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"O‘n ikkini ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Biru-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Ikkiyu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Uchu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"To‘rtu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Beshu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Oltiyu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Yettiyu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Sakkizu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"To‘qqizu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"O‘nu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"O‘n biru-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"O‘n ikkiyu-o‘ttizni ko‘rsatib turgan soat"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Fuji cho‘qqisi"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tokio teleminorasi"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Ozodlik haykali"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Yaponiyaning xaritadagi ko‘rinishi"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai haykali"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Tirjaygan yuz"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Katta tabassum, ko‘zlar qisilgan"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Quvonch ko‘z yoshlari"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Og‘zini katta ochib kulayotgan yuz"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Tabassum, og‘iz ochiq, ko‘zlar qisilgan"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Og‘zini katta ochib kulayotgan yuz va bir tomchi ko‘z yoshi"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Og‘zini katta ochib kulayotgan yuz va qattiq yumilgan ko‘zlar"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Tabassum, bosh ustida gardish"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Kulayotgan shayton"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Ko‘z qisish"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Tabassum va kulib turgan ko‘zlar"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Mazali taomni tatib ko‘rgan til"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Xotirjam yuz"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Tabassum va yurak shaklidagi ko‘zlar"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Ko‘zoynak taqqan hamda kulayotgan yuz"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Ahmoqona iljayish"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"His-tuyg‘usiz"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"His-tuyg‘usiz yuz"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Kulmayotgan yuz"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Ko‘z yoshi oqayotgan yuz"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"G‘amgin yuz"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Xijolat bo‘lish"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Xijolatli yuz"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Bo‘sa olayotgan yuz"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Bo‘sa yuborayotgan yuz"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Bo‘sa olayotgan yuz va kulayotgan ko‘zlar"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Bo‘sa olayotgan yuz va yumilgan ko‘zlar"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Tilni chiqarish"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Tili osilgan va ko‘zi qisilgan"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Tili osilgan va ko‘zlari qattiq yumilgan"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Hafsalasi pir bo‘lgan yuz"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Havotir olayotgan yuz"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Jahli chiqqan yuz"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Arazlagan yuz"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Yig‘layotgan yuz"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Matonatli yuz"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Shod-xurramlik"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Hafsalasi pir bo‘lgan, biroq xotirjam yuz"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Og‘zini katta ochib xo‘mraygan yuz"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"G‘am-tashvishli yuz"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Qo‘rqqan yuz"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Xorg‘in yuz"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Uyqusiragan yuz"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Charchagan yuz"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Afti burishgan yuz"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Xo‘ngrab yig‘lash"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Og‘zi katta ochiq yuz"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Sukut saqlash"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Og‘zi katta ochiq va yig‘layotgan yuz"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Qo‘rquvdan qichqirish"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Hayratlanayotgan yuz"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Yuzi qizargan"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Uxlayotgan yuz"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Boshi aylanayotgan yuz"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Og‘zi yo‘q yuz"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Tibbiy niqob taqqan yuz"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Ko‘zlarini qisgan holda kulayotgan mushuk"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Quvonch ko‘z yoshlariga ega mushukbashara yuz"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Og‘zi ochiq holatda kulayotgan mushuk"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Yurak shaklidagi ko‘zlarga ega kulib turgan mushukbashara yuz"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Tirjayib turgan mushuk"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Ko‘zlari yopiq holda bo‘sa olayotgan mushukbashara yuz"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Badjahl mushuk"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Yig‘layotgan mushukbashara yuz"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Charchagan mushuk"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Hech narsa ishorasini ko‘rsatib turgan yuz"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"OK ishorasini ko‘rsatib turgan yuz"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Chuqur ta’zim qilayotgan odam"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Ko‘zlari yumilgan maymun"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Yomonlikni eshitmaydigan maymun"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Yomonlikni gapirmaydigan maymun"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Bir qo‘lini ko‘tarib turgan xursand odam"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Ikki qo‘lini ko‘tarib nishonlayotgan odam"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Xo‘mraygan odam"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Jahli chiqqan odam"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Qo‘llari ko‘ksiga zanjir qilingan odam"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Raketa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Vertolyot"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Parovoz"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Temiryo‘l vagoni"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tezyurar poyezd"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Oldi uchli tezyurar poyezd"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Poyezd"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Tor izli temiryo‘l"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Bekat"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Tramvay"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tramvay"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Avtobus"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Yaqinlashayotgan avtobus"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Trolleybus"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Avtobus bekati"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Minibus"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Tez tibbiy yordam mashinasi"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"O‘t o‘chirish mashinasi"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Politsiya mashinasi"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Yaqinlashayotgan politsiya mashinasi"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taksi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Yaqinlashayotgan taksi"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Avtomobil"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Yaqinlashayotgan avtomobil"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Xordiq chiqarish avtomobili"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Buyurtmani yetkazib beruvchi yuk mashinasi"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Tirkamali yuk mashinasi"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Traktor"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Bir izli temiryo‘l"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Tog‘ temiryo‘li"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Vaqtinchalik to‘xtatilgan temiryo‘l"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Tog‘ dor yo‘li"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Havo tramvayi"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Kema"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Eshkakli qayiq"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Tezyurar kater"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Yotiq holatdagi svetofor"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Tik holatdagi svetofor"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Qurilish belgisi"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Plotsiya mashinasi mayog‘i"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Tayoqqa o‘rnatilgan uchburchak bayroq"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Eshik"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Kirish mumkin emas belgisi"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Chekish mumkin belgisi"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Chekish mumkin emas belgisi"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Axlatni o‘z joyiga tashlang belgisi"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Axlat tashlamang belgisi"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Ichimlik suvi belgisi"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Ichib bo‘lmaydigan suv belgisi"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Velosiped"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Velosipedlar mumkin emas"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Velosipedchi"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Tog‘ velosipedchisi"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Piyoda"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Piyodalar mumkin emas"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Bolalar o‘tish joyi"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Erkaklar uchun belgisi"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Ayollar hojatxonasi"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Pardoz-andoz xonasi"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Chaqaloq belgisi"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Hojatxona"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Hojatxona"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Dush"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Vanna"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Cho‘milish uchun tos"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Pasport nazorati"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Bojxona"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Yuklarni olish joyi"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Vaqtinchalik saqlash xonasida qoldirilgan yuk"</string>
+</resources>
diff --git a/java/res/values-uz-rUZ/strings-talkback-descriptions.xml b/java/res/values-uz-rUZ/strings-talkback-descriptions.xml
index 589790b..4a1e802 100644
--- a/java/res/values-uz-rUZ/strings-talkback-descriptions.xml
+++ b/java/res/values-uz-rUZ/strings-talkback-descriptions.xml
@@ -20,112 +20,69 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for spoken_use_headphones (4313642710742229868) -->
-    <skip />
-    <!-- no translation found for spoken_current_text_is (4240549866156675799) -->
-    <skip />
-    <!-- no translation found for spoken_no_text_entered (1711276837961785646) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct (8989324692167993804) -->
-    <skip />
-    <!-- no translation found for spoken_auto_correct_obscured (7769449372355268412) -->
-    <skip />
+    <string name="spoken_use_headphones" msgid="4313642710742229868">"Parolni eshitish uchun quloqchinni tiqing."</string>
+    <string name="spoken_current_text_is" msgid="4240549866156675799">"Kiritilgan matn: %s"</string>
+    <string name="spoken_no_text_entered" msgid="1711276837961785646">"Hech qanday matn kiritilmadi"</string>
+    <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> tugmasi bosilganda “<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>” so‘zi “<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>” so‘ziga o‘zgartiriladi"</string>
+    <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> tugmasi avtomatik tuzatishni amalga oshiradi"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Taklif yo‘q"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Noma’lum belgi"</string>
-    <!-- no translation found for spoken_description_shift (7209798151676638728) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift (3483198879916435717) -->
-    <skip />
-    <!-- no translation found for spoken_description_shift_shifted (3122704922642232605) -->
-    <skip />
-    <!-- no translation found for spoken_description_symbols_shift_shifted (5179175466878186081) -->
-    <skip />
-    <!-- no translation found for spoken_description_caps_lock (1224851412185975036) -->
-    <skip />
-    <!-- no translation found for spoken_description_delete (3878902286264983302) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_symbol (8244903740201126590) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_alpha (4081215210530031950) -->
-    <skip />
-    <!-- no translation found for spoken_description_to_numeric (4560261331530795682) -->
-    <skip />
-    <!-- no translation found for spoken_description_settings (7281251004003143204) -->
-    <skip />
-    <!-- no translation found for spoken_description_tab (8210782459446866716) -->
-    <skip />
-    <!-- no translation found for spoken_description_space (5908716896642059145) -->
-    <skip />
-    <!-- no translation found for spoken_description_mic (6153138783813452464) -->
-    <skip />
-    <!-- no translation found for spoken_description_emoji (7990051553008088470) -->
-    <skip />
-    <!-- no translation found for spoken_description_return (3183692287397645708) -->
-    <skip />
-    <!-- no translation found for spoken_description_search (5099937658231911288) -->
-    <skip />
-    <!-- no translation found for spoken_description_dot (5644176501632325560) -->
-    <skip />
-    <!-- no translation found for spoken_description_language_switch (6818666779313544553) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_next (431761808119616962) -->
-    <skip />
-    <!-- no translation found for spoken_description_action_previous (2919072174697865110) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_on (5107180516341258979) -->
-    <skip />
-    <!-- no translation found for spoken_description_shiftmode_locked (7307477738053606881) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol (111186851131446691) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_symbol_shift (4305607977537665389) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_alpha (4676004119618778911) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone (2061220553756692903) -->
-    <skip />
-    <!-- no translation found for spoken_description_mode_phone_shift (7879963803547701090) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_hidden (2313574218950517779) -->
-    <skip />
-    <!-- no translation found for announce_keyboard_mode (6698257917367823205) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date (6597407244976713364) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_date_time (3642804408726668808) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_email (1239682082047693644) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_im (3812086215529493501) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_number (5395042245837996809) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_phone (2486230278064523665) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_text (9138789594969187494) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_time (8558297845514402675) -->
-    <skip />
-    <!-- no translation found for keyboard_mode_url (8072011652949962550) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_recents (4185344945205590692) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_people (8414196269847492817) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_objects (6116297906606195278) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_nature (5018340512472354640) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_places (1163315840948545317) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_symbols (474680659024880601) -->
-    <skip />
-    <!-- no translation found for spoken_descrption_emoji_category_emoticons (456737544787823539) -->
-    <skip />
+    <string name="spoken_description_shift" msgid="7209798151676638728">"Yuqori registr tugmasi"</string>
+    <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Ko‘proq belgilar"</string>
+    <string name="spoken_description_shift_shifted" msgid="3122704922642232605">"Yuqori registr tugmasi"</string>
+    <string name="spoken_description_symbols_shift_shifted" msgid="5179175466878186081">"Belgilar"</string>
+    <string name="spoken_description_caps_lock" msgid="1224851412185975036">"Yuqori registr tugmasi"</string>
+    <string name="spoken_description_delete" msgid="3878902286264983302">"O‘chirish"</string>
+    <string name="spoken_description_to_symbol" msgid="8244903740201126590">"Belgilar"</string>
+    <string name="spoken_description_to_alpha" msgid="4081215210530031950">"Harflar"</string>
+    <string name="spoken_description_to_numeric" msgid="4560261331530795682">"Raqamlar"</string>
+    <string name="spoken_description_settings" msgid="7281251004003143204">"Sozlamalar"</string>
+    <string name="spoken_description_tab" msgid="8210782459446866716">"Tab tugmasi"</string>
+    <string name="spoken_description_space" msgid="5908716896642059145">"Bo‘sh joy"</string>
+    <string name="spoken_description_mic" msgid="6153138783813452464">"Ovoz bilan yozish"</string>
+    <string name="spoken_description_emoji" msgid="7990051553008088470">"Kulgichlar"</string>
+    <string name="spoken_description_return" msgid="3183692287397645708">"Kiritish"</string>
+    <string name="spoken_description_search" msgid="5099937658231911288">"Qidirish"</string>
+    <string name="spoken_description_dot" msgid="5644176501632325560">"Qora nuqta"</string>
+    <string name="spoken_description_language_switch" msgid="6818666779313544553">"Tilni o‘zgartirish"</string>
+    <string name="spoken_description_action_next" msgid="431761808119616962">"Keyingi"</string>
+    <string name="spoken_description_action_previous" msgid="2919072174697865110">"Avvalgi"</string>
+    <string name="spoken_description_shiftmode_on" msgid="5107180516341258979">"Yuqori registr yoqildi"</string>
+    <string name="spoken_description_shiftmode_locked" msgid="7307477738053606881">"Caps Lock yoqildi"</string>
+    <string name="spoken_description_mode_symbol" msgid="111186851131446691">"Belgilar rejimi"</string>
+    <string name="spoken_description_mode_symbol_shift" msgid="4305607977537665389">"Ko‘proq belgilar rejimi"</string>
+    <string name="spoken_description_mode_alpha" msgid="4676004119618778911">"Harflar rejimi"</string>
+    <string name="spoken_description_mode_phone" msgid="2061220553756692903">"Telefon rejimi"</string>
+    <string name="spoken_description_mode_phone_shift" msgid="7879963803547701090">"Telefon belgilari rejimi"</string>
+    <string name="announce_keyboard_hidden" msgid="2313574218950517779">"Klaviatura yashirildi."</string>
+    <string name="announce_keyboard_mode" msgid="6698257917367823205">"<xliff:g id="KEYBOARD_MODE">%s</xliff:g> rejimi yoqildi"</string>
+    <string name="keyboard_mode_date" msgid="6597407244976713364">"sana"</string>
+    <string name="keyboard_mode_date_time" msgid="3642804408726668808">"sana va vaqt"</string>
+    <string name="keyboard_mode_email" msgid="1239682082047693644">"e-pochta"</string>
+    <string name="keyboard_mode_im" msgid="3812086215529493501">"xabar kiritish"</string>
+    <string name="keyboard_mode_number" msgid="5395042245837996809">"raqam"</string>
+    <string name="keyboard_mode_phone" msgid="2486230278064523665">"telefon"</string>
+    <string name="keyboard_mode_text" msgid="9138789594969187494">"matn kiritish"</string>
+    <string name="keyboard_mode_time" msgid="8558297845514402675">"vaqt"</string>
+    <string name="keyboard_mode_url" msgid="8072011652949962550">"URL"</string>
+    <string name="spoken_descrption_emoji_category_recents" msgid="4185344945205590692">"So‘nggi ishlatilganlar"</string>
+    <string name="spoken_descrption_emoji_category_people" msgid="8414196269847492817">"Odamlar"</string>
+    <string name="spoken_descrption_emoji_category_objects" msgid="6116297906606195278">"Narsa-buyumlar"</string>
+    <string name="spoken_descrption_emoji_category_nature" msgid="5018340512472354640">"Tabiat"</string>
+    <string name="spoken_descrption_emoji_category_places" msgid="1163315840948545317">"Joylar"</string>
+    <string name="spoken_descrption_emoji_category_symbols" msgid="474680659024880601">"Belgilar"</string>
+    <string name="spoken_descrption_emoji_category_emoticons" msgid="456737544787823539">"Kulgichlar"</string>
     <string name="spoken_description_upper_case" msgid="4904835255229433916">"Bosh harf bilan yozilgan <xliff:g id="LOWER_LETTER">%s</xliff:g>"</string>
     <string name="spoken_letter_0049" msgid="4743162182646977944">"Katta I harfi"</string>
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Tepasida nuqtasi bor katta I harfi"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Noma’lum belgi"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Noma’lum kulgich"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Zerikkan"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Uyalgan"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Qora ko‘zoynak taqqan yuz"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Ajablangan"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Bo‘sa olayotgan yuz"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Xo‘mraygan"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Muqobil belgilar mavjud"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Muqobil belgilar tushirib qoldirildi"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Muqobil takliflar mavjud"</string>
diff --git a/java/res/values-uz-rUZ/strings.xml b/java/res/values-uz-rUZ/strings.xml
index 2b5da53..64261ff 100644
--- a/java/res/values-uz-rUZ/strings.xml
+++ b/java/res/values-uz-rUZ/strings.xml
@@ -20,355 +20,188 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for english_ime_input_options (3909945612939668554) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_title (5374120998125353898) -->
-    <skip />
-    <!-- no translation found for use_contacts_for_spellchecking_option_summary (8754413382543307713) -->
-    <skip />
-    <!-- no translation found for vibrate_on_keypress (5258079494276955460) -->
-    <skip />
-    <!-- no translation found for sound_on_keypress (6093592297198243644) -->
-    <skip />
-    <!-- no translation found for popup_on_keypress (123894815723512944) -->
-    <skip />
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list (4533689960308565519) -->
-    <skip />
-    <!-- no translation found for include_other_imes_in_language_switch_list_summary (840637129103317635) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key (5915478828318774384) -->
-    <skip />
-    <!-- no translation found for show_language_switch_key_summary (7343403647474265713) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview (6604262359510068370) -->
-    <skip />
-    <!-- no translation found for sliding_key_input_preview_summary (6340524345729093886) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_delay (6213164897443068248) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_no_delay (2096123151571458064) -->
-    <skip />
-    <!-- no translation found for key_preview_popup_dismiss_default_delay (2166964333903906734) -->
-    <skip />
-    <!-- no translation found for abbreviation_unit_milliseconds (8700286094028323363) -->
-    <skip />
-    <!-- no translation found for settings_system_default (6268225104743331821) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict (4435317977804180815) -->
-    <skip />
-    <!-- no translation found for use_contacts_dict_summary (6599983334507879959) -->
-    <skip />
-    <!-- no translation found for use_personalized_dicts (5167396352105467626) -->
-    <skip />
+    <string name="english_ime_input_options" msgid="3909945612939668554">"Matn kiritish sozlamalari"</string>
+    <string name="use_contacts_for_spellchecking_option_title" msgid="5374120998125353898">"Kontaktlarni qidirish"</string>
+    <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Imlo tekshirgich kontaktlaringizdagi qaydlardan foydalanadi"</string>
+    <string name="vibrate_on_keypress" msgid="5258079494276955460">"Tugma bosilganda tebranish"</string>
+    <string name="sound_on_keypress" msgid="6093592297198243644">"Tugma bosilganda ovoz"</string>
+    <string name="popup_on_keypress" msgid="123894815723512944">"Tugma bosilganda qalqib chiqish"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Shaxsiy sozlamalar"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Hisoblar va maxfiylik"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Tashqi ko‘rinishi va joylashuvi"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Imo-ishoralar bilan yozish"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Matnni tuzatish"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Qo‘shimcha"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Mavzu"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Ikkiga ajratiladigan klaviaturani yoqish"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google klaviaturasini sinx-sh"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Sinxronlash yoqildi"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Shaxsiy lug‘atingizni qurilmalar bo‘ylab sinxronlang"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Hozir sinxronlash"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Bulutdagi ma’lumotlarni o‘chirish"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Google xizmatlaridagi sinxronlangan ma’lumotlaringizni o‘chirib tashlaydi"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Sinxronlangan ma’lumotlaringiz o‘chib ketadi. Davom etsinmi?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"O‘chirish"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Bekor qilish"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Sizning shaxsiy lug\'atingiz Google serverlarida sinxronlashadi va zahiraga nusxalanadi. So‘zning qayta uchrash ko‘rsatkichi statistik ma’lumotlari, bizga mahsulotlarimiz sifatini oshirishda ko‘maklashish uchun to‘planishi mumkin. Barcha ma’lumotlar yig‘ilishi va foydalanishi "<a href="https://www.google.com/policies/privacy">" Google maxfiylik siyosati "</a>" shartlari bo‘yicha amalga oshadi."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Ushbu imkoniyatni yoqish uchun, iltimos, Google hisobingizni qo‘shing"</string>
+    <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Boshqa usullarga o‘tish"</string>
+    <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tilni o‘zgartirish tugmasi matn kiritish usulini ham o‘zgartiradi"</string>
+    <string name="show_language_switch_key" msgid="5915478828318774384">"Tilni o‘zgartirish tugmasi"</string>
+    <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Bir nechta matn kiritish tili mavjud bo‘lganda ko‘rsatilsin"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Yopilish uchun to‘xtalish"</string>
+    <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"To‘xtalishlarsiz"</string>
+    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Standart"</string>
+    <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> ms"</string>
+    <string name="settings_system_default" msgid="6268225104743331821">"Tizim standarti"</string>
+    <string name="use_contacts_dict" msgid="4435317977804180815">"Ismlarni taklif qilish"</string>
+    <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Kontaktlardagi ismlardan takliflar va tuzatishlarda foydalanilsin"</string>
+    <string name="use_personalized_dicts" msgid="5167396352105467626">"Moslashtirilgan takliflar"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ilovasini takomillashtirish"</string>
-    <!-- no translation found for use_double_space_period (8781529969425082860) -->
-    <skip />
-    <!-- no translation found for use_double_space_period_summary (6532892187247952799) -->
-    <skip />
-    <!-- no translation found for auto_cap (1719746674854628252) -->
-    <skip />
-    <!-- no translation found for auto_cap_summary (7934452761022946874) -->
-    <skip />
-    <!-- no translation found for edit_personal_dictionary (3996910038952940420) -->
-    <skip />
-    <!-- no translation found for configure_dictionaries_title (4238652338556902049) -->
-    <skip />
-    <!-- no translation found for main_dictionary (4798763781818361168) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions (8026799663445531637) -->
-    <skip />
-    <!-- no translation found for prefs_show_suggestions_summary (1583132279498502825) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_name (3219916594067551303) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_show_only_portrait_name (3859783767435239118) -->
-    <skip />
-    <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_title (5078480071057408934) -->
-    <skip />
-    <!-- no translation found for prefs_block_potentially_offensive_summary (2371835479734991364) -->
-    <skip />
-    <!-- no translation found for auto_correction (7630720885194996950) -->
-    <skip />
-    <!-- no translation found for auto_correction_summary (5625751551134658006) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_off (8470882665417944026) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_modest (8788366690620799097) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_aggressive (7319007299148899623) -->
-    <skip />
-    <!-- no translation found for auto_correction_threshold_mode_very_aggressive (1853309024129480416) -->
-    <skip />
-    <!-- no translation found for bigram_prediction (1084449187723948550) -->
-    <skip />
-    <!-- no translation found for bigram_prediction_summary (3896362682751109677) -->
-    <skip />
-    <!-- no translation found for gesture_input (826951152254563827) -->
-    <skip />
-    <!-- no translation found for gesture_input_summary (9180350639305731231) -->
-    <skip />
-    <!-- no translation found for gesture_preview_trail (3802333369335722221) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text (4443240334739381053) -->
-    <skip />
-    <!-- no translation found for gesture_floating_preview_text_summary (4472696213996203533) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware (2078291600664682496) -->
-    <skip />
-    <!-- no translation found for gesture_space_aware_summary (4371385818348528538) -->
-    <skip />
-    <!-- no translation found for voice_input (3583258583521397548) -->
-    <skip />
-    <!-- no translation found for voice_input_disabled_summary (8141750303464726129) -->
-    <skip />
-    <!-- no translation found for configure_input_method (373356270290742459) -->
-    <skip />
-    <!-- no translation found for language_selection_title (1651299598555326750) -->
-    <skip />
-    <!-- no translation found for send_feedback (1780431884109392046) -->
-    <skip />
-    <!-- no translation found for select_language (3693815588777926848) -->
-    <skip />
-    <!-- no translation found for hint_add_to_dictionary (573678656946085380) -->
-    <skip />
-    <!-- no translation found for has_dictionary (6071847973466625007) -->
-    <skip />
-    <!-- no translation found for keyboard_layout (8451164783510487501) -->
-    <skip />
-    <!-- no translation found for subtype_en_GB (88170601942311355) -->
-    <skip />
-    <!-- no translation found for subtype_en_US (6160452336634534239) -->
-    <skip />
-    <!-- no translation found for subtype_es_US (5583145191430180200) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_GB (1931018968641592304) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_en_US (8809311287529805422) -->
-    <skip />
-    <!-- no translation found for subtype_with_layout_es_US (510930471167541338) -->
-    <skip />
-    <!-- no translation found for subtype_generic_traditional (8584594350973800586) -->
-    <skip />
-    <!-- no translation found for subtype_generic_cyrillic (7486451947618138947) -->
-    <skip />
-    <!-- no translation found for subtype_generic_latin (9128716486310604145) -->
-    <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 />
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
-    <!-- no translation found for custom_input_styles_title (8429952441821251512) -->
-    <skip />
-    <!-- no translation found for add_style (6163126614514489951) -->
-    <skip />
-    <!-- no translation found for add (8299699805688017798) -->
-    <skip />
-    <!-- no translation found for remove (4486081658752944606) -->
-    <skip />
-    <!-- no translation found for save (7646738597196767214) -->
-    <skip />
-    <!-- no translation found for subtype_locale (8576443440738143764) -->
-    <skip />
-    <!-- no translation found for keyboard_layout_set (4309233698194565609) -->
-    <skip />
-    <!-- no translation found for custom_input_style_note_message (8826731320846363423) -->
-    <skip />
-    <!-- no translation found for enable (5031294444630523247) -->
-    <skip />
-    <!-- no translation found for not_now (6172462888202790482) -->
-    <skip />
-    <!-- no translation found for custom_input_style_already_exists (8008728952215449707) -->
-    <skip />
-    <!-- no translation found for prefs_key_longpress_timeout_settings (6102240298932897873) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_vibration_duration_settings (7918341459947439226) -->
-    <skip />
-    <!-- no translation found for prefs_keypress_sound_volume_settings (6027007337036891623) -->
-    <skip />
-    <!-- no translation found for prefs_read_external_dictionary (2588931418575013067) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_no_files_message (4947420942224623792) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_multiple_files_title (7637749044265808628) -->
-    <skip />
-    <!-- no translation found for read_external_dictionary_confirm_install_message (4782116251651288054) -->
-    <skip />
-    <!-- no translation found for error (8940763624668513648) -->
-    <skip />
-    <!-- no translation found for button_default (3988017840431881491) -->
-    <skip />
-    <!-- no translation found for setup_welcome_title (6112821709832031715) -->
-    <skip />
-    <!-- no translation found for setup_welcome_additional_description (8150252008545768953) -->
-    <skip />
-    <!-- no translation found for setup_start_action (8936036460897347708) -->
-    <skip />
-    <!-- no translation found for setup_next_action (371821437915144603) -->
-    <skip />
-    <!-- no translation found for setup_steps_title (6400373034871816182) -->
-    <skip />
-    <!-- no translation found for setup_step1_title (3147967630253462315) -->
-    <skip />
-    <!-- no translation found for setup_step1_instruction (2578631936624637241) -->
-    <skip />
-    <!-- no translation found for setup_step1_finished_instruction (10761482004957994) -->
-    <skip />
-    <!-- no translation found for setup_step1_action (4366513534999901728) -->
-    <skip />
-    <!-- no translation found for setup_step2_title (6860725447906690594) -->
-    <skip />
-    <!-- no translation found for setup_step2_instruction (9141481964870023336) -->
-    <skip />
-    <!-- no translation found for setup_step2_action (1660330307159824337) -->
-    <skip />
-    <!-- no translation found for setup_step3_title (3154757183631490281) -->
-    <skip />
-    <!-- no translation found for setup_step3_instruction (8025981829605426000) -->
-    <skip />
-    <!-- no translation found for setup_step3_action (600879797256942259) -->
-    <skip />
-    <!-- no translation found for setup_finish_action (276559243409465389) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon (5008028590593710830) -->
-    <skip />
-    <!-- no translation found for show_setup_wizard_icon_summary (4119998322536880213) -->
-    <skip />
-    <!-- no translation found for app_name (6320102637491234792) -->
-    <skip />
-    <!-- no translation found for dictionary_provider_name (3027315045397363079) -->
-    <skip />
-    <!-- no translation found for dictionary_service_name (6237472350693511448) -->
-    <skip />
-    <!-- no translation found for download_description (6014835283119198591) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_title (8091417676045693313) -->
-    <skip />
-    <!-- no translation found for dictionary_install_over_metered_network_prompt (3587517870006332980) -->
-    <skip />
-    <!-- no translation found for dictionary_settings_summary (5305694987799824349) -->
-    <skip />
-    <!-- no translation found for user_dictionaries (3582332055892252845) -->
-    <skip />
-    <!-- no translation found for default_user_dict_pref_name (1625055720489280530) -->
-    <skip />
-    <!-- no translation found for dictionary_available (4728975345815214218) -->
-    <skip />
-    <!-- no translation found for dictionary_downloading (2982650524622620983) -->
-    <skip />
-    <!-- no translation found for dictionary_installed (8081558343559342962) -->
-    <skip />
-    <!-- no translation found for dictionary_disabled (8950383219564621762) -->
-    <skip />
-    <!-- no translation found for cannot_connect_to_dict_service (9216933695765732398) -->
-    <skip />
-    <!-- no translation found for no_dictionaries_available (8039920716566132611) -->
-    <skip />
-    <!-- no translation found for check_for_updates_now (8087688440916388581) -->
-    <skip />
-    <!-- no translation found for last_update (730467549913588780) -->
-    <skip />
-    <!-- no translation found for message_updating (4457761393932375219) -->
-    <skip />
-    <!-- no translation found for message_loading (5638680861387748936) -->
-    <skip />
-    <!-- no translation found for main_dict_description (3072821352793492143) -->
-    <skip />
-    <!-- no translation found for cancel (6830980399865683324) -->
-    <skip />
-    <!-- no translation found for go_to_settings (3876892339342569259) -->
-    <skip />
-    <!-- no translation found for install_dict (180852772562189365) -->
-    <skip />
-    <!-- no translation found for cancel_download_dict (7843340278507019303) -->
-    <skip />
-    <!-- no translation found for delete_dict (756853268088330054) -->
-    <skip />
-    <!-- no translation found for should_download_over_metered_prompt (1583881200688185508) -->
-    <skip />
-    <!-- no translation found for download_over_metered (1643065851159409546) -->
-    <skip />
-    <!-- no translation found for do_not_download_over_metered (2176209579313941583) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_title (4583842811218581658) -->
-    <skip />
-    <!-- no translation found for dict_available_notification_description (1075194169443163487) -->
-    <skip />
-    <!-- no translation found for toast_downloading_suggestions (6128155879830851739) -->
-    <skip />
-    <!-- no translation found for version_text (2715354215568469385) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_menu_title (1254195365689387076) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_title (4096700390211748168) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_screen_title (5818914331629278758) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_more_options (5671682004887093112) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_less_options (2716586567241724126) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_dialog_confirm (4703129507388332950) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_option_name (6665558053408962865) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_option_name (3094731590655523777) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_locale_option_name (4738643440987277705) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_word_hint (4902434148985906707) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_add_shortcut_hint (2265453012555060178) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_edit_dialog_title (3765774633869590352) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_edit_title (6812255903472456302) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_context_menu_delete_title (8142932447689461181) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_empty_text (558499587532668203) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_all_languages (8276126583216298886) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_more_languages (7131268499685180461) -->
-    <skip />
-    <!-- no translation found for user_dict_settings_delete (110413335187193859) -->
-    <skip />
-    <!-- no translation found for user_dict_fast_scroll_alphabet (5431919401558285473) -->
-    <skip />
+    <string name="use_double_space_period" msgid="8781529969425082860">"Nuqta avtomatik qo‘yilsin"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Bo‘sh joy tugmasini ikki marta bosish nuqta va bo‘sh joy qoldirsin"</string>
+    <string name="auto_cap" msgid="1719746674854628252">"Avtomatik bosh harfga o‘tkazish"</string>
+    <string name="auto_cap_summary" msgid="7934452761022946874">"Har bir gapning birinchi so‘zini bosh harf bilan yozish"</string>
+    <string name="edit_personal_dictionary" msgid="3996910038952940420">"Shaxsiy lug‘at"</string>
+    <string name="configure_dictionaries_title" msgid="4238652338556902049">"Qo‘shimcha lug‘atlar"</string>
+    <string name="main_dictionary" msgid="4798763781818361168">"Asosiy lug‘at"</string>
+    <string name="prefs_show_suggestions" msgid="8026799663445531637">"To‘g‘rilash uchun variantlar"</string>
+    <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Yozayotganda taklif qilingan so‘zlar ko‘rsatilsin"</string>
+    <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Haqoratomuz so‘zlarni bloklash"</string>
+    <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Haqoratomuz so‘zlar taklif qilinmasin"</string>
+    <string name="auto_correction" msgid="7630720885194996950">"Avtomatik to‘g‘rilash"</string>
+    <string name="auto_correction_summary" msgid="5625751551134658006">"Bo‘sh joy yoki tinish belgisi xato yoz-n so‘z-ni avto. to‘g‘ri-di"</string>
+    <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"O‘chirish"</string>
+    <string name="auto_correction_threshold_mode_modest" msgid="8788366690620799097">"O‘rtacha"</string>
+    <string name="auto_correction_threshold_mode_aggressive" msgid="7319007299148899623">"Juda faol"</string>
+    <string name="auto_correction_threshold_mode_very_aggressive" msgid="1853309024129480416">"Juda faol"</string>
+    <string name="bigram_prediction" msgid="1084449187723948550">"Keyingi so‘zni taklif qilish"</string>
+    <string name="bigram_prediction_summary" msgid="3896362682751109677">"So‘zlarni taklif qilishda avval yozilgan so‘zga asoslanish"</string>
+    <string name="gesture_input" msgid="826951152254563827">"Imo-ishoralar bilan yozish"</string>
+    <string name="gesture_input_summary" msgid="9180350639305731231">"So‘zlarni barmog‘ingizni klaviaturadan uzmasdan yozing"</string>
+    <string name="gesture_preview_trail" msgid="3802333369335722221">"Chiziq chizish"</string>
+    <string name="gesture_floating_preview_text" msgid="4443240334739381053">"Taklif qil-n so‘z-ni ko‘rsatish"</string>
+    <string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"Matn kiritayotganda taklif qilingan so‘zlarni ko‘rsatish"</string>
+    <string name="gesture_space_aware" msgid="2078291600664682496">"Iboralarni uzluksiz kiritish"</string>
+    <string name="gesture_space_aware_summary" msgid="4371385818348528538">"Barmoqni har bir so‘zdan so‘ng bo‘sh joy qoldirish tugmasiga olib borish"</string>
+    <string name="voice_input" msgid="3583258583521397548">"Ovoz bilan kiritish tugmasi"</string>
+    <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Ovoz bilan yozish usuli yoqilmagan. Til va matn kiritish sozlamalarini tekshiring."</string>
+    <string name="configure_input_method" msgid="373356270290742459">"Matn kiritish usullarini sozlash"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Tillar"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Yordam va fikr-mulohaza"</string>
+    <string name="select_language" msgid="5709487854987078367">"Tillar"</string>
+    <string name="hint_add_to_dictionary" msgid="573678656946085380">"Saqlash uchun yana bosing"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Saqlash uchun bu yerga bosing"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"Lug‘at mavjud"</string>
+    <string name="keyboard_layout" msgid="8451164783510487501">"Klaviatura mavzusi"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Hisobni almashtirish"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Hech qanday hisob tanlanmadi"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Hozir foydalanilmoqda: <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Bekor qilish"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Chiqish"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Foydalanish uchun hisobni tanlang"</string>
+    <string name="subtype_en_GB" msgid="88170601942311355">"Ingliz (Buyuk Britaniya)"</string>
+    <string name="subtype_en_US" msgid="6160452336634534239">"Ingliz (AQSH)"</string>
+    <string name="subtype_es_US" msgid="5583145191430180200">"Ispan (AQSH)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Serb (Lotin)"</string>
+    <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Ingliz (Buyuk Britaniya) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Ingliz (AQSH) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Ispan (AQSH) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Serb (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (an’anaviy)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (ixcham)"</string>
+    <string name="subtype_no_language" msgid="7137390094240139495">"Til aniqlanmadi (lotin)"</string>
+    <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Lotin (QWERTY)"</string>
+    <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Lotin (QWERTZ)"</string>
+    <string name="subtype_no_language_azerty" msgid="8144348527575640087">"Lotin (AZERTY)"</string>
+    <string name="subtype_no_language_dvorak" msgid="1564494667584718094">"Lotin (Dvorak)"</string>
+    <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Lotin (Colemak)"</string>
+    <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Lotin (shaxsiy kompyuter)"</string>
+    <string name="subtype_emoji" msgid="7483586578074549196">"Kulgichlar"</string>
+    <string name="keyboard_theme" msgid="4909551808526178852">"Klaviatura mavzusi"</string>
+    <string name="custom_input_styles_title" msgid="8429952441821251512">"Moslashtirilgan usullar"</string>
+    <string name="add_style" msgid="6163126614514489951">"Uslub qo‘shish"</string>
+    <string name="add" msgid="8299699805688017798">"Qo‘shish"</string>
+    <string name="remove" msgid="4486081658752944606">"O‘chirish"</string>
+    <string name="save" msgid="7646738597196767214">"Saqlash"</string>
+    <string name="subtype_locale" msgid="8576443440738143764">"Til"</string>
+    <string name="keyboard_layout_set" msgid="4309233698194565609">"Joylashuv"</string>
+    <string name="custom_input_style_note_message" msgid="8826731320846363423">"Moslashtirilgan matn kiritish usulini yoqish lozim. Uni hozir yoqmoqchimisiz?"</string>
+    <string name="enable" msgid="5031294444630523247">"Yoqish"</string>
+    <string name="not_now" msgid="6172462888202790482">"Hozir emas"</string>
+    <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Xuddi shunday matn kiritish usuli allaqachon mavjud: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
+    <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Tugma bosilganda tebranish vaqti"</string>
+    <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Tugma bosilgandagi ovoz"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Uzoq bosib turish"</string>
+    <string name="button_default" msgid="3988017840431881491">"Standart"</string>
+    <string name="setup_welcome_title" msgid="6112821709832031715">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ilovasiga xush kelibsiz!"</string>
+    <string name="setup_welcome_additional_description" msgid="8150252008545768953">"Imo-ishoralar bilan yozish"</string>
+    <string name="setup_start_action" msgid="8936036460897347708">"Boshladik"</string>
+    <string name="setup_next_action" msgid="371821437915144603">"Keyingi qadam"</string>
+    <string name="setup_steps_title" msgid="6400373034871816182">"Sozlash: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_step1_title" msgid="3147967630253462315">"Yoqish: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="setup_step1_instruction" msgid="2578631936624637241">"Matn kiritishda foydalanish uchun Til va matn kiritish sozlamalarida “<xliff:g id="APPLICATION_NAME">%s</xliff:g>” bandiga belgi qo‘ying."</string>
+    <string name="setup_step1_finished_instruction" msgid="10761482004957994">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ilovasi allaqachon Til va matn kiritish sozlamalarida yoqilgan, shuning uchun keyingi qadamga o‘tish mumkin."</string>
+    <string name="setup_step1_action" msgid="4366513534999901728">"Sozlamalardan yoqish"</string>
+    <string name="setup_step2_title" msgid="6860725447906690594">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>: faollashtirish"</string>
+    <string name="setup_step2_instruction" msgid="9141481964870023336">"Keyin, joriy matn kiritish usuli sifatida “<xliff:g id="APPLICATION_NAME">%s</xliff:g>” ilovasini tanlang."</string>
+    <string name="setup_step2_action" msgid="1660330307159824337">"Matn kiritish usulini o‘zgartirish"</string>
+    <string name="setup_step3_title" msgid="3154757183631490281">"Tabriklaymiz, hammasi tayyor!"</string>
+    <string name="setup_step3_instruction" msgid="8025981829605426000">"Endi, matn kiritish uchun “<xliff:g id="APPLICATION_NAME">%s</xliff:g>” ilovasidan foydalanishingiz mumkin."</string>
+    <string name="setup_step3_action" msgid="600879797256942259">"Qo‘shimcha tillarni sozlash"</string>
+    <string name="setup_finish_action" msgid="276559243409465389">"Tugallandi"</string>
+    <string name="app_name" msgid="6320102637491234792">"Lug‘atlar ta’minotchisi"</string>
+    <string name="dictionary_provider_name" msgid="3027315045397363079">"Lug‘atlar ta’minotchisi"</string>
+    <string name="dictionary_service_name" msgid="6237472350693511448">"Lug‘atlar xizmati"</string>
+    <string name="download_description" msgid="6014835283119198591">"Lug‘atlarni yangilash ma’lumoti"</string>
+    <string name="dictionary_settings_title" msgid="8091417676045693313">"Qo‘shimcha lug‘atlar"</string>
+    <string name="dictionary_install_over_metered_network_prompt" msgid="3587517870006332980">"Lug‘at mavjud"</string>
+    <string name="dictionary_settings_summary" msgid="5305694987799824349">"Lug‘atlar uchun sozlamalar"</string>
+    <string name="user_dictionaries" msgid="3582332055892252845">"Foydalanuvchi lug‘atlari"</string>
+    <string name="default_user_dict_pref_name" msgid="1625055720489280530">"Foydalanuvchi lug‘ati"</string>
+    <string name="dictionary_available" msgid="4728975345815214218">"Lug‘at mavjud"</string>
+    <string name="dictionary_downloading" msgid="2982650524622620983">"Hozirda yuklab olinmoqda"</string>
+    <string name="dictionary_installed" msgid="8081558343559342962">"O‘rnatilgan"</string>
+    <string name="dictionary_disabled" msgid="8950383219564621762">"O‘rnatilgan, o‘chirib qo‘yilgan"</string>
+    <string name="cannot_connect_to_dict_service" msgid="9216933695765732398">"Ulanib bo‘lmadi"</string>
+    <string name="no_dictionaries_available" msgid="8039920716566132611">"Lug‘at mavjud emas"</string>
+    <string name="check_for_updates_now" msgid="8087688440916388581">"Yangilash"</string>
+    <string name="last_update" msgid="730467549913588780">"So‘nggi marta yangilandi"</string>
+    <string name="message_updating" msgid="4457761393932375219">"Yangilanish mavjudligi tekshirilmoqda"</string>
+    <string name="message_loading" msgid="5638680861387748936">"Yuklanmoqda…"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"Asosiy lug‘at"</string>
+    <string name="cancel" msgid="6830980399865683324">"Bekor qilish"</string>
+    <string name="go_to_settings" msgid="3876892339342569259">"Sozlamalar"</string>
+    <string name="install_dict" msgid="180852772562189365">"O‘rnatish"</string>
+    <string name="cancel_download_dict" msgid="7843340278507019303">"Bekor qilish"</string>
+    <string name="delete_dict" msgid="756853268088330054">"O‘chirish"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Mobil telefoningizda tanlangan til uchun lug‘at mavjud.&lt;br/&gt; Matnlarni tezkor va bexato kiritish uchun <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> lug‘atini &lt;b&gt;yuklab olish&lt;/b&gt; tavsiya etiladi. &lt;br/&gt; &lt;br/&gt; Agar sizda mobil internet uchun &lt;b&gt;cheksiz internet tarifi&lt;/b&gt; o‘rnatilgan bo‘lsa, lug‘atni 3G orqali yuklab olishingiz mumkin (bir-ikki daqiqa vaqt oladi).&lt;br/&gt;Agar tarif rejangiz tafsilotlarini bilmasangiz, u holda Wi-Fi orqali yuklab olgan ma’qul (yuklab olish avtomatik ravishda boshlanadi).&lt;br/&gt; &lt;br/&gt; Maslahat: Lug‘at qo‘shish, o‘chirish yoki sozlash uchun mobil qurilmangizning &lt;b&gt;Sozlamalar&lt;/b&gt; menyusidan &lt;b&gt;Til va matn kiritish&lt;/b&gt; bo‘limiga o‘ting."</string>
+    <string name="download_over_metered" msgid="1643065851159409546">"Yuklab olish (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> MB)"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"Wi-Fi orqali yuklab olish"</string>
+    <string name="dict_available_notification_title" msgid="4583842811218581658">"Lug‘at mavjud: <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
+    <string name="dict_available_notification_description" msgid="1075194169443163487">"Ko‘rib chiqish va yuklab olish uchun bosing"</string>
+    <string name="toast_downloading_suggestions" msgid="6128155879830851739">"Yuklab olinmoqda: <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> tili uchun so‘zlarni taklif qilish xususiyati tez orada tayyor bo‘ladi."</string>
+    <string name="version_text" msgid="2715354215568469385">"<xliff:g id="VERSION_NUMBER">%1$s</xliff:g> versiyasi"</string>
+    <string name="user_dict_settings_add_menu_title" msgid="1254195365689387076">"Qo‘shish"</string>
+    <string name="user_dict_settings_add_dialog_title" msgid="4096700390211748168">"Lug‘atga qo‘shish"</string>
+    <string name="user_dict_settings_add_screen_title" msgid="5818914331629278758">"Ibora"</string>
+    <string name="user_dict_settings_add_dialog_more_options" msgid="5671682004887093112">"Ko‘proq soz-lar"</string>
+    <string name="user_dict_settings_add_dialog_less_options" msgid="2716586567241724126">"Kamroq sozlamalar"</string>
+    <string name="user_dict_settings_add_dialog_confirm" msgid="4703129507388332950">"OK"</string>
+    <string name="user_dict_settings_add_word_option_name" msgid="6665558053408962865">"So‘z:"</string>
+    <string name="user_dict_settings_add_shortcut_option_name" msgid="3094731590655523777">"Tezkor tugmalar:"</string>
+    <string name="user_dict_settings_add_locale_option_name" msgid="4738643440987277705">"Til:"</string>
+    <string name="user_dict_settings_add_word_hint" msgid="4902434148985906707">"So‘zni kiriting"</string>
+    <string name="user_dict_settings_add_shortcut_hint" msgid="2265453012555060178">"Ibora uchun yorliq (ixtiyoriy)"</string>
+    <string name="user_dict_settings_edit_dialog_title" msgid="3765774633869590352">"So‘zni tahrirlash"</string>
+    <string name="user_dict_settings_context_menu_edit_title" msgid="6812255903472456302">"Tahrirlash"</string>
+    <string name="user_dict_settings_context_menu_delete_title" msgid="8142932447689461181">"O‘chirish"</string>
+    <string name="user_dict_settings_empty_text" msgid="558499587532668203">"Foydalanuvchi lug‘atida hali hech narsa yo‘q. Yangi so‘z qo‘shish uchun Qo‘shish (+) tugmasini bosing."</string>
+    <string name="user_dict_settings_all_languages" msgid="8276126583216298886">"Barcha tillar uchun"</string>
+    <string name="user_dict_settings_more_languages" msgid="7131268499685180461">"Ko‘proq tillar…"</string>
+    <string name="user_dict_settings_delete" msgid="110413335187193859">"O‘chirish"</string>
+    <string name="user_dict_fast_scroll_alphabet" msgid="5431919401558285473">" ABDEFGHIJKLMNOPQRSTUVXYZO‘G‘SHCH"</string>
 </resources>
diff --git a/java/res/values-v19/spinner-style.xml b/java/res/values-v19/spinner-style.xml
new file mode 100644
index 0000000..a699905
--- /dev/null
+++ b/java/res/values-v19/spinner-style.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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">
+    <!-- Until KitKat (API 19), {@link android.widget.Spinner} of dialog mode in a Dialog can't
+         handle orientation change correctly. Using dropdown mode avoids the issue.
+         This file overrides values/spinner-style.xml on KitKat and up. -->
+    <style name="additionalSubtypeSpinnerStyle">
+        <item name="android:spinnerMode">dialog</item>
+    </style>
+</resources>
diff --git a/java/res/values-v21/platform-theme.xml b/java/res/values-v21/platform-theme.xml
index 2a54798..58763fb 100644
--- a/java/res/values-v21/platform-theme.xml
+++ b/java/res/values-v21/platform-theme.xml
@@ -20,6 +20,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="platformActivityTheme" parent="@android:style/Theme.DeviceDefault.Light" />
-    <style name="platformSettingsTheme" parent="@android:style/Theme.DeviceDefault.Light" />
+    <style name="platformSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings" />
     <style name="platformDialogTheme" parent="@android:style/Theme.DeviceDefault.Light.Dialog" />
 </resources>
diff --git a/java/res/values-v21/themes-lxx.xml b/java/res/values-v21/themes-lxx.xml
new file mode 100644
index 0000000..5a6017c
--- /dev/null
+++ b/java/res/values-v21/themes-lxx.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style
+        name="InputView.LXX"
+        parent="InputView"
+    >
+        <item name="android:elevation">8dp</item>
+    </style>
+</resources>
diff --git a/java/res/values-vi/strings-emoji-descriptions.xml b/java/res/values-vi/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..492c726
--- /dev/null
+++ b/java/res/values-vi/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Biểu tượng bản quyền"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Biểu tượng đã đăng ký"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Hai dấu chấm than"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Dấu chấm than dấu hỏi"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Biểu tượng nhãn hiệu thương mại"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Nguồn thông tin"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Mũi tên trái phải"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Mũi tên lên xuống"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Mũi tên tây bắc"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Mũi tên đông bắc"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Mũi tên đông nam"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Mũi tên tây nam"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Mũi tên sang trái có móc"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Mũi tên sang phải có móc"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Đồng hồ"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Đồng hồ cát"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Hai tam giác màu đen trỏ sang phải"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Hai tam giác màu đen trỏ sang trái"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Hai tam giác màu đen trỏ lên"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Hai tam giác màu đen trỏ xuống"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Đồng hồ báo thức"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Đồng hồ cát với cát đang chảy"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Chữ m hoa trong vòng tròn"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Hình vuông đen nhỏ"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Hình vuông trắng nhỏ"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Hình tam giác đen trỏ sang phải"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Hình tam giác đen trỏ sang trái"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Hình vuông trắng trung bình"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Hình vuông đen trung bình"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Hình vuông trắng nhỏ trung bình"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Hình vuông đen nhỏ trung bình"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Mặt trời màu đen với các tia"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Mây"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Điện thoại màu đen"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Hộp phiếu có dấu kiểm"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Ô với giọt mưa"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Đồ uống nóng"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Ngón trỏ chỉ lên màu trắng"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Mặt cười màu trắng"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"Cung Bạch dương"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"Cung Kim ngưu"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"Cung Song sinh"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"Cung Cự giải"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"Cung Sư tử"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"Cung Xử nữ"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"Cung Thiên bình"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"Cung Bọ cạp"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"Cung Nhân mã"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"Cung Ma kết"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"Cung Bảo bình"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"Cung Song ngư"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Quân bích đen"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Quân tép đen"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Quân cơ đen"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Quân rô đen"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Suối nước nóng"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Biểu tượng tái chế chung màu đen"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Biểu tượng xe lăn"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Mỏ neo"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Biển báo nguy hiểm"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Biểu tượng điện cao thế"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Vòng tròn trắng trung bình"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Vòng tròn đen trung bình"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Quả bóng đá"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"Bóng chày"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Người tuyết không có tuyết"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Mặt trời phía sau đám mây"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"Chòm sao"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Cấm vào"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Nhà thờ"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Vòi phun nước"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Cờ trong lỗ"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Thuyền buồm"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Lều"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Bơm nhiên liệu"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Kéo đen"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Dấu kiểm trắng đậm"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Máy bay"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Phong bì"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Giơ quả đấm"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Giơ tay"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Tay chữ V"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Bút chì"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Đầu ngòi bút đen"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Dấu kiểm đậm"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"Dấu nhân x đậm"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Tia lửa"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Dấu hoa thị 8 que"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Sao màu đen 8 que"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Bông tuyết"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Tia lửa"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Dấu gạch chéo"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Biểu tượng dấu gạch chéo hình vuông"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Hình trang trí dấu hỏi màu đen"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Hình trang trí dấu hỏi màu trắng"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Hình trang trí dấu cảm thán màu trắng"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Biểu tượng dấu cảm thán đậm"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Trái tim buồn phiền"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Dấu cộng đậm"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Dấu trừ đậm"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Dấu chia đậm"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Mũi tên sang phải màu đen"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Vòng xoắn"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Hai vòng xoắn"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Mũi tên trỏ sang phải rồi uốn cong lên trên"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Mũi tên trỏ sang phải rồi uốn cong xuống dưới"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Mũi tên đen trỏ sang trái"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Mũi tên đen trỏ lên"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Mũi tên đen trỏ xuống"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Hình vuông lớn màu đen"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Hình vuông lớn màu trắng"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Sao trắng trung bình"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Vòng tròn đậm lớn"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"Nét lượn sóng"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Dấu biến thiên từng phần"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Biểu tượng chữ tượng hình \"Chúc mừng\" vòng tròn"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Biểu tượng chữ tượng hình \"Bí mật\" vòng tròn"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Rồng đỏ xếp tầng Mahjong"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Chơi bài phăng teo đen"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Nhóm máu A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Nhóm máu B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Nhóm máu O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Bãi đỗ xe"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Nhóm máu AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"Biểu tượng CL hình vuông"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Biểu tượng \"Cool\" hình vuông"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Biểu tượng \"Free\" hình vuông"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"Biểu tượng \"ID\" hình vuông"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Biểu tượng \"New\" hình vuông"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"Biểu tượng \"N G\" hình vuông"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"Biểu tượng \"OK\" hình vuông"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"Biểu tượng \"SOS\" hình vuông"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Biểu tượng \"Up!\" hình vuông"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Biểu tượng \"VS\" hình vuông"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"Biểu tượng \"Here\" (theo kiểu katakana) hình vuông"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Biểu tượng \"Service\" (theo kiểu katakana) hình vuông"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Biểu tượng chữ tượng hình \"Miễn phí\" hình vuông"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Biểu tượng chữ tượng hình \"Chỗ ngồi đặt trước\" hình vuông"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Biểu tượng chữ tượng hình \"Cấm\" hình vuông"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Biểu tượng chữ tượng hình \"Còn trống\" hình vuông"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Biểu tượng chữ tượng hình \"Chấp nhận\" hình vuông"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Biểu tượng chữ tượng hình \"Hết chỗ\" hình vuông"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"Biểu tượng chữ tượng hình \"Trả tiền\" hình vuông"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"Biểu tượng chữ tượng hình \"Hàng tháng\" hình vuông"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Biểu tượng chữ tượng hình \"Đơn đăng ký\" hình vuông"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Biểu tượng chữ tượng hình \"Giảm giá\" hình vuông"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"Biểu tượng chữ tượng hình \"Doanh nghiệp\" hình vuông"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Biểu tượng chữ tượng hình \"Thuận lợi\" hình tròn"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Biểu tượng chữ tượng hình \"Chấp nhận\" hình tròn"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Gió xoáy"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Sương mù"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Ô đóng"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Đêm đầy sao"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Bình minh trên núi"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Bình minh"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Cảnh quan thành phố khi trời tối"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Bình minh trên các tòa nhà"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Cầu vồng"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Cầu vào ban đêm"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Sóng nước"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Núi lửa"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Ngân hà"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Châu Âu-Châu Phi trên quả địa cầu"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"Châu Mỹ trên quả địa cầu"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Châu Á-Châu Úc trên quả địa cầu"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Quả cầu có kinh tuyến"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Biểu tượng trăng non"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Biểu tượng trăng lưỡi liềm"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Biểu tượng trăng thượng tuần"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Biểu tượng trăng khuyết"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Biểu tượng trăng tròn"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Biểu tượng trăng khuyết cuối tháng"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Biểu tượng trăng hạ tuần"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Biểu tượng trăng khuyết"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Trăng lưỡi liềm"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Trăng non hình khuôn mặt"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Trăng thượng tuần hình khuôn mặt"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Trăng hạ tuần hình khuôn mặt"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Trăng tròn hình khuôn mặt"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Mặt trời hình khuôn mặt"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Sao lấp lánh"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Sao băng"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"Cây hạt dẻ"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Cây giống con"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Cây thường xanh"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Cây lá rộng"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Cây cọ"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Cây xương rồng"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"Hoa tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Hoa anh đào"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Hoa hồng"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"Hoa dâm bụt"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Hoa hướng dương"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Hoa nở"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Bắp ngô"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Bông lúa"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Thảo mộc"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"Cỏ bốn lá"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Lá phong đỏ"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Lá rơi"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Lá đu đưa trong gió"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Nấm"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Cà chua"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"Cà tím"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Nho"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Quả dưa"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Dưa hấu"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"Quả quýt"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Chanh"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Quả chuối"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Quả dứa"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"Táo đỏ"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"Táo xanh"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Lê"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Đào"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Quả anh đào"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Quả dâu"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Lát pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Thịt trên xương"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Chân gia cầm"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Bánh gạo"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Nắm gạo"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Cơm"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Bột ca ri và gạo"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Bát bốc hơi"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"Mì ống"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Bánh mì"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Khoai tây chiên kiểu Pháp"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Khoai lang nướng"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"Bánh đoàn tử"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Tôm chiên"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Bánh cá hình cuộn sóng"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"Kem mềm"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Đá bào"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"Kem"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Bánh rán"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Bánh quy"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Thanh sôcôla"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Kẹo"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Món sữa trứng"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Mắt ong"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Bánh bơ giòn"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Hộp Bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Nồi thức ăn"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Nấu ăn"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Dao và nĩa"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Chèn trà không có tay cầm"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Cốc và chai sake"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Cốc rượu"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Cốc cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Đồ uống kiểu nhiệt đới"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Cốc bia"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Chạm cốc bia"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Chai nhỏ"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Chiếc nơ"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Món quà được bọc"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Bánh sinh nhật"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"Đèn ma"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Cây Nô-en"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Ông già Nô-en"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Pháo hoa"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Nến pháo hoa"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Bóng bay"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Pháo hoa kim tuyến"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Quả cầu hoa giấy"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Cây Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Cờ đan chéo"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Trang trí bằng quả thông"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Búp bê Nhật Bản"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"Cờ cá chép"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Gió thổi"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Khai mạc lễ ngắm trăng"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Cặp đi học"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Mũ tốt nghiệp"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Vòng quay ngựa gỗ"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Vòng đu quay"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"Đường sắt cho tàu trượt"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Cần câu cá và cá"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Micrô"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Máy quay phim"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Rạp chiếu phim"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Tai nghe"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Bảng màu họa sĩ"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Mũ chóp cao"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Lều trại"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Vé"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Bảng phân cảnh"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Nghệ thuật biểu diễn"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Trò chơi điện tử"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Mũi tên trúng đích"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Máy bán hàng tự động"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Bi-a"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Xúc xắc"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"Trò chơi lăn bóng gỗ"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Chơi bài hoa"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Nốt nhạc"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Nhiều nốt nhạc"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Saxophone"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Guitar"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Bàn phím nhạc"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Kèn Trompet"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Vĩ cầm"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Điểm âm nhạc"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Áo thun có khăn quàng cổ chạy"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Vợt tennis và bóng"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Trượt tuyết và ủng trượt tuyết"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"Bóng rổ và vòng"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Cờ có kẻ ô vuông"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Người trượt tuyết bằng ván"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Người chạy"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Người lướt sóng"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Cúp"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Đua ngựa"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Bóng đá Mỹ"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Bóng bầu dục"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Người bơi"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Xây nhà"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Nhà có vườn"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Tòa nhà văn phòng"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Bưu điện ở Nhật Bản"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Bưu điện ở Châu Âu"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Bệnh viện"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Ngân hàng"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Máy rút tiền tự động"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Khách sạn"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Khách sạn tình yêu"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Cửa hàng tiện ích"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Trường học"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Cửa hàng bách hóa"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Nhà máy"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"Đèn lồng Izakaya"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Lâu đài ở Nhật Bản"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Lâu đài ở Châu Âu"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Chuột cống"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Chuột"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Bò đực"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Con trâu"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Bò cái"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Con báo"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Con thỏ"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Mèo"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Rồng"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Cá sấu"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Cá voi"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Ốc sên"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Rắn"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Ngựa"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Cừu đực"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Dê"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Cừu"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Khỉ"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Gà trống"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Gà con"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Cún"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Lợn"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Lợn lòi đực"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Voi"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Bạch tuộc"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"Vỏ xoắn"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Con rệp"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Kiến"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Ong mật"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Bọ cánh cứng"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Cá"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Cá nhiệt đới"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"Cá nóc"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Rùa"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Gà ấp trứng"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Gà con"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Gà con mặt trước"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Chim"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Chim cánh cụt"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"Gấu túi"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Chó xù"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Lạc đà một bướu"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Lạc đà hai bướu"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Cá heo"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Mặt chuột"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Mặt bò đực"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Mặt hổ"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Mặt thỏ"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Mặt mèo"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Mặt rồng"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Cá voi phun tia"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Mặt ngựa"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Mặt khỉ"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Mặt cún"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Mặt lợn"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Mặt ếch"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Mặt chuột đồng"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Mặt sói"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Mặt gấu"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Mặt gấu trúc"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Mũi lợn"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Vết móng"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Đôi mắt"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Tai"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Mũi"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Miệng"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Lưỡi"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Ngón trỏ chỉ lên trên"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Ngón trỏ chỉ xuống dưới"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Ngón trỏ chỉ sang trái"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Ngón trỏ chỉ sang phải"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Biểu tượng quả đấm"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Biểu tượng tay vẫy"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Biểu tượng bàn tay ra dấu Ok"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Biểu tượng ngón tay cái giơ lên"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Biểu tượng ngón tay cái quay xuống"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Biểu tượng vỗ tay"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Biểu tượng đôi bàn tay mở"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Vương miện"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Mũ nữ"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Mắt kính"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Ca vát"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Áo sơ mi"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Quần bò"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Váy"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Bộ bikini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Quần áo nữ"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Ví"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Túi xách"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Túi đựng"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Giày nam"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Giày điền kinh"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Giày cao gót"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Xăng đan nữ"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Giày ống nữ"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Dấu chân"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Hình bóng nửa người"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Hình bóng nửa người"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Cậu bé"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Cô bé"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Nam"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Nữ"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Gia đình"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Đôi nam nữ nắm tay"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Hai người đàn ông nắm tay"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Hai người phụ nữ nắm tay"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Cảnh sát"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Người phụ nữ có tai thỏ"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Cô dâu mang khăn che mặt"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Người có tóc vàng hoe"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Người đàn ông đội mũ gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Người đàn ông đội khăn xếp"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Người đàn ông già hơn"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Người phụ nữ già hơn"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Đứa trẻ"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Công nhân xây dựng"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Công chúa"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Yêu quái Nhật Bản"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Yêu tinh Nhật Bản"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Ma"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Thiên thần nhỏ"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"Người ngoài hành tinh"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"Quỷ ngoài hành tinh"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Tiểu yêu"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Sọ"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Nhân viên tiếp tân"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Nhân viên bảo vệ"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Vũ công"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Son môi"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Sơn móng tay"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Xoa bóp mặt"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Cắt tóc"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Thợ cắt tóc"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Ống tiêm"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Viên thuốc"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Dấu hôn"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Thư tình"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Chuông"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Ngọc"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Nụ hôn"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Bó hoa"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Cặp đôi trái tim"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Lễ cưới"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Trái tim đập"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Trái tim tan vỡ"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Hai trái tim"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Trái tim lấp lánh"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Trái tím lớn lên"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Trái tim có mũi tên"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Trái tim màu xanh lam"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Trái tim màu xanh lục"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Trái tim màu vàng"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Trái tim màu tía"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Trái tim có dải băng"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Trái tim xoay vòng"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Trang trí trái tim"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Hình kim cương có dấu chấm bên trong"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Đèn điện"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Biểu tượng giận dữ"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Bom"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Biểu tượng đang ngủ"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Biểu tượng va chạm"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Biểu trưng giọt mồ hôi vã ra"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Giọt nhỏ"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Biểu tượng nét gạch"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Một đống"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Bắp tay uốn cong"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Biểu tượng hoa mắt"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Bóng lời nói"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Bóng suy nghĩ"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Hoa trắng"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Biểu tượng một trăm điểm"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Túi tiền"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Hối đoái"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Biểu tượng đồng đô la mạnh"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Thẻ tín dụng"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Tiền giấy có ký hiệu đồng yên"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Tiền giấy có ký hiệu đô la"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Tiền giấy có ký hiệu đồng Euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Tiền giấy có ký hiệu bảng Anh"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Tiền có đôi cánh"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Biểu đồ có xu hướng đi lên và ký hiệu yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Chỗ ngồi"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Máy tính cá nhân"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Cặp tài liệu"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Đĩa nhỏ"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Đĩa mềm"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Đĩa quang"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"Dvd"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Thư mục tệp"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Mở thư mục tệp"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Trang giấy uốn quăn"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Trang ngửa lên"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Lịch"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Lịch xé"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Chỉ mục thẻ"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Biểu đồ có xu hướng đi lên"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Biểu đồ có xu hướng đi xuống"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Biểu đồ thanh"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Khay nhớ tạm"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Đinh ghim"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Đinh ghim tròn"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Kẹp giấy"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Thước kẻ thẳng"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Thước kẻ hình chữ nhật"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Thanh dấu trang"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Sổ cái"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Sổ ghi chú"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Sổ ghi chú có bìa trang trí"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Sách đóng"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Sách mở"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Sách xanh lục"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Sách xanh lam"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Sách cam"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Sách"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Huy hiệu tên"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Cuộn"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Bản ghi nhớ"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Bộ nhận điện thoại"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Máy nhắn tin"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Máy fax"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"Ăng-ten vệ tinh"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Loa phóng thanh"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"Loa cổ động"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Khay hộp thư đi"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Khay hộp thư đến"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Gói"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Biểu tượng email"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Phong bì thư đến"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Phong bì có mũi tên hướng xuống dưới ở trên"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Hộp thư đóng với cờ được hạ xuống"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Hộp thư đóng với cờ được giương lên"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Hộp thư mở với cờ được giương lên"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Hộp thư mở với cờ được hạ xuống"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Hòm thư"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Còi bưu chính"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Báo"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Điện thoại di động"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Điện thoại di động có mũi tên về phía phải ở bên trái"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Chế độ rung"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Tắt điện thoại di động"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Cấm điện thoại di động"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"Ăng-ten có các vạch"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Máy ảnh"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Máy quay video"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"TV"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Đài"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Videocassette"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Mũi tên xoắn về bên phải"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Mũi tên vòng tròn mở về bên phải và về bên trái theo chiều kim đồng hồ"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Mũi tên vòng tròn mở về bên phải và bên bên trái theo chiều kim đồng hồ có lớp phủ 1 hình tròn"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Mũi tên hình tròn mở hướng xuống dưới và hướng lên trên theo chiều kim đồng hồ"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Mũi tên hình tròn mở hướng xuống dưới và hướng lên trên ngược chiều kim đồng hồ"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Biểu tượng độ sáng thấp"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Biểu tượng độ sáng cao"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Loa có tiếng gõ hủy"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Loa"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Loa có một sóng âm thanh"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Loa có ba sóng âm thanh"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Pin"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Đầu cắm điện"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Kính lúp trỏ sang trái"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Kính lúp trỏ sang phải"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Khóa có bút mực"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Khóa đóng có chìa"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Chìa khóa"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Khóa"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Khóa mở"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Chuông"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Chuông có tiếng gõ hủy"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Dấu trang"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Biểu tượng liên kết"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Nút đài"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Biểu tượng \"BACK\" có mũi tên sang trái ở trên"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Biểu tượng \"END\" có mũi tên sang trái ở trên"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Biểu tượng \"ON!\" có mũi tên trái phải ở trên"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Biểu tượng \"SOON\" với mũi tên sang phải ở trên"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Biểu tượng \"TOP\" với mũi tên hướng lên trên ở trên"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Biểu tượng cấm người dưới 18"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"Mũ phím 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Biểu tượng nhập cho chữ cái hoa la tinh"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Biểu tượng nhập các chữ cái nhỏ la tinh"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Biểu tượng nhập cho số"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Nhập ký hiệu cho ký hiệu"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Biểu tượng nhập cho chữ cái la tinh"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Lửa"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Đuốc điện"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Cờ lê"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Búa"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Đai ốc và bu lông"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Súng lục"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Kính hiển vi"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Kính thiên văn"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Quả cầu pha lê"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Ngôi sao sáu cánh có chấm ở giữa"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Biểu tượng tiếng Nhật cho người mới bắt đầu"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Biểu tượng đinh ba"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Nút hình vuông màu đen"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Nút hình vuông màu trắng"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Vòng tròn đỏ lớn"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Vòng tròn xanh lam lớn"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Hình thoi màu cam lớn"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Hình thoi màu xanh lam lớn"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Hình thoi màu cam nhỏ"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Hình thoi màu xanh lam nhỏ"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Hình tam giác đỏ một đỉnh trỏ lên"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Tam giác đỏ một đỉnh trỏ xuống"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Tam giác đỏ nhỏ một đỉnh trỏ lên"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Tam giác đỏ nhỏ một đỉnh trỏ xuống"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Mặt đồng hồ chỉ 1 giờ"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Mặt đồng hồ chỉ 2 giờ"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Mặt đồng hồ chỉ 3 giờ"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Mặt đồng hồ chỉ 4 giờ"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Mặt đồng hồ chỉ 5 giờ"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Mặt đồng hồ chỉ 6 giờ"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Mặt đồng hồ chỉ 7 giờ"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Mặt đồng hồ chỉ 8 giờ"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Mặt đồng hồ chỉ 9 giờ"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Mặt đồng hồ chỉ 10 giờ"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Mặt đồng hồ chỉ 11 giờ"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Mặt đồng hồ chỉ 12 giờ"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Mặt đồng hồ chỉ 1 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Mặt đồng hồ chỉ 2 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Mặt đồng hồ chỉ 3 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Mặt đồng hồ chỉ 4 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Mặt đồng hồ chỉ 5 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Mặt đồng hồ chỉ 6 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Mặt đồng hồ chỉ 7 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Mặt đồng hồ chỉ 8 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Mặt đồng hồ chỉ 9 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Mặt đồng hồ chỉ 10 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Mặt đồng hồ chỉ 11 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Mặt đồng hồ chỉ 12 giờ 30 phút"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"Đỉnh fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Tháp Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Tượng nữ thần tự do"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"Hình bóng của Nhật Bản"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Mặt cười"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Khuôn mặt cười toe toét với đôi mắt cười"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Khuôn mặt với giọt nước mắt vui mừng"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Mặt cười với miệng há"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Mặt cười với miệng há và đôi mắt cười"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Mặt cười với miệng há và toát mồ hôi"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Mặt cười với miệng há và đôi mắt nhắm chặt"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Mặt cười với vầng hào quang"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Mặt có sừng cười"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Mặt nháy mắt"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Mặt cười với đôi mắt cười"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Mặt nhấm nháp thức ăn ngon"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Mặt thanh thản"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Mặt cười với đôi mắt hình trái tim"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Mặt cười với kính râm"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Mặt cười giả tạo"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Mặt trung lập"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Mặt vô cảm"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Mặt buồn rầu"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Mặt toát mồ hôi"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Mặt trầm ngâm"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Mặt bối rối"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Mặt bực bội"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Mặt đang hôn"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Mặt đang gửi một nụ hôn"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Mặt đang hôn với đôi mắt cười"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Mặt đang hôn với đôi mắt nhắm"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Mặt lè lưỡi"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Mặt lè lưỡi và nháy mắt"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Mặt lè lưỡi và đôi mắt nhắm chặt"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Mặt thất vọng"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Mặt lo lắng"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Mặt giận dữ"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Mặt hờn dỗi"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Mặt khóc"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Mặt kiên nhẫn"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Mặt giận dữ"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Mặt thất vọng nhưng thanh thản"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Mặt cau có với miệng há"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Khuôn mặt đau khổ"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Mặt sợ hãi"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Mặt mệt lử"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Mặt buồn ngủ"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Mặt mệt mỏi"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Mặt nhăn nhó"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Mặt khóc òa"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Mặt há miệng"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Mặt ngơ ngác"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Mặt há miệng và toát mồ hôi"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Mặt la hét vì sợ hãi"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Mặt ngạc nhiên"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Mặt xúc động"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Mặt buồn ngủ"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Mặt choáng váng"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Khuôn mặt không có miệng"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Khuôn mặt đeo khẩu trang y tế"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Khuôn mặt mèo rạng rỡ với đôi mắt cười"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Khuôn mặt với giọt nước mắt vui mừng"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Khuôn mặt mèo cười với miệng há"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Mặt mèo cười với đôi mắt hình trái tim"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Mặt mèo với nụ cười gượng gạo"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Khuôn mặt mèo đang hôn với mắt nhắm"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Mặt mèo hờn dỗi"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Mặt mèo khóc"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Mặt mèo mệt lử"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Khuôn mặt với cử chỉ tồi"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Khuôn mặt với cử chỉ tốt"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Người cúi gập mình"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Khỉ che mắt"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Khỉ bịt tai"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Khỉ bịt miệng"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Người vui vẻ giơ một tay"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Người giơ hai tay chúc mừng"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Người mặt cau có"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Người mặt hờn dỗi"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Người với hai tay gập"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Tên lửa"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Máy bay trực thăng"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Đầu máy hơi nước"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Ô tô ray"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Tàu cao tốc"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Tàu cao tốc có mũi hình viên đạn"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Tàu"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"Xe điện ngầm"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Đường sắt loại nhẹ"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Ga"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Xe điện"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Tàu điện"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Xe buýt"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Xe buýt sắp đến"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Ô tô điện"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Bến xe buýt"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Xe buýt nhỏ"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"Xe cứu thương"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Xe chữa cháy"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Ô tô cảnh sát"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Ô tô cảnh sát sắp đến"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Taxi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Taxi sắp đến"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Ô tô"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Ô tô sắp đến"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Phương tiện giải trí"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Xe chở hàng"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Xe tải nối khớp"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Máy kéo"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Đường một ray"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Đường sắt trên núi"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Đường xe lửa trên cao"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Đường cáp qua núi"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Cáp treo"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Tàu thủy"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Xuồng"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Thuyền tốc độ"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Đèn giao thông theo chiều ngang"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Đèn giao thông theo chiều dọc"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Biểu tượng xây dựng"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Ô tô cảnh sát có đèn xoay"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Cờ tam giác trên cột trụ"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Cửa"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Biểu tượng cấm vào"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Biểu tượng hút thuốc"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Biểu tượng không hút thuốc"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Biểu tượng vứt rác vào nơi quy định"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Biểu tượng không vứt rác"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Biểu tượng nước uống được"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Biểu tượng nước không uống được"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Xe đạp"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Cấm xe đap"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Người đi xe đạp"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Người đi xe đạp leo núi"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Người đi bộ"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Cấm người đi bộ"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Trẻ em qua đường"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Biểu tượng đàn ông"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Biểu tượng phụ nữ"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Phòng vệ sinh"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Biểu tượng trẻ em"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Nhà vệ sinh"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Nhà vệ sinh"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Vòi hoa sen"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Tắm"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Bồn tắm"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Kiểm soát hộ chiếu"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Hải quan"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Xác nhận hành lý"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Hành lý bên trái"</string>
+</resources>
diff --git a/java/res/values-vi/strings-talkback-descriptions.xml b/java/res/values-vi/strings-talkback-descriptions.xml
index 659b1d3..c799345 100644
--- a/java/res/values-vi/strings-talkback-descriptions.xml
+++ b/java/res/values-vi/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Không có ký tự nào được nhập"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"<xliff:g id="KEY_NAME">%1$s</xliff:g> sửa <xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> thành <xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"<xliff:g id="KEY_NAME">%1$s</xliff:g> tự động sửa"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Không có đề xuất nào"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Ký tự không xác định"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Biểu tượng khác"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"I hoa, dấu chấm phía trên"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Ký hiệu không xác định"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"Biểu tượng cảm xúc không xác định"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Mặt buồn chán"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Mặt bối rối"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Mặt đeo kính râm"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Mặt ngạc nhiên"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Mặt đang hôn"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Mặt cau mày"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Có ký tự thay thế"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Ký tự thay thế đã bị loại bỏ"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Có đề xuất thay thế"</string>
diff --git a/java/res/values-vi/strings.xml b/java/res/values-vi/strings.xml
index ccb8668..14a029d 100644
--- a/java/res/values-vi/strings.xml
+++ b/java/res/values-vi/strings.xml
@@ -25,26 +25,31 @@
     <string name="use_contacts_for_spellchecking_option_summary" msgid="8754413382543307713">"Trình kiểm tra chính tả sử dụng các mục nhập từ danh sách liên hệ của bạn"</string>
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Rung khi nhấn phím"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Âm thanh khi nhấn phím"</string>
-    <string name="popup_on_keypress" msgid="123894815723512944">"Cửa sổ bật lên khi nhấn phím"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="popup_on_keypress" msgid="123894815723512944">"Bật lên khi nhấn phím"</string>
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Tùy chọn"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Tài khoản và bảo mật"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Giao diện và bố cục"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Nhập bằng cử chỉ"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Sửa văn bản"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Nâng cao"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Chủ đề"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Bật chia bàn phím"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Đồng bộ hóa Bàn phím Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Đã bật tính năng đồng bộ hóa"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Đồng bộ hóa từ điển cá nhân của bạn trên các thiết bị"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Đồng bộ hóa ngay bây giờ"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Xóa dữ liệu đám mây"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Xóa dữ liệu đã được đồng bộ hóa của bạn khỏi Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Dữ liệu đã đồng bộ hóa của bạn sẽ bị xóa khỏi đám mây. Bạn có chắc chắn không?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Xóa"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Hủy"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Từ điển cá nhân của bạn sẽ được đồng bộ hóa và sao lưu vào máy chủ Google. Chúng tôi có thể thu thập thông tin thống kê về tần suất của từ để giúp cải thiện sản phẩm của mình. Việc thu thập và sử dụng tất cả thông tin sẽ tuân thủ "<a href="https://www.google.com/policies/privacy">"Chính sách bảo mật của Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Vui lòng thêm một tài khoản Google vào thiết bị này để bật tính năng này"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Phương thức nhập khác"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Khóa chuyển ngôn ngữ bao gồm cả các phương thức nhập liệu khác"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Phím chuyển đổi ngôn ngữ"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Hiển thị khi nhiều ngôn ngữ đầu vào được bật"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Hiển thị chỉ báo trượt"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Hiển thị tín hiệu hình ảnh trong khi trượt từ phím Shift hoặc phím Biểu tượng"</string>
-    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Loại bỏ hiển thị phím trễ"</string>
+    <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Độ trễ ẩn phím bật lên"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Không có tgian trễ"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Mặc định"</string>
     <string name="abbreviation_unit_milliseconds" msgid="8700286094028323363">"<xliff:g id="MILLISECONDS">%s</xliff:g> mili giây"</string>
@@ -53,8 +58,8 @@
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Sử dụng tên từ Danh bạ cho các đề xuất và chỉnh sửa"</string>
     <string name="use_personalized_dicts" msgid="5167396352105467626">"Đề xuất được cá nhân hóa"</string>
     <string name="enable_metrics_logging" msgid="5506372337118822837">"Cải thiện <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="use_double_space_period" msgid="8781529969425082860">"Dấu cách đôi"</string>
-    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Nhấn đúp vào phím cách sẽ chèn thêm một dấu sau dấu cách"</string>
+    <string name="use_double_space_period" msgid="8781529969425082860">"Nhấn đúp phím cách chèn dấu chấm câu"</string>
+    <string name="use_double_space_period_summary" msgid="6532892187247952799">"Nhấn đúp phím cách sẽ chèn thêm một dấu chấm câu, theo sau là dấu cách"</string>
     <string name="auto_cap" msgid="1719746674854628252">"Tự động viết hoa"</string>
     <string name="auto_cap_summary" msgid="7934452761022946874">"Viết hoa chữ đầu tiên của mỗi câu"</string>
     <string name="edit_personal_dictionary" msgid="3996910038952940420">"Từ điển cá nhân"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Từ điển chính"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Hiển thị gợi ý sửa"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Hiển thị từ được đề xuất khi nhập"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Luôn hiển thị"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Hiển thị ở chế độ dọc"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Luôn ẩn"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Chặn các từ xúc phạm"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Không đề xuất các từ có thể gây xúc phạm"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Tự động sửa"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Khóa nhập giọng nói"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Không có phương thức nhập bằng giọng nói nào được bật. Kiểm tra cài đặt Ngôn ngữ và phương thức nhập."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Gửi phản hồi"</string>
-    <string name="select_language" msgid="3693815588777926848">"Ngôn ngữ nhập"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Ngôn ngữ"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Trợ giúp và phản hồi"</string>
+    <string name="select_language" msgid="5709487854987078367">"Ngôn ngữ"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Chạm lại để lưu"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Chạm vào đây để lưu"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Chủ đề bàn phím"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Chuyển đổi tài khoản"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Chưa chọn tài khoản nào"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Hiện đang sử dụng <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"OK"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Hủy"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Đăng xuất"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Chọn một tài khoản để sử dụng"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"Tiếng Anh (Anh)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"Tiếng Anh (Mỹ)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"Tiếng Tây Ban Nha (Mỹ)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"Tiếng Anh-Hindi"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Tiếng Serbia (La tinh)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"Tiếng Anh (Anh) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"Tiếng Anh (Mỹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Tiếng Tây Ban Nha (Mỹ) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"Tiếng Anh-Hindi (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Tiếng Serbia (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Truyền thống)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tiếng Kirin)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (tiếng Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Viết tắt)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Không ngôn ngữ nào (Bảng chữ cái)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Bảng chữ cái (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Bảng chữ cái (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Bảng chữ cái (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Bảng chữ cái (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Biểu tượng cảm xúc"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Chủ đề bàn phím"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Kiểu nhập tùy chỉnh"</string>
     <string name="add_style" msgid="6163126614514489951">"Thêm kiểu"</string>
     <string name="add" msgid="8299699805688017798">"Thêm"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Bật"</string>
     <string name="not_now" msgid="6172462888202790482">"Để sau"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Đã tồn tại kiểu nhập tương tự: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tgian chờ cho nhấn và giữ phím"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Thời gian rung khi nhấn phím"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Âm lượng khi nhấn phím"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Đọc tệp từ điển bên ngoài"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Không có tệp từ điển nào trong thư mục Nội dung tải xuống"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Chọn tệp từ điển để cài đặt"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Thực sự cài đặt tệp này cho <xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Đã xảy ra lỗi"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Tgian chờ cho nhấn và giữ phím"</string>
     <string name="button_default" msgid="3988017840431881491">"Mặc định"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Chào mừng bạn đến với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"với Nhập bằng cử chỉ"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Bây giờ bạn có thể nhập vào tất cả ứng dụng yêu thích của mình với <xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Định cấu hình các ngôn ngữ khác"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Đã xong"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Hiển thị biểu tượng ứng dụng"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Hiển thị biểu tượng ứng dụng trong trình chạy"</string>
     <string name="app_name" msgid="6320102637491234792">"Nhà cung cấp từ điển"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Nhà cung cấp từ điển"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Dịch vụ từ điển"</string>
@@ -181,7 +178,7 @@
     <string name="install_dict" msgid="180852772562189365">"Cài đặt"</string>
     <string name="cancel_download_dict" msgid="7843340278507019303">"Hủy"</string>
     <string name="delete_dict" msgid="756853268088330054">"Xóa"</string>
-    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Ngôn ngữ đã chọn trên thiết bị di động của bạn hiện có từ điển.&lt;br/&gt; Bạn nên &lt;b&gt;tải xuống&lt;/b&gt; từ điển <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> để cải thiện trải nghiệm nhập của mình.&lt;br/&gt; &lt;br/&gt; Quá trình tải xuống có thể mất vài phút qua 3G. Có thể mất phí nếu bạn không có &lt;b&gt;gói dữ liệu không giới hạn&lt;/b&gt;.&lt;br/&gt; Nếu bạn không chắc mình có gói dữ liệu nào, bạn nên tìm kết nối Wi-Fi để bắt đầu tải xuống tự động.&lt;br/&gt; &lt;br/&gt; Mẹo: Bạn có thể tải xuống và xóa từ điển bằng cách đi tới &lt;b&gt;Ngôn ngữ và nhập&lt;/b&gt; trong trình đơn &lt;b&gt;Cài đặt&lt;/b&gt; trên thiết bị di động của mình."</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"Ngôn ngữ đã chọn trên thiết bị di động của bạn hiện có từ điển.&lt;br/&gt; Bạn nên &lt;b&gt;tải xuống&lt;/b&gt; từ điển <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> để cải thiện trải nghiệm nhập của mình.&lt;br/&gt; &lt;br/&gt; Quá trình tải xuống có thể mất vài phút qua 3G. Có thể mất phí nếu bạn không có &lt;b&gt;gói dữ liệu không giới hạn&lt;/b&gt;.&lt;br/&gt; Nếu bạn không chắc mình có gói dữ liệu nào, bạn nên tìm kết nối Wi-Fi để bắt đầu tải xuống tự động.&lt;br/&gt; &lt;br/&gt; Mẹo: Bạn có thể tải xuống và xóa từ điển bằng cách đi tới &lt;b&gt;Ngôn ngữ và nhập&lt;/b&gt; trong menu &lt;b&gt;Cài đặt&lt;/b&gt; trên thiết bị di động của mình."</string>
     <string name="download_over_metered" msgid="1643065851159409546">"Tải xuống bây giờ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g>MB)"</string>
     <string name="do_not_download_over_metered" msgid="2176209579313941583">"Tải xuống qua Wi-Fi"</string>
     <string name="dict_available_notification_title" msgid="4583842811218581658">"Hiện có từ điển cho <xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>"</string>
diff --git a/java/res/values-zh-rCN/strings-emoji-descriptions.xml b/java/res/values-zh-rCN/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..9ea3fbe
--- /dev/null
+++ b/java/res/values-zh-rCN/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"版权符号"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"注册符号"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"双叹号"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"感叹号和问号"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"商标符号"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"信息来源"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"左右箭头"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"上下箭头"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"西北箭头"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"东北箭头"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"东南箭头"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"西南箭头"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"有钩的向左箭头"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"有钩的向右箭头"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"手表"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"沙漏"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"实心右指双三角"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"实心左指双三角"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"实心上指双三角"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"实心下指双三角"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"闹钟"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"沙粒流动中的沙漏"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"带圆圈的拉丁文大写字母M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"实心小方形"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"空心小方形"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"实心右指三角形"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"实心左指三角形"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"空心中等方形"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"实心中等方形"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"空心中小方形"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"实心中小方形"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"放射光线的实心太阳"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"云朵"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"实心电话标志"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"带对钩的选框"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"挡着雨点的雨伞"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"热饮料"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"向上指的食指"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"轻松的笑脸"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"白羊座"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"金牛座"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"双子座"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"巨蟹座"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"狮子座"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"处女座"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"天秤座"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"天蝎座"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"人马座"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"摩羯座"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"水瓶座"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"双鱼座"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"实心黑桃"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"实心梅花"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"实心红桃"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"实心方块"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"温泉"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"实心通用再循环符号"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"轮椅符号"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"锚"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"警告符号"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"高压符号"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"中等空心圆圈"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"中等实心圆圈"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"足球"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"棒球"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"雪人"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"被云遮挡的太阳"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"蛇夫座"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"禁止通行"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"教堂"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"喷泉"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"插在高尔夫球洞中的旗"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"帆船"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"帐篷"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"油泵"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"实心剪刀"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"空心加粗对钩标志"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"飞机"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"信封"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"举着的拳头"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"举着的手"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"胜利手势"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"铅笔"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"实心钢笔尖"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"加粗对钩标志"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"加粗乘号 x"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"火花"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"八轮辐星号"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"实心八角星"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"雪花"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"火花"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"十字线"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"带方框的反白十字线"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"实心问号装饰"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"空心问号装饰"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"空心叹号装饰"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"加粗叹号"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"实心的心形"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"加粗加号"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"加粗减号"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"加粗除号"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"实心向右箭头"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"卷曲环"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"双卷曲环"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"指向右侧然后向上弯曲的箭头"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"指向右侧然后向下弯曲的箭头"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"向左实心箭头"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"向上实心箭头"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"向下实心箭头"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"实心大正方形"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"空心大正方形"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"空心中等星形"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"加粗大圆圈"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"波形长划"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"部分替换标记"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"带圆圈的汉字祝"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"带圆圈的汉字秘"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"麻将牌红中"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"扑克牌小王"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A型血"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B型血"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"O型血"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"停车场"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB型血"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"带方框的CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"带方框的COOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"带方框的FREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"带方框的ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"带方框的NEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"带方框的NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"带方框的OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"带方框的SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"带方框的UP和感叹号"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"带方框的VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"带方框的片假名ココ"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"带方框的片假名サ"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"带方框的汉字無"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"带方框的汉字指"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"带方框的汉字禁"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"带方框的汉字空"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"带方框的汉字合"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"带方框的汉字満"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"带方框的汉字有"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"带方框的汉字月"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"带方框的汉字申"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"带方框的汉字割"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"带方框的汉字営"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"带圆圈的汉字得"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"带圆圈的汉字可"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"旋风"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"有雾"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"合上的雨伞"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"有星星的夜晚"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"越过山顶的日出"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"日出"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"黄昏的城市风景"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"越过建筑物的日落"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"彩虹"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"夜间的大桥"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"水波"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"火山"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"银河系"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"地球欧洲-非洲"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"地球美洲"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"地球亚洲-澳大利亚"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"带子午线的球形"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"新月符号"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"新月娥眉月符号"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"上弦月符号"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"盈凸月符号"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"满月符号"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"亏凸月符号"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"下弦月符号"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"残月娥眉月符号"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"娥眉月"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"带一张脸的新月"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"带一张脸的上弦月"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"带一张脸的下弦月"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"带一张脸的满月"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"带一张脸的太阳"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"发光的星星"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"流星"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"板栗"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"幼苗"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"常青树"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"落叶树"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"棕榈树"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"仙人掌"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"郁金香"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"樱花"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"玫瑰"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"芙蓉"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"向日葵"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"花蕾"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"玉米穗"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"稻穗"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"香草"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"四叶草"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"枫叶"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"落叶"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"在风中飘扬的树叶"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"蘑菇"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"番茄"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"茄子"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"葡萄"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"哈密瓜"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"西瓜"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"柑橘"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"柠檬"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"香蕉"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"菠萝"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"红苹果"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"青苹果"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"梨"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"桃"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"樱桃"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"草莓"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"汉堡"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"披萨片"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"连骨肉"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"鸡腿"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"米饼"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"饭团"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"白米饭"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"咖喱饭"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"热气腾腾的碗"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"意大利面"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"面包"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"炸薯条"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"烤地瓜"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"团子"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"关东煮"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"寿司"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"炸虾"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"漩涡图案鱼饼"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"软冰淇淋"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"刨冰"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"冰淇淋"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"甜甜圈"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"饼干"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"巧克力块"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"糖果"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"棒棒糖"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"奶油蛋羹"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"蜜罐"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"水果蛋糕"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"便当盒"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"盛满食物的锅"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"烹调"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"刀叉"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"无柄茶杯"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"日本酒瓶和杯子"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"葡萄酒杯"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"鸡尾酒杯"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"热带风情鸡尾酒"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"啤酒杯"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"碰在一起的啤酒杯"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"婴儿奶瓶"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"绸带"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"包好的礼物"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"生日蛋糕"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"南瓜灯"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"圣诞树"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"圣诞老人"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"焰火"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"烟花焰火"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"气球"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"礼花"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"五彩纸屑球"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"七夕树"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"交叉旗帜"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"门松"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"日本人偶"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"鲤鱼旗"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"风铃"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"赏月仪式"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"书包"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"毕业帽"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"旋转木马"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"摩天轮"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"过山车"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"鱼竿和鱼"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"麦克风"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"摄像机"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"电影院"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"耳机"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"画家调色板"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"礼帽"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"马戏团帐篷"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"门票"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"场记板"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"表演艺术"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"电子游戏机"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"命中靶心"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"老虎机"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"台球"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"游戏骰子"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"保龄球"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"花牌"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"音符"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"多个音符"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"萨克斯管"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"吉他"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"音乐键盘"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"小号"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"小提琴"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"乐谱"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"带饰带的运动衫"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"网球拍和网球"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"滑雪板和滑雪靴"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"篮球和篮框"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"格子旗"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"单板滑雪者"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"跑步者"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"冲浪者"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"奖杯"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"赛马"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"美式橄榄球"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"英式橄榄球"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"游泳者"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"房屋建筑"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"带花园的房子"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"办公楼"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"日本邮局"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"欧洲邮局"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"医院"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"银行"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"自动取款机"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"酒店"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"情侣酒店"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"便利店"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"学校"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"百货公司"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"工厂"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"居酒屋灯笼"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"日本城堡"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"欧洲城堡"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"大老鼠"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"小老鼠"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"牛"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"水牛"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"奶牛"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"豹"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"兔子"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"猫"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"龙"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"鳄鱼"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"鲸"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"蜗牛"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"蛇"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"马"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"公羊"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"山羊"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"绵羊"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"猴子"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"公鸡"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"母鸡"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"狗"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"猪"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"野猪"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"大象"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"章鱼"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"螺蛳"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"虫子"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"蚂蚁"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"蜜蜂"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"瓢虫"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"鱼"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"热带鱼"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"河豚"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"乌龟"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"破壳而出的小鸡"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"小鸡"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"面朝前方的小鸡"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"鸟"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"企鹅"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"考拉"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"贵宾狗"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"单峰驼"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"双峰驼"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"海豚"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"老鼠脸"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"牛脸"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"老虎脸"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"兔脸"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"猫脸"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"龙脸"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"喷水的鲸"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"马脸"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"猴脸"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"狗脸"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"猪脸"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"青蛙脸"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"仓鼠脸"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"狼脸"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"熊脸"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"熊猫脸"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"猪鼻子"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"掌印"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"眼睛"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"耳朵"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"鼻子"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"嘴"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"舌头"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"反手向上指的食指"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"反手向下指的食指"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"反手向左指的食指"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"反手向右指的食指"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"握拳手势"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"挥手手势"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK手势"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"拇指朝上手势"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"拇指朝下手势"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"拍手手势"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"张开双手手势"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"王冠"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"女式帽子"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"眼镜"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"领带"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T恤衫"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"牛仔裤"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"礼服"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"和服"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"比基尼"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"女装"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"女用小提包"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"手提包"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"小包包"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"男鞋"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"运动鞋"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"高跟鞋"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"女式凉鞋"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"女靴"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"脚印"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"半身人像轮廓"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"双半身人像轮廓"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"男孩"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"女孩"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"男人"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"女人"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"家庭"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"男人和女人手牵着手"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"握住手的两位男性"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"握住手的两位女性"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"警官"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"兔耳朵装扮的女性"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"戴面纱的新娘"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"金发人"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"戴瓜皮帽的男性"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"戴头巾的男性"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"年长的男性"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"年长的女性"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"婴儿"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"建筑工人"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"公主"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"日本鬼"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"日本天狗"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"幽灵"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"天使宝贝"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"外星人"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"外星怪物"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"小鬼"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"头骨"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"信息服务台人员"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"卫兵"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"舞者"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"口红"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"指甲油"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"脸部按摩"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"理发"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"理发店门前的旋转彩柱"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"注射器"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"药丸"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"吻痕"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"情书"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"戒指"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"宝石"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"接吻"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"花束"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"夫妻连心"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"婚礼"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"跳动的心"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"破碎的心"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"两颗心"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"闪亮的心"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"成长的心"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"被箭射中的心"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"蓝色的心"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"绿色的心"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"黄色的心"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"紫色的心"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"带丝带的心"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"环绕旋转的心"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"心形装饰"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"代表花卉的内部带点的菱形"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"电灯泡"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"愤怒标志"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"炸弹"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"睡觉标志"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"碰撞标志"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"汗水飞溅"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"水滴"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"快速奔跑标志"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"便便堆"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"弯曲二头肌"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"眩晕符号"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"对话泡泡框"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"思考泡泡框"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"白花"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"一百分符号"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"钱袋"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"货币兑换"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"加粗美元符号"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"信用卡"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"带日元符号的钞票"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"带美元符号的钞票"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"带欧元符号的钞票"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"带英镑符号的钞票"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"长翅膀的钱"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"带向上趋势和日元符号的图表"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"座椅"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"个人计算机"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"公文包"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"微型碟片"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"软盘"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"光盘"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"文件夹"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"打开的文件夹"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"下端卷起的纸页"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"正面朝上的纸页"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"日历"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"撕页日历"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"卡片索引"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"带向上趋势的图表"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"带向下趋势的图表"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"条形图"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"带夹写字板"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"图钉"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"圆图钉"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"曲别针"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"直尺"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"三角尺"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"书签贴纸"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"帐簿"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"笔记本"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"带装饰封面的笔记本"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"合上的书"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"打开的书"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"绿皮书"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"蓝皮书"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"橙皮书"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"图书"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"姓名牌"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"文卷"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"便笺"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"电话听筒"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"寻呼机"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"传真机"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"卫星天线"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"公共广播喇叭"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"啦啦队喇叭筒"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"发件箱"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"收件箱"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"包裹"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"电子邮件符号"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"来函"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"上方带有向下箭头的信封"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"带有降下的旗帜的关闭信箱"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"带有升起的旗帜的关闭信箱"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"带有升起的旗帜的打开信箱"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"带有降下的旗帜的打开信箱"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"信箱"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"邮政号角"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"报纸"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"手机"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"左侧带向右箭头的手机"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"振动模式"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"手机关机"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"禁止使用手机"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"天线信号格"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"相机"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"摄像机"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"电视"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"收音机"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"录像带"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"相交的向右箭头"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"顺时针向右和向左绕成开放式圆圈的箭头"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"顺时针向右和向左绕成开放式圆圈的箭头,左下角圆圈中标有数字1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"顺时针向下和向上绕成开放式圆圈的箭头"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"逆时针向下和向上绕成开放式圆圈的箭头"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"低亮度符号"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"高亮度符号"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"带删除斜线的扬声器"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"扬声器"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"带一个声波的扬声器"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"带三个声波的扬声器"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"电池"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"电源插头"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"朝向左边的放大镜"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"朝向右边的放大镜"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"带有墨水笔的锁"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"带有钥匙的闭合锁"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"钥匙"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"锁"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"打开的锁"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"铃"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"带删除斜线的铃"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"书签"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"链接符号"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"单选按钮"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"上带向左箭头的BACK"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"上带向左箭头的END"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"上带左右箭头的ON和感叹号"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"上带向右箭头的SOON"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"上带向上箭头的TOP"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"未满18岁禁止符号"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"键帽10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"大写拉丁文字母输入符号"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"小写拉丁文字母输入符号"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"数字输入符号"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"符号的输入符号"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"拉丁文字母输入符号"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"火"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"手电筒"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"扳手"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"锤子"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"螺母和螺栓"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"日式厨刀"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"手枪"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"显微镜"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"望远镜"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"水晶球"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"中间带点的六角星"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"日本的新手标志"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"三叉戟徽章"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"实心方形按钮"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"空心方形按钮"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"红色大圆"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"蓝色大圆"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"橙色大菱形"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"蓝色大菱形"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"橙色小菱形"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"蓝色小菱形"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"尖朝上的红色三角形"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"尖朝下的红色三角形"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"尖朝上的红色小三角形"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"尖朝下的红色小三角形"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"显示为一点的钟面"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"显示为两点的钟面"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"显示为三点的钟面"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"显示为四点的钟面"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"显示为五点的钟面"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"显示为六点的钟面"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"显示为七点的钟面"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"显示为八点的钟面"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"显示为九点的钟面"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"显示为十点的钟面"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"显示为十一点的钟面"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"显示为十二点的钟面"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"显示为一点半的钟面"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"显示为两点半的钟面"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"显示为三点半的钟面"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"显示为四点半的钟面"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"显示为五点半的钟面"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"显示为六点半的钟面"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"显示为七点半的钟面"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"显示为八点半的钟面"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"显示为九点半的钟面"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"显示为十点半的钟面"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"显示为十一点半的钟面"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"显示为十二点半的钟面"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"富士山"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"东京塔"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"自由女神像"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"日本地图轮廓"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"摩艾石像"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"露齿而笑的表情"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"咧嘴眉开眼笑的表情"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"喜极而泣的表情"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"咧嘴笑的表情"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"咧嘴且眯眼笑的表情"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"咧嘴笑且冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"咧嘴笑且眼睛紧闭的表情"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"带光环的笑脸"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"带恶魔角的笑脸"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"眨眼微笑的表情"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"眼睛笑眯眯的表情"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"品尝到美食的表情"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"如释重负的表情"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"眼睛呈心形的笑脸"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"戴墨镜的笑脸"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"得意的笑脸"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"无表情的脸"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"无动于衷的脸"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"面带不快的脸"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"冒冷汗的脸"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"忧虑的表情"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"困惑的表情"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"不知所措的表情"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"为亲吻而嘟着嘴的脸"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"拋飞吻的脸"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"为亲吻而嘟着嘴的笑眯眯的脸"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"为亲吻而嘟着嘴的闭起眼的脸"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"吐舌头的表情"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"眨眼吐舌头的表情"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"闭眼吐舌头的表情"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"失望的表情"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"担心的表情"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"生气的表情"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"噘嘴的表情"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"哭泣的表情"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"忍着哭的表情"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"不可一世的表情"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"失望但如释重负的表情"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"张嘴皱眉的表情"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"苦恼的表情"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"害怕的表情"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"厌烦的表情"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"打瞌睡的表情"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"疲惫的表情"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"做鬼脸的表情"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"嚎啕大哭的表情"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"张大嘴的表情"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"噤声的表情"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"张嘴冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"恐惧尖叫的表情"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"惊讶的表情"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"脸红的表情"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"熟睡的表情"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"头晕眼花的表情"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"没有嘴的脸"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"戴医用口罩的脸"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"露齿笑眯眯的猫脸"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"喜极而泣的猫脸"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"张嘴微笑的猫脸"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"眼睛呈心形的笑猫脸"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"坏笑的猫脸"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"为亲吻而嘟着嘴的闭起眼的猫脸"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"噘嘴的猫脸"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"哭泣的猫脸"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"厌倦的猫脸"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"做禁止手势的人"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"做OK手势的人"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"跪伏的人"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"非礼勿视的猴子"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"非礼勿听的猴子"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"非礼勿言的猴子"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"开心地举起一只手的人"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"高举双手庆祝的人"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"皱眉的人"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"噘嘴的人"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"双手合十的人"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"火箭"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"直升飞机"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"蒸汽火车"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"火车车厢"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"高铁列车"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"子弹头高铁列车"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"火车"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"地铁"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"轻轨"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"车站"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"有轨电车"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"电车车厢"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"公交车"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"迎面而来的公交车"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"无轨电车"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"公交车站牌"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"小型公共汽车"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"救护车"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"消防车"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"警车"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"迎面而来的警车"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"出租车"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"迎面而来的出租车"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"汽车"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"迎面而来的汽车"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"野营旅游车"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"送货车"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"铰接式卡车"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"拖拉机"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"单轨列车"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"山区铁路"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"高架铁路"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"山地索道"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"空中缆车"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"轮船"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"小船"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"快艇"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"横向红绿灯"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"竖向红绿灯"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"施工标志"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"旋转的警车警示灯"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"旗杆上的三角旗"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"门"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"禁止通行标志"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"吸烟标志"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"禁止吸烟标志"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"正确丢弃垃圾标志"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"请勿乱丢垃圾标志"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"饮用水标志"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"非饮用水标志"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"自行车"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"禁止自行车通行"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"骑自行车的人"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"骑山地自行车的人"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"行人"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"禁止行人通行"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"注意儿童穿越马路"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"男士标志"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"女士标志"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"洗手间"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"婴儿标志"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"卫生间"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"厕所"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"淋浴喷头"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"洗浴"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"浴缸"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"入境护照检查"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"海关"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"行李领取处"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"行李寄存处"</string>
+</resources>
diff --git a/java/res/values-zh-rCN/strings-talkback-descriptions.xml b/java/res/values-zh-rCN/strings-talkback-descriptions.xml
index b7b6b41..ed59f30 100644
--- a/java/res/values-zh-rCN/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rCN/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"未输入文字"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"按<xliff:g id="KEY_NAME">%1$s</xliff:g>键可将<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>更正为<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"按<xliff:g id="KEY_NAME">%1$s</xliff:g>键可进行自动更正"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"没有任何建议"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"未知字符"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"更多符号"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"带上点的拉丁文大写字母I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知符号"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知表情符号"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"无聊"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"尴尬"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"戴墨镜"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"惊讶"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"亲吻"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"皱眉"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字符"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已关闭替代字符"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的其他建议字词"</string>
diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml
index 9e71e99..e1bbe15 100644
--- a/java/res/values-zh-rCN/strings.xml
+++ b/java/res/values-zh-rCN/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按键振动"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"按键音效"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"按键时弹出显示字符"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"偏好设置"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"帐户和隐私权"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"外观和布局"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"滑行输入"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"文字更正"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"高级"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"主题背景"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"使用分离式键盘"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google 键盘同步"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"同步功能已开启"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"在设备间同步您的个人字典"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"立即同步"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"删除云端数据"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"将您已同步的数据从 Google 删除"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"您已同步的数据将会从云端删除。确定要执行此操作吗?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"删除"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"取消"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"您的个人字典将会同步并备份到 Google 服务器。系统可能会收集字词出现频率的统计信息,来帮助改进我们的产品。所有信息的收集和使用都会遵守 "<a href="https://www.google.com/policies/privacy">"Google 隐私权政策"</a>"。"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"要启用此功能,请将 Google 帐户添加到此设备中"</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">"语言切换键也可用于切换其他输入法"</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">"显示滑动指示效果"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"从 Shift 键或符号键滑动时显示视觉提示"</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>
@@ -57,14 +62,11 @@
     <string name="use_double_space_period_summary" msgid="6532892187247952799">"双击空格键可插入句号并后跟空格"</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="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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"语音输入键"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"未启用任何语音输入法。请检查“语言和输入法”设置。"</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="language_selection_title" msgid="3666971864764478269">"语言"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"帮助和反馈"</string>
+    <string name="select_language" msgid="5709487854987078367">"语言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次触摸即可保存"</string>
-    <string name="has_dictionary" msgid="6071847973466625007">"有可用词典"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"触摸此处即可保存"</string>
+    <string name="has_dictionary" msgid="6071847973466625007">"有可用字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"键盘主题"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"切换帐户"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"未选择任何帐户"</string>
+    <string name="account_selected" msgid="2846876462199625974">"当前使用的是<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"确定"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"取消"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"退出帐户"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"选择要使用的帐户"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英语(英国)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英语(美国)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙语(美国)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印地英语"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"塞尔维亚语(拉丁语布局)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英式英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"美式英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"美式西班牙语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印地英语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞尔维亚语(<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>布局)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(传统)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(西里尔文)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(拉丁文)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g>(紧凑型)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"无语言(字母)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"字母 (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"字母 (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"表情符号"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"键盘主题"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"自定义输入风格"</string>
     <string name="add_style" msgid="6163126614514489951">"添加样式"</string>
     <string name="add" msgid="8299699805688017798">"添加"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"确定要安装这个<xliff:g id="LANGUAGE_NAME">%s</xliff:g>词典吗?"</string>
-    <string name="error" msgid="8940763624668513648">"出现错误"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"按键长按延迟"</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>
@@ -154,42 +153,40 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"现在,您可以在自己喜欢的所有应用中使用 <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">"在启动器中显示应用图标"</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="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="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="5638680861387748936">"正在加载…"</string>
-    <string name="main_dict_description" msgid="3072821352793492143">"主词典"</string>
+    <string name="main_dict_description" msgid="3072821352793492143">"主字典"</string>
     <string name="cancel" msgid="6830980399865683324">"取消"</string>
     <string name="go_to_settings" msgid="3876892339342569259">"设置"</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="1583881200688185508">"您的移动设备上选择的语言有一个词典可供下载。&lt;br/&gt;我们建议您&lt;b&gt;下载&lt;/b&gt;这个<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>词典,以便获得更好的输入体验。&lt;br/&gt;&lt;br/&gt;通过3G网络下载可能需要一两分钟的时间。如果您使用的不是&lt;b&gt;无流量限制的套餐&lt;/b&gt;,则可能产生一定的流量费。&lt;br/&gt;如果您不确定自己使用的是哪种流量套餐,我们建议您连接到WLAN网络以便自动开始下载。&lt;br/&gt;&lt;br/&gt;提示:您可以在移动设备上的&lt;b&gt;语言和输入法&lt;/b&gt;部分(位于&lt;b&gt;设置&lt;/b&gt;菜单中)下载和删除词典。"</string>
+    <string name="should_download_over_metered_prompt" msgid="1583881200688185508">"您的移动设备上选择的语言有一个字典可供下载。&lt;br/&gt;我们建议您&lt;b&gt;下载&lt;/b&gt;这个<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>字典,以便获得更好的输入体验。&lt;br/&gt;&lt;br/&gt;通过3G网络下载可能需要一两分钟的时间。如果您使用的不是&lt;b&gt;无流量限制的套餐&lt;/b&gt;,则可能产生一定的流量费。&lt;br/&gt;如果您不确定自己使用的是哪种流量套餐,我们建议您连接到WLAN网络以便自动开始下载。&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>MB)"</string>
-    <string name="do_not_download_over_metered" msgid="2176209579313941583">"通过 WLAN 下载"</string>
-    <string name="dict_available_notification_title" msgid="4583842811218581658">"有一个<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>词典可供下载"</string>
+    <string name="do_not_download_over_metered" msgid="2176209579313941583">"通过WLAN网络下载"</string>
+    <string name="dict_available_notification_title" msgid="4583842811218581658">"有一个<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g>字典可供下载"</string>
     <string name="dict_available_notification_description" msgid="1075194169443163487">"按此通知即可查看和下载"</string>
     <string name="toast_downloading_suggestions" msgid="6128155879830851739">"正在下载:<xliff:g id="LANGUAGE_NAME">%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_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>
@@ -202,7 +199,7 @@
     <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_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>
diff --git a/java/res/values-zh-rHK/strings-emoji-descriptions.xml b/java/res/values-zh-rHK/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..b14c41d
--- /dev/null
+++ b/java/res/values-zh-rHK/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"版權符號"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"註冊符號"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"雙感嘆號"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"感嘆和問號"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"商標符號"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"資料來源"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"向左向右箭嘴"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"向上向下箭嘴"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"西北方箭嘴"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"東北方箭嘴"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"東南方箭嘴"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"西南方箭嘴"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"有鉤向左箭嘴"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"有鉤向右箭嘴"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"手錶"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"沙漏"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"黑色向右雙重三角形"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"黑色向左雙重三角形"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"黑色向上雙重三角形"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"黑色向下雙重三角形"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"鬧鐘"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"流動的沙漏"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"圓圈中的大寫字母 M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"小型黑色正方形"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"小型白色正方形"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"黑色向右三角形"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"黑色向左三角形"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"中型白色正方形"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"中型黑色正方形"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"中小型白色正方形"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"中小型黑色正方形"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"有光芒的太陽"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"雲朵"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"黑色電話"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"有勾選記號的投票箱"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"有雨滴的傘"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"熱飲"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"指向上的白色食指"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"白色笑臉"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"白羊座"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"金牛座"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"雙子座"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"巨蟹座"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"獅子座"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"處女座"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"天秤座"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"天蠍座"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"射手座"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"摩羯座"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"水瓶座"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"雙魚座"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"黑色葵扇紙牌"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"黑色梅花紙牌"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"黑色紅心紙牌"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"黑色階磚紙牌"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"溫泉"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"黑色的國際通用資源回收符號"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"輪椅符號"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"錨"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"警告標誌"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"高電壓標誌"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"中型白圓點"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"中型黑圓點"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"足球"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"棒球"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"四周沒有下雪的雪人"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"雲遮日"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"蛇夫座"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"禁止進入"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"教堂"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"噴泉"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"插在洞中的旗子"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"帆船"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"帳篷"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"燃料泵"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"黑剪刀"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"白色加粗的剔號"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"飛機"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"信封"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"高舉拳頭"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"舉起的手"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"勝利手勢"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"鉛筆"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"黑色筆尖"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"加粗的剔號"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"加粗的乘法符號"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"三個火花"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"八角星號"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"黑色八角星形"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"雪花"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"火花"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"打叉符號"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"反白方框交叉符號"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"黑色問號裝飾"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"白色問號裝飾"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"白色感嘆號裝飾"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"加粗的感嘆號符號"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"粗黑的愛心"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"加粗的加號"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"加粗的減號"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"加粗的除號"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"黑色向右箭嘴"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"捲曲循環線"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"雙捲曲循環線"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"先向右再往上彎曲的箭嘴"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"先向右再往下彎曲的箭嘴"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"黑色向左箭嘴"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"黑色向上箭嘴"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"黑色向下箭嘴"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"大型黑色正方形"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"大型白色正方形"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"中型白色星星"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"加粗的大圓形"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"波折線"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"專輯交替標記"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"圓形的表意文字「祝賀」"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"圓形的表意文字「秘密」"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"麻雀牌紅中"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"黑色鬼牌"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"A 型血"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"B 型血"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"O 型血"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"停車場"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"AB 型血"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"方框 CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"方框 COOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"方框 FREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"方框 ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"方框 NEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"方框 NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"方框 OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"方框 SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"方框 UP 與感嘆號"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"方框 VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"方框片假名「這裡」"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"方框片假名「服務」"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"方框表意文字「免費」"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"方框表意文字「預留座位」"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"方框表意文字「禁止」"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"方框表意文字「空位」"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"方框表意文字「同意」"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"方框表意文字「已滿」"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"方框表意文字「收費」"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"方框表意文字「每月」"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"方框表意文字「申請」"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"方框表意文字「折扣」"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"方框表意文字「營業中」"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"圓圈表意文字「特惠」"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"圓圈表意文字「接受」"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"氣旋"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"有霧"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"未打開的雨傘"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"有星空的夜晚"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"山頂日出"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"日出"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"暮光傾城"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"夕陽下的城市森林"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"彩虹"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"橋下夜色"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"水波"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"火山"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"銀河"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"地球 (歐洲到非洲)"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"地球 (美洲)"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"地球 (亞洲到澳洲)"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"有經線的地球"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"新月符號"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"眉月符號"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"上弦月符號"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"盈凸月符號"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"滿月符號"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"虧凸月符號"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"下弦月符號"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"殘月符號"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"新月"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"有臉孔的新月"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"有臉孔的上弦月"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"有臉孔的下弦月"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"有臉孔的滿月"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"有臉孔的太陽"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"閃耀的星星"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"流星"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"栗子"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"幼苗"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"長青樹"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"落葉樹"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"棕櫚樹"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"仙人掌"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"鬱金香"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"櫻花"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"玫瑰"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"大紅花"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"向日葵"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"花朵"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"玉米穗"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"稻穗"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"香草"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"四葉草"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"楓葉"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"落葉"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"隨風飛舞的葉子"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"蘑菇"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"番茄"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"茄子"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"葡萄"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"蜜瓜"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"西瓜"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"橘子"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"檸檬"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"香蕉"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"菠蘿"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"紅蘋果"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"青蘋果"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"梨"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"桃"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"車厘子"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"士多啤梨"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"漢堡包"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"一片薄餅"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"連骨的肉"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"家禽腿肉"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"米餅"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"飯糰"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"煮熟的飯"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"咖哩飯"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"冒著熱氣的碗"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"意粉"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"麵包"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"薯條"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"烤蕃薯"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"糯米丸子"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"關東煮"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"壽司"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"炸蝦"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"魚餅"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"軟雪糕"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"刨冰"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"雪糕"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"冬甩"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"曲奇"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"朱古力條"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"糖果"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"波板糖"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"奶黄/吉士"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"蜜糖罐"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"酥餅"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"便當"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"鍋物"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"烹飪"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"刀叉"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"無柄茶杯"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"清酒瓶與杯"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"酒杯"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"雞尾酒杯"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"熱帶飲料"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"啤酒杯"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"乾杯"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"奶瓶"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"絲帶"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"包裝好的禮物"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"生日蛋糕"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"南瓜燈"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"聖誕樹"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"聖誕老人"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"煙花"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"仙女棒"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"汽球"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"單線拉炮"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"五彩碎紙球"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"七夕許願樹"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"交叉的旗子"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"松果裝飾品"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"日本娃娃"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"鯉魚旗"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"風鈴"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"賞月"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"書包"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"學士帽"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"旋轉木馬"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"摩天輪"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"過山車"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"釣竿與魚"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"咪高峰"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"電影攝影機"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"戲院"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"耳機"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"調色盤"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"大禮帽"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"馬戲團帳篷"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"門票"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"場記牌"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"表演藝術"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"電子遊戲"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"正中紅心"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"老虎機"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"桌球"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"遊戲骰子"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"保齡球"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"花牌"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"音符"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"許多音符"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"色士風"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"結他"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"鍵盤琴"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"小號"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"小提琴"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"樂譜"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"有飾帶的運動衣"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"網球拍與球"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"滑雪與滑雪靴"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"籃球與球框"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"賽車方格旗"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"滑雪的人"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"跑步者"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"衝浪者"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"獎盃"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"賽馬"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"美式足球"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"橄欖球"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"游泳者"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"住宅建築"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"有庭院的房子"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"辦公大樓"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"日本郵局"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"歐洲郵局"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"醫院"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"銀行"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"自動提款機"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"酒店"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"汽車旅館"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"便利店"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"學校"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"百貨公司"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"工廠"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"居酒屋燈籠"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"日本城堡"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"歐式城堡"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"大型家鼠"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"老鼠"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"牛"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"水牛"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"母牛"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"豹"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"兔子"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"貓"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"龍"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"鱷魚"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"鯨魚"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"蝸牛"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"蛇"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"馬"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"公羊"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"山羊"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"綿羊"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"猴子"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"公雞"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"雞"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"狗"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"豬"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"野豬"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"大象"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"章魚"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"貝殼"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"蟲子"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"螞蟻"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"蜜蜂"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"甲蟲"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"魚"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"熱帶魚"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"河豚"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"烏龜"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"剛孵化的小雞"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"小雞"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"正面的小雞"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"鳥"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"企鵝"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"無尾熊"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"捲毛狗"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"單峰駱駝"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"雙峰駱駝"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"海豚"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"老鼠臉"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"牛臉"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"老虎臉"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"兔子臉"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"貓臉"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"龍臉"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"噴水鯨魚"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"馬臉"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"猴子臉"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"狗臉"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"豬臉"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"青蛙臉"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"倉鼠臉"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"狼臉"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"熊臉"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"熊貓臉"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"豬鼻"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"動物足印"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"眼睛"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"耳朵"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"鼻子"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"嘴巴"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"舌頭"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"白色食指向上反手"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"白色食指向下反手"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"白色食指向左反手"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"白色食指向右反手"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"握拳符號"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"揮手符號"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK 手勢符號"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"豎起拇指符號"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"拇指朝下符號"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"鼓掌符號"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"張開雙手符號"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"皇冠"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"女裝帽"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"眼鏡"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"領帶"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T 恤"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"牛仔褲"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"連身裙"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"和服"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"比基尼"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"女裝"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"皮包"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"手提包"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"小袋子"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"男裝鞋"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"運動鞋"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"高跟鞋"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"女裝涼鞋"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"女裝長靴"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"腳印"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"半身剪影"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"多個半身剪影"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"男孩"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"女孩"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"男人"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"女人"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"家庭"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"手牽手的男女"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"手牽手的男人"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"手牽手的女人"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"警察"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"兔女郎"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"戴著面紗的新娘"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"金髮的人"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"戴瓜皮帽的男人"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"戴著頭巾的男性"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"男性長者"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"女性長者"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"嬰兒"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"建築工人"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"公主"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"日本魔鬼"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"日本天狗"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"鬼魂"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"嬰兒天使"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"外星人"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"外星怪獸"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"小惡魔"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"骷髏頭"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"服務台人員"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"衛兵"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"舞者"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"唇膏"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"指甲油"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"臉部按摩"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"理髮"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"理髮店招牌"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"注射器"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"藥丸"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"唇印"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"情書"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"戒指"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"寶石"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"親吻"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"花束"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"情侶加上愛心"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"婚禮"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"跳動的心"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"破碎的心"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"兩顆心"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"閃耀的心"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"日益增大的心"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"一箭穿心"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"藍色的心"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"綠色的心"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"黃色的心"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"紫色的心"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"有彩帶的心"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"旋轉的心"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"心形裝飾品"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"中間有一點的鑽石圖案"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"電燈泡"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"生氣符號"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"炸彈"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"睡覺中符號"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"衝突符號"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"噴汗符號"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"小水滴"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"衝刺符號"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"一坨便便"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"展示二頭肌"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"暈眩符號"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"對話框"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"思考框"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"白色的花"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"一百分符號"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"錢包"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"貨幣換算"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"粗黑貨幣符號"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"信用卡"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"有日圓記號的鈔票"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"有美元記號的鈔票"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"有歐元記號的鈔票"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"有英鎊記號的鈔票"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"有翅膀的貨幣"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"有日圓記號且走勢向上的圖表"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"座位"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"個人電腦"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"公事包"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"迷你光碟"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"磁碟"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"光碟"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"檔案資料夾"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"開啟文件夾"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"捲曲的頁面"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"頁面朝上"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"日曆"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"撕頁式日曆"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"卡片索引"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"走勢向上的圖表"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"走勢向下的圖表"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"棒型圖"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"剪貼簿"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"圖釘"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"圓頂圖釘"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"萬字夾"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"直尺"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"三角尺"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"便利貼書籤"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"總帳"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"筆記本"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"有裝飾封面的筆記本"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"合起來的書"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"打開的書"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"綠色的書"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"藍色的書"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"橙色的書"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"圖書"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"名牌"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"捲軸"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"備忘標籤"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"電話聽筒"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"傳呼機"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"傳真機"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"衛星天線"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"大型擴音器"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"傳聲筒加油棒"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"送件匣"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"收件匣"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"包裹"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"電郵符號"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"寄來的信封"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"上方有向下箭嘴的信封"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"關閉而旗幟倒下的信箱"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"關閉而旗幟拉起的信箱"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"開啟而旗幟拉起的信箱"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"開啟而旗幟倒下的信箱"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"郵筒"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"急件喇叭"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"報紙"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"手機"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"左方有向右箭嘴的手機"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"振動模式"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"手機關機"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"禁止使用手機"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"含訊號格的天線"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"相機"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"攝影機"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"電視"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"無線電"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"錄影帶"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"扭轉向右的兩個箭嘴"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"順時針向右和向左繞成開放式圓圈的箭嘴"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"順時針向右和向左繞成開放式圓圈的箭嘴,上面有在圓圈內的 1 字"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"順時針向下和向上繞成開放式圓圈的箭嘴"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"逆時針向下和向上繞成開放式圓圈的箭嘴"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"低亮度符號"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"高亮度符號"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"加上刪除斜線的揚聲器"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"揚聲器"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"有一個聲波符號的揚聲器"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"有三個聲波符號的揚聲器"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"電池"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"電源插頭"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"向左的放大鏡"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"向右的放大鏡"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"墨水筆和鎖"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"鎖與鑰匙"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"鑰匙"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"鎖"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"打開了的鎖"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"鈴噹"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"加上刪除斜線的鈴鐺"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"書籤"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"連結符號"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"圓形按鈕"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"上方有向左箭嘴的「BACK」"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"上方有向左箭嘴的「END」"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"上方有向左、向右箭嘴的「ON」和感嘆號"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"上方有向右箭嘴的「SOON」"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"上方有向上箭嘴的「TOP」"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18 禁符號"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"鍵帽 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"大寫拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"小寫拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"數字輸入符號"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"符號輸入符號"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"火"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"電筒"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"士巴拿"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"鐵鎚"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"螺帽與螺栓"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"日式廚刀"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"手槍"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"顯微鏡"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"望遠鏡"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"水晶球"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"中間有一點的六星形"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"日本的新手符號"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"三叉戟圖騰"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"黑色方形按鈕"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"白色方形按鈕"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"大型紅色圓圈"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"大型藍色圓圈"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"大型橙色菱形"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"大型藍色菱形"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"小型橙色菱形"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"小型藍色菱形"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"往上的紅色三角形"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"往下的紅色三角形"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"往上的小型紅色三角形"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"往下的小型紅色三角形"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"顯示為一點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"顯示為兩點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"顯示為三點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"顯示為四點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"顯示為五點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"顯示為六點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"顯示為七點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"顯示為八點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"顯示為九點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"顯示為十點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"顯示為十一點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"顯示為十二點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"顯示為一點辦的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"顯示為兩點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"顯示為三點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"顯示為四點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"顯示為五點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"顯示為六點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"顯示為七點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"顯示為八點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"顯示為九點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"顯示為十點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"顯示為十一點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"顯示為十二點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"富士山"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"東京鐵塔"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"自由女神像"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"日本的剪影"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"澀谷仿摩艾石像"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"露齒而笑的笑臉"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"帶著微笑眼睛且露齒而笑的笑臉"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"流下開心淚水的笑臉"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"張嘴的笑臉"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"張嘴且帶著笑意的笑臉"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"張嘴且冒著冷汗的笑臉"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"張嘴閉眼的笑臉"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"頭頂光環的笑臉"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"頭上長角的笑臉"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"眨眼睛的表情"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"眼帶笑意的笑臉"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"嚐到美食的表情"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"安心的表情"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"眼睛呈現心形的笑臉"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"戴著太陽眼鏡的笑臉"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"嘻笑的臉"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"無表情"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"面無表情的臉"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"不帶一絲愉悅的表情"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"沈思的表情"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"困惑的表情"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"狼狽的表情"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"親吻的表情"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"送出飛吻的表情"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"笑咪咪親吻的表情"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"閉眼親吻的表情"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"伸舌的表情"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"伸舌眨眼的表情"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"伸舌閉眼的表情"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"失望的表情"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"擔心的表情"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"生氣的表情"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"面露不悅的表情"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"嚎啕大哭"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"固執己見的表情"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"洋洋得意的表情"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"失望卻又安心的表情"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"皺眉張嘴的表情"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"苦惱的表情"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"害怕的表情"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"精疲力竭的表情"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"想睡的表情"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"疲倦的表情"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"做鬼臉"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"大聲哭泣的表情"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"張嘴的表情"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"噤聲的表情"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"張嘴且冒著冷汗的表情"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"因害怕而尖叫的表情"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"驚訝的表情"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"興奮的表情"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"熟睡的表情"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"頭暈目眩的表情"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"沒有嘴巴的臉"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"帶著口罩的臉"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"眼睛微笑且露齒而笑的貓臉"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"喜極而泣的貓臉"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"露齒而笑的貓臉"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"微笑時眼睛呈心形的貓臉"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"帶著諷刺微笑的貓臉"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"閉著眼睛親吻的貓臉"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"生氣的貓臉"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"正在哭泣的貓臉"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"精疲力竭的貓臉"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"帶有「不好」手勢的臉"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"帶有 OK 手勢的臉"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"深深鞠躬的人"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"非禮勿視的猴子"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"非禮勿聽的猴子"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"非禮勿言的猴子"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"快樂且高舉單手的人"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"高舉雙手慶祝的人"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"皺眉的人"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"面露不悅的人"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"雙手交叉的人"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"火箭"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"直升機"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"蒸汽火車頭"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"火車車廂"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"高鐵列車"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"子彈火車"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"火車"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"地鐵"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"輕鐵"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"車站"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"電車"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"電車車廂"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"巴士"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"迎面駛來的巴士"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"無軌電車"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"巴士站"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"小巴"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"救護車"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"消防車"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"警車"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"迎面駛來的警車"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"的士"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"迎面駛來的的士"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"汽車"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"迎面駛來的汽車"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"露營車"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"運輸貨車"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"拖斗貨車"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"拖拉機"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"單軌鐵路"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"山區火車"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"懸掛式鐵路"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"山區纜車"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"架空纜車"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"船隻"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"划艇"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"快艇"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"橫向紅綠燈"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"垂直式紅綠燈"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"施工標誌"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"旋轉的警車警示燈"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"郵筒上的三角旗"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"門"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"禁止進入標誌"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"吸煙區符號"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"禁煙符號"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"正確丟棄垃圾標誌"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"請勿亂丟垃圾標誌"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"飲用水標誌"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"非飲用水標誌"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"單車"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"禁止單車"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"單車騎士"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"越野單車騎士"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"行人"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"禁止行人通過"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"注意兒童穿越馬路"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"男性符號"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"女性符號"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"廁所"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"嬰兒符號"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"廁所"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"盥洗室"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"淋浴間"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"浸浴"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"浴缸"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"護照檢查處"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"海關"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"行李領取處"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"行李寄存處"</string>
+</resources>
diff --git a/java/res/values-zh-rHK/strings-talkback-descriptions.xml b/java/res/values-zh-rHK/strings-talkback-descriptions.xml
index 386b5b5..6a1aa53 100644
--- a/java/res/values-zh-rHK/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rHK/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"未輸入文字"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"按「<xliff:g id="KEY_NAME">%1$s</xliff:g>」可將「<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>」修正為「<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>」"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"按「<xliff:g id="KEY_NAME">%1$s</xliff:g>」可自動修正"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"沒有建議"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"未知的字元"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift 鍵"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"更多符號"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"上方加點的大寫 I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知的符號"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知的表情符號"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"無聊"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"尷尬"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"戴著墨鏡"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"驚訝"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"親吻"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"皺眉"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字元"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已關閉替代字元"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的建議字詞"</string>
diff --git a/java/res/values-zh-rHK/strings.xml b/java/res/values-zh-rHK/strings.xml
index 4229bce..a3dd148 100644
--- a/java/res/values-zh-rHK/strings.xml
+++ b/java/res/values-zh-rHK/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"按鍵時播放音效"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"按鍵時顯示彈出式視窗"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"偏好設定"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"帳戶與私隱權"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"外觀和版面配置"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"手勢輸入"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"文字更正"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"進階"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"主題背景"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"啟用分離式鍵盤"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google 鍵盤同步"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"同步功能已啟用"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"同步處理各裝置之間的個人字典"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"立即同步"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"刪除雲端資料"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"刪除您來自 Google 的同步處理資料"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"您的同步處理資料將從雲端刪除,要確定嗎?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"刪除"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"取消"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"您的個人字典將同步處理並備份至 Google 伺服器。系統可能會收集字詞頻率的統計資料,以協助改善產品。所有資訊的收集和使用均遵循《"<a href="https://www.google.com/policies/privacy">"Google 私隱權政策"</a>"》。"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"請在這部裝置加入 Google 帳戶,以加入此功能。"</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">"語言切換鍵包括其他輸入法"</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">"顯示滑動指示器"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"從 Shift 鍵或符號鍵開始滑動時顯示視覺提示"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"語音輸入鍵"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"尚未啟用語音輸入法,請檢查語言和輸入設定。"</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="language_selection_title" msgid="3666971864764478269">"語言"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"說明和意見反映"</string>
+    <string name="select_language" msgid="5709487854987078367">"語言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"輕觸即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"切換帳戶"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"未選取任何帳戶"</string>
+    <string name="account_selected" msgid="2846876462199625974">"目前使用的是 <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"確定"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"取消"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"登出"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"選取要使用的帳戶"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英國)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美國)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙文 (美國)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印度英文"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"塞爾維亞文 (拉丁文)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英文 (英國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"西班牙文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞爾維亞文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (西里爾文)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (拉丁文)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (精簡版)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"無語言 (字母)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"字母 (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"字母 (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"鍵盤主題"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"自訂輸入樣式"</string>
     <string name="add_style" msgid="6163126614514489951">"新增樣式"</string>
     <string name="add" msgid="8299699805688017798">"新增"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"準備為<xliff:g id="LANGUAGE_NAME">%s</xliff:g>版本安裝這個檔案嗎?"</string>
-    <string name="error" msgid="8940763624668513648">"發生錯誤"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"長按鍵延遲"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"現在,您可以在所有最愛的應用程式中使用「<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">"在啟動器中顯示應用程式圖示"</string>
     <string name="app_name" msgid="6320102637491234792">"字典供應商"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"字典供應商"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"字典服務"</string>
@@ -163,8 +160,8 @@
     <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="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>
@@ -202,7 +199,7 @@
     <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_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>
diff --git a/java/res/values-zh-rTW/strings-emoji-descriptions.xml b/java/res/values-zh-rTW/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..b5c7230
--- /dev/null
+++ b/java/res/values-zh-rTW/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"版權符號"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"註冊符號"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"雙驚嘆號"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"驚嘆號和問號"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"商標符號"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"資訊來源"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"左右箭頭"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"上下箭頭"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"西北方箭頭"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"東北方箭頭"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"東南方箭頭"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"西南方箭頭"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"鉤狀向左箭頭"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"鉤狀向右箭頭"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"手錶"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"沙漏"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"指向右邊的兩個黑色三角形"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"指向左邊的兩個黑色三角形"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"指向上方的兩個黑色三角形"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"指向下方的兩個黑色三角形"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"鬧鐘"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"沙粒流動中的沙漏"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"圓圈中的大寫字母 M"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"小型黑色正方形"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"小型白色正方形"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"指向右邊的黑色三角形"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"指向左邊的黑色三角形"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"中型白色正方形"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"中型黑色正方形"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"中小型白色正方形"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"中小型黑色正方形"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"黑色的太陽和光線"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"雲朵"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"黑色電話"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"打勾的黑色方塊"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"雨傘和雨滴"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"熱飲"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"往上指的白色食指"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"白色笑臉"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"牡羊座"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"金牛座"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"雙子座"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"巨蟹座"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"獅子座"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"處女座"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"天秤座"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"天蠍座"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"射手座"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"摩羯座"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"水瓶座"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"雙魚座"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"黑色的黑桃紙牌花色"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"黑色的梅花紙牌花色"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"黑色的紅心紙牌花色"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"黑色的方塊紙牌花色"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"溫泉"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"黑色的國際通用資源回收符號"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"輪椅符號"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"船錨"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"警告標誌"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"高壓電標誌"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"中型白色圓形"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"中型黑色圓形"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"足球"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"棒球"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"四周沒有下雪的雪人"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"雲後的太陽"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"蛇夫座"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"禁止進入"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"教堂"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"噴泉"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"球洞中的旗子"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"帆船"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"帳篷"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"燃油泵"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"黑色剪刀"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"加粗的白色打勾記號"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"飛機"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"信封"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"舉起的拳頭"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"舉起的手"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"勝利手勢"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"鉛筆"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"黑色鋼筆筆尖"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"加粗的打勾記號"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"加粗的乘法記號"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"閃光"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"八角星芒"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"黑色八角星形"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"雪花"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"火花"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"交叉記號"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"反白方框打叉記號"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"黑色問號裝飾"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"白色問號裝飾"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"白色驚嘆號裝飾"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"加粗的驚嘆號符號"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"加粗的黑色愛心"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"加粗的加號"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"加粗的減號"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"加粗的除號"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"黑色向右箭頭"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"捲曲線"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"雙捲曲線"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"先向右再往上彎曲的箭頭"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"先向右再往下彎曲的箭頭"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"黑色向左箭頭"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"黑色向上箭頭"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"黑色向下箭頭"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"大型黑色正方形"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"大型白色正方形"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"中型白色星星"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"加粗的大型圓形"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"連續波浪號"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"歌謠標記"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"圓圈形的表意字元「祝賀」"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"圓圈形的表意字元「秘密」"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"麻將牌紅中"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"黑色鬼牌"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"血型 A 型"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"血型 B 型"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"血型 O 型"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"停車場"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"血型 AB 型"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"方框 CL"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"方框 COOL"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"方框 FREE"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"方框 ID"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"方框 NEW"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"方框 NG"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"方框 OK"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"方框 SOS"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"方框 UP 和驚嘆號"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"方框 VS"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"方框片假名「這裡」"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"方框片假名「服務」"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"方框表意字元「免費」"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"方框表意字元「對號座」"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"方框表意字元「禁止」"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"方框表意字元「空位」"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"方框表意字元「同意」"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"方框表意字元「已滿」"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"方框表意字元「收費」"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"方框表意字元「每月」"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"方框表意字元「申請」"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"方框表意字元「折扣」"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"方框表意字元「營業中」"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"圓圈形的表意字元「特惠」"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"圓圈形的表意字元「接受」"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"氣旋"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"起霧"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"收起的雨傘"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"星夜"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"山頂日出"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"日出"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"城市暮色"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"高樓日落"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"彩虹"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"夜晚的橋"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"水波"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"火山"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"銀河"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"地球 (歐洲到非洲)"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"地球 (美洲)"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"地球 (亞洲到澳洲)"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"有經線的地球"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"新月符號"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"娥眉月符號"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"上弦月符號"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"盈凸月符號"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"滿月符號"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"虧凸月符號"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"下弦月符號"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"殘月符號"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"月牙"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"有臉的新月"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"有臉的上弦月"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"有臉的下弦月"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"有臉的滿月"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"有臉的太陽"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"發光的星星"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"流星"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"栗子"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"樹苗"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"常綠植物"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"落葉植物"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"棕櫚樹"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"仙人掌"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"鬱金香"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"櫻花"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"玫瑰"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"扶桑花"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"向日葵"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"花朵"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"玉米"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"稻米"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"香草"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"四葉酢醬草"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"楓葉"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"落葉"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"風中落葉"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"蘑菇"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"番茄"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"茄子"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"葡萄"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"香瓜"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"西瓜"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"柑橘"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"檸檬"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"香蕉"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"鳳梨"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"紅蘋果"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"綠蘋果"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"梨子"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"桃子"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"櫻桃"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"草莓"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"漢堡"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"披薩切片"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"帶骨肉"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"家禽腿肉"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"米脆餅"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"飯糰"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"米飯"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"咖哩飯"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"熱食"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"義大利麵"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"麵包"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"薯條"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"烤地瓜"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"日式糯米丸子"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"關東煮"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"壽司"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"炸蝦"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"鳴門卷"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"霜淇淋"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"刨冰"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"冰淇淋"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"甜甜圈"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"餅乾"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"巧克力棒"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"糖果"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"卡士達"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"蜂蜜罐"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"水果蛋糕"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"便當"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"火鍋料理"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"烹飪"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"刀叉"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"茶碗"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"清酒和酒杯"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"葡萄酒杯"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"雞尾酒杯"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"熱帶風情雞尾酒"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"啤酒杯"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"乾杯"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"奶瓶"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"緞帶"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"包裝好的禮物"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"生日蛋糕"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"萬聖節南瓜燈籠"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"聖誕樹"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"聖誕老人"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"煙火"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"仙女棒"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"氣球"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"拉炮"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"五彩碎紙球"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"七夕許願樹"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"交叉的旗子"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"門松"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"日本女兒節人偶"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"鯉魚旗"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"風鈴"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"賞月"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"書包"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"學士帽"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"旋轉木馬"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"摩天輪"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"雲霄飛車"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"釣竿和魚"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"麥克風"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"電影攝影機"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"電影"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"耳機"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"調色盤"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"禮帽"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"馬戲團帳篷"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"門票"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"場記板"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"表演藝術"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"電玩遊戲"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"正中紅心"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"吃角子老虎機"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"撞球"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"遊戲骰子"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"保齡球"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"日本花牌"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"音符"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"許多音符"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"薩克斯風"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"吉他"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"鍵盤樂器"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"小號"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"小提琴"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"樂譜"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"有飾帶的跑步運動服"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"網球拍和球"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"滑雪和滑雪靴"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"籃球和籃框"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"賽車方格旗"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"滑雪板"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"跑者"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"衝浪客"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"獎盃"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"賽馬"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"美式足球"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"橄欖球"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"游泳者"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"住家建築"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"有庭院的房子"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"辦公建築"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"日本郵局"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"歐洲郵局"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"醫院"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"銀行"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"自動櫃員機"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"飯店"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"賓館"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"便利商店"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"學校"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"百貨公司"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"工廠"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"居酒屋燈籠"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"日式宮殿"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"歐式城堡"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"大型家鼠"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"老鼠"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"牛"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"水牛"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"母牛"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"豹"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"兔子"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"貓"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"龍"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"鱷魚"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"鯨魚"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"蝸牛"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"蛇"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"馬"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"公羊"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"山羊"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"綿羊"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"猴子"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"公雞"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"雞"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"狗"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"豬"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"野豬"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"大象"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"章魚"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"螺"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"蟲子"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"螞蟻"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"蜜蜂"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"瓢蟲"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"魚"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"熱帶魚"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"河豚"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"烏龜"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"剛孵化的小雞"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"小雞"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"面向前方的小雞"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"鳥"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"企鵝"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"無尾熊"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"貴賓狗"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"單峰駱駝"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"雙峰駱駝"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"海豚"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"老鼠臉"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"母牛臉"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"老虎臉"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"兔子臉"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"貓臉"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"龍臉"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"噴水的鯨魚"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"馬臉"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"猴子臉"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"狗臉"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"豬臉"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"青蛙臉"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"倉鼠臉"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"狼臉"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"熊臉"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"貓熊臉"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"豬鼻子"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"腳掌印"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"眼睛"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"耳朵"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"鼻子"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"嘴巴"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"舌頭"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"手背朝前往上指的白色食指"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"手背朝前往下指的白色食指"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"手背朝前往左指的白色食指"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"手背朝前往右指的白色食指"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"握拳符號"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"揮手符號"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"OK 手勢符號"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"拇指朝上符號"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"拇指朝下符號"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"鼓掌符號"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"張開雙手符號"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"皇冠"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"女帽"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"眼鏡"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"領帶"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"T 恤"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"牛仔褲"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"洋裝"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"和服"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"比基尼"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"女裝"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"錢包"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"手提包"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"小袋子"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"男鞋"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"運動鞋"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"高跟鞋"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"女用涼鞋"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"女靴"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"腳印"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"半身像輪廓"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"多個半身像輪廓"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"男孩"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"女孩"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"男人"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"女人"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"家庭"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"一男一女手牽手"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"兩個男人手牽手"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"兩個女人手牽手"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"警察"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"兔耳女郎"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"戴頭紗的新娘"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"金髮的人"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"戴瓜皮帽的男人"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"戴頭巾的男人"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"男性長者"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"女性長者"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"嬰兒"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"建築工人"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"公主"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"日本妖怪"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"日本天狗"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"幽靈"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"小天使"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"外星人"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"外星怪物"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"小惡魔"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"骷髏"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"服務台人員"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"衛兵"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"舞者"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"口紅"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"指甲油"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"臉部按摩"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"剪髮"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"理髮店彩色旋轉燈筒招牌"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"注射器"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"藥丸"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"唇印"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"情書"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"戒指"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"寶石"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"親吻"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"花束"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"情侶和愛心"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"婚禮"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"跳動的心"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"碎裂的心"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"兩顆愛心"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"閃閃發光的愛心"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"變大的愛心"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"一箭穿心"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"藍色愛心"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"綠色愛心"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"黃色愛心"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"紫色愛心"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"綁上緞帶的愛心"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"旋轉的愛心"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"心形裝飾"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"中間有一個點的鑽石形狀"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"電燈泡"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"生氣符號"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"炸彈"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"想睡符號"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"碰撞符號"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"噴汗符號"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"水滴"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"衝刺符號"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"一坨便便"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"股起的二頭肌"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"暈眩符號"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"對話泡泡框"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"思考泡泡框"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"白花"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"一百分符號"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"錢袋"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"貨幣兌換"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"大型錢幣符號"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"信用卡"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"有日幣符號的鈔票"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"有美元符號的鈔票"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"有歐元符號的鈔票"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"有英鎊符號的鈔票"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"長翅膀的錢"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"有日圓符號且走勢往上的圖表"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"座位"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"個人電腦"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"公事包"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"迷你光碟"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"磁碟片"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"光碟"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"文件夾"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"開啟的文件夾"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"一角捲起的紙頁"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"正面朝上的紙頁"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"日曆"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"撕頁式日曆"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"卡片索引"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"走勢往上的圖表"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"走勢往下的圖表"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"長條圖"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"剪貼簿"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"圖釘"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"圓頭圖釘"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"迴紋針"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"直尺"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"三角板"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"書籤標籤"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"分類帳"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"筆記本"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"有裝飾性封面的筆記本"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"闔上的書"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"翻開的書"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"綠色的書"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"藍色的書"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"橘色的書"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"書籍"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"識別證"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"卷軸"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"筆記"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"電話話筒"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"呼叫器"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"傳真機"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"衛星天線"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"大聲公"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"傳聲筒加油棒"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"寄件匣"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"收件匣"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"包裹"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"電子郵件符號"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"寄來的信封"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"上方有向下箭頭的信封"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"關閉且已將旗子拉下的信箱"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"關閉且已將旗子升起的信箱"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"開啟且已將旗子升起的信箱"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"開啟且已將旗子降下的信箱"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"郵筒"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"急件喇叭"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"報紙"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"手機"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"左方有向右箭頭的手機"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"振動模式"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"手機關機"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"禁止使用手機"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"含訊號格的天線"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"相機"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"攝影機"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"電視"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"收音機"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"錄影帶"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"扭轉向右的兩個箭頭"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"順時針向右和向左繞成開放式圓圈的箭頭"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"順時針向右和向左繞成開放式圓圈的箭頭,上面有圈起來的 1"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"順時針向下和向上繞成開放式圓圈的箭頭"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"逆時針向下和向上繞成開放式圓圈的箭頭"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"低亮度符號"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"高亮度符號"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"加上刪除斜線的喇叭"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"喇叭"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"有一個聲波符號的喇叭"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"有三個聲波符號的喇叭"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"電池"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"插頭"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"朝向左邊的放大鏡"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"朝向右邊的放大鏡"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"鎖頭和鋼筆"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"關上的鎖頭和鑰匙"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"鑰匙"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"鎖頭"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"打開的鎖頭"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"響鈴"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"加上刪除斜線的響鈴"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"書籤"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"連結符號"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"圓形按鈕"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"上方有向左箭頭的 BACK"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"上方有向左箭頭的 END"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"上方有向左箭頭的 ON 和驚嘆號"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"上面有向右箭頭的 SOON"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"上面有向上箭頭的 TOP"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"18 禁符號"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"鍵帽 10"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"大寫拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"小寫拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"數字輸入符號"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"符號輸入符號"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"拉丁字母輸入符號"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"火"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"手電筒"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"扳手"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"鐵鎚"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"螺帽與螺栓"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"日式廚刀"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"手槍"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"顯微鏡"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"望遠鏡"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"水晶球"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"中間有一個點的六角星"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"日本的新手符號"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"三插戟圖騰"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"黑色方形按鈕"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"白色方形按鈕"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"大型紅色圓圈"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"大型藍色圓圈"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"大型橘色菱形"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"大型藍色菱形"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"小型橘色菱形"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"小型藍色菱形"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"往上的紅色三角形"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"往下的紅色三角形"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"往上的小型紅色三角形"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"往下的小型紅色三角形"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"顯示為一點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"顯示為兩點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"顯示為三點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"顯示為四點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"顯示為五點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"顯示為六點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"顯示為七點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"顯示為八點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"顯示為九點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"顯示為十點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"顯示為十一點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"顯示為十二點的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"顯示為一點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"顯示為兩點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"顯示為三點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"顯示為四點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"顯示為五點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"顯示為六點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"顯示為七點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"顯示為八點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"顯示為九點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"顯示為十點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"顯示為十一點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"顯示為十二點半的時鐘鐘面"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"富士山"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"東京鐵塔"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"自由女神像"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"日本地圖輪廓"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"澀谷仿摩艾石像"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"露齒而笑的表情"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"眉開眼笑的表情"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"喜極而泣的表情"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"張嘴微笑的表情"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"張嘴眉開眼笑的表情"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"張嘴微笑冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"張嘴微笑眼睛緊閉的表情"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"有光圈的笑臉"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"長角的笑臉"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"眨眼微笑的表情"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"眼睛笑眯眯的表情"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"嚐到美食的表情"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"如釋重負的表情"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"眼睛變成愛心的笑臉"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"戴墨鏡微笑的表情"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"得意的表情"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"心平氣和的表情"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"面無表情的臉"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"無精打采的表情"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"憂慮的表情"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"困惑的表情"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"困惑的表情"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"親吻的表情"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"飛吻的表情"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"笑咪咪親吻的表情"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"眨眼親吻的表情"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"吐舌頭的表情"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"眨眼吐舌頭的表情"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"緊閉眼睛吐舌頭的表情"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"失望的表情"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"擔心的表情"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"生氣的表情"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"噘嘴的表情"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"哭泣的表情"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"堅持的表情"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"洋洋得意的表情"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"失望又鬆了一口氣的表情"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"皺眉張嘴的表情"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"苦惱的表情"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"害怕的表情"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"厭倦的表情"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"想睡的表情"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"疲累的表情"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"扭曲的表情"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"嚎啕大哭的表情"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"張大嘴的表情"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"噤聲的表情"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"張嘴冒冷汗的表情"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"驚恐尖叫的表情"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"吃驚的表情"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"臉紅的表情"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"想睡的表情"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"頭暈眼花的表情"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"沒有嘴巴的臉"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"戴著醫療口罩的臉"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"貓咪眉開眼笑的表情"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"貓咪喜極而泣的表情"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"貓咪張嘴微笑的表情"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"貓咪眼睛變成愛心的笑臉"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"貓咪狡猾微笑的表情"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"貓咪眨眼親吻的表情"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"貓咪噘嘴的表情"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"貓咪哭泣的表情"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"貓咪厭倦的表情"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"比出拒絕手勢的人"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"比出 OK 手勢的人"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"深深鞠躬的人"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"代表非禮勿視的猴子"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"代表非禮勿聽的猴子"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"代表非禮勿言的猴子"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"開心地舉起一隻手的人"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"舉起雙手慶祝的人"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"皺眉的人"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"噘嘴的人"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"雙手合十的人"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"火箭"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"直昇機"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"蒸汽火車頭"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"火車車廂"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"高速鐵路列車"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"子彈頭高速鐵路列車"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"火車"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"地下鐵路"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"輕軌鐵路"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"車站"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"電車"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"電車車廂"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"公車"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"迎面駛來的公車"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"無軌電車"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"公車站牌"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"小型巴士"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"救護車"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"消防車"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"警車"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"迎面駛來的警車"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"計程車"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"迎面駛來的計程車"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"汽車"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"迎面駛來的汽車"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"休旅露營車"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"運貨車"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"鉸接式卡車"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"拖拉機"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"單軌鐵路"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"山區火車"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"懸掛式鐵路"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"山區纜車"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"空中纜車"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"船隻"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"划槳船"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"快艇"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"水平式紅綠燈"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"垂直式紅綠燈"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"施工標誌"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"旋轉的警車警示燈"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"旗杆上的三角旗"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"門"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"禁止進入標誌"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"吸菸標誌"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"禁菸標誌"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"請正確丟棄垃圾標誌"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"請勿亂丟垃圾標誌"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"飲用水標誌"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"非飲用水標誌"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"腳踏車"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"禁帶腳踏車"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"腳踏車騎士"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"越野自行車騎士"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"行人"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"禁止行人通行"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"注意兒童穿越馬路"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"男性符號"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"女性符號"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"洗手間"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"嬰兒符號"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"馬桶"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"廁所"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"淋浴間"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"浴室"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"浴缸"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"護照查驗處"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"海關"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"行李領取處"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"行李寄存處"</string>
+</resources>
diff --git a/java/res/values-zh-rTW/strings-talkback-descriptions.xml b/java/res/values-zh-rTW/strings-talkback-descriptions.xml
index 7a5f3df..ed5f158 100644
--- a/java/res/values-zh-rTW/strings-talkback-descriptions.xml
+++ b/java/res/values-zh-rTW/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"未輸入文字"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"按下「<xliff:g id="KEY_NAME">%1$s</xliff:g>」可將「<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g>」修正為「<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>」"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"按下「<xliff:g id="KEY_NAME">%1$s</xliff:g>」可執行自動修正"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"沒有任何建議"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"未知的字元"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"Shift 鍵"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"更多符號"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"上方加點的大寫 I"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"未知的符號"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"未知的表情符號"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"無聊"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"尷尬"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"戴墨鏡"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"驚訝"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"親吻"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"皺眉"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"有可用的替代字元"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"已關閉替代字元"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"有可用的建議字詞"</string>
diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml
index eafea5b..21b3498 100644
--- a/java/res/values-zh-rTW/strings.xml
+++ b/java/res/values-zh-rTW/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"按鍵時震動"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"按鍵聲音"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"按鍵時彈出"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"偏好設定"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"帳戶與隱私權"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"外觀與版面配置"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"手勢輸入"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"文字修正"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"進階"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"主題"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"啟用分離式鍵盤"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Google 鍵盤同步處理"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"同步處理功能已開啟"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"在各裝置上同步處理您的個人字典"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"立即同步處理"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"刪除雲端資料"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"將已同步處理的資料從 Google 刪除"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"已同步處理的資料將從雲端中刪除。您確定嗎?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"刪除"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"取消"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"系統將會同步處理您的個人字典並備份至 Google 伺服器,同時也會收集字詞頻率的統計資訊,藉此改善我們的產品品質。所有資訊的收集和使用方式都會遵守《"<a href="https://www.google.com/policies/privacy">"Google 隱私權政策"</a>"》的規定。"</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"請將 Google 帳戶新增到這個裝置以啟用這項功能"</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">"使語言切換鍵包含其他輸入法"</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">"顯示滑動指示器"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"從 Shift 鍵或符號鍵滑動時顯示視覺提示"</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>
@@ -62,9 +67,6 @@
     <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>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"語音輸入按鍵"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"尚未啟動語音輸入法,請檢查語言與輸入設定。"</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="language_selection_title" msgid="3666971864764478269">"語言"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"說明與意見回饋"</string>
+    <string name="select_language" msgid="5709487854987078367">"語言"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"再次輕觸即可儲存"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"輕觸這裡即可儲存"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"可用的字典"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"鍵盤主題"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"切換帳戶"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"尚未選取帳戶"</string>
+    <string name="account_selected" msgid="2846876462199625974">"目前使用的帳戶是 <xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"確定"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"取消"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"登出"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"選取要使用的帳戶"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"英文 (英國)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"英文 (美國)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"西班牙文 (美國)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"印度英文"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"塞爾維亞文 (拉丁文)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"英文 (英國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"英文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"西班牙文 (美國) (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"印度英文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"塞爾維亞文 (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (傳統)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (斯拉夫文)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (拉丁文)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (精簡)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"無語言 (字母)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"字母 (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"字母 (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"字母 (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"字母 (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"表情符號"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"鍵盤主題"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"自訂輸入樣式"</string>
     <string name="add_style" msgid="6163126614514489951">"新增樣式"</string>
     <string name="add" msgid="8299699805688017798">"新增"</string>
@@ -129,14 +133,9 @@
     <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_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="4782116251651288054">"確定要安裝這個<xliff:g id="LANGUAGE_NAME">%s</xliff:g>檔案嗎?"</string>
-    <string name="error" msgid="8940763624668513648">"發生錯誤"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"按鍵長按延遲"</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>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"現在,您可以在自己喜愛的所有應用程式中使用「<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">"在啟動器中顯示應用程式圖示"</string>
     <string name="app_name" msgid="6320102637491234792">"字典提供者"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"字典提供者"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"字典服務"</string>
diff --git a/java/res/values-zu/strings-emoji-descriptions.xml b/java/res/values-zu/strings-emoji-descriptions.xml
new file mode 100644
index 0000000..d8f81bd
--- /dev/null
+++ b/java/res/values-zu/strings-emoji-descriptions.xml
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/*
+**
+** Copyright 2014, 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.
+*/
+ -->
+
+<!-- 
+    These Emoji symbols are unsupported by TTS.
+    TODO: Remove this file when TTS/TalkBack support these Emoji symbols.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="spoken_emoji_00A9" msgid="2859822817116803638">"Uphawu le-copyright"</string>
+    <string name="spoken_emoji_00AE" msgid="7708335454134589027">"Uphawu olubhalisiwe"</string>
+    <string name="spoken_emoji_203C" msgid="153340916701508663">"Isababazo kabili"</string>
+    <string name="spoken_emoji_2049" msgid="4877256448299555371">"Uphawu lesibabazo mbuzo"</string>
+    <string name="spoken_emoji_2122" msgid="9188440722954720429">"Uphawu lokuhweba"</string>
+    <string name="spoken_emoji_2139" msgid="9114342638917304327">"Umthombo wolwazi"</string>
+    <string name="spoken_emoji_2194" msgid="8055202727034946680">"Umcibisholo ongakwesokunxele-nakwesokudla"</string>
+    <string name="spoken_emoji_2195" msgid="8028122253301087407">"Umcibisholo obheke phezulu naphansi"</string>
+    <string name="spoken_emoji_2196" msgid="4019164898967854363">"Umcibisholo wenyakatho nentshonalanga"</string>
+    <string name="spoken_emoji_2197" msgid="4255723717709017801">"Umcibisholo wenyakatho nempumalanga"</string>
+    <string name="spoken_emoji_2198" msgid="1452063451313622090">"Umcibisholo weningizimu nempumalanga"</string>
+    <string name="spoken_emoji_2199" msgid="6942722693368807849">"Umcibisholo weningizimu nentshonalanga"</string>
+    <string name="spoken_emoji_21A9" msgid="5204750172335111188">"Umcibisholo ongakwesokunxele nehhuku"</string>
+    <string name="spoken_emoji_21AA" msgid="3950259884359247006">"Umcibisholo ongakwesokudla nehhuku"</string>
+    <string name="spoken_emoji_231A" msgid="6751448803233874993">"Buka"</string>
+    <string name="spoken_emoji_231B" msgid="5956428809948426182">"Ingilasi yesikhathi"</string>
+    <string name="spoken_emoji_23E9" msgid="4022497733535162237">"Unxande okabili omnyama obheke ngakwesokudla"</string>
+    <string name="spoken_emoji_23EA" msgid="2251396938087774944">"Unxande okabili omnyama obheke ngakwesokunxele"</string>
+    <string name="spoken_emoji_23EB" msgid="3746885195641491865">"Unxande okabili omnyama obheke ngaphezulu"</string>
+    <string name="spoken_emoji_23EC" msgid="7852372752901163416">"Unxande okabili omnyama obheke ngezansi"</string>
+    <string name="spoken_emoji_23F0" msgid="8474219588750627870">"Iwashi le-alamu"</string>
+    <string name="spoken_emoji_23F3" msgid="166900119581024371">"Ingilasi yesikhathi egeleza isihlabathi"</string>
+    <string name="spoken_emoji_24C2" msgid="3948348737566038470">"Igama elingu-m lofeleba oyingiliziwe"</string>
+    <string name="spoken_emoji_25AA" msgid="7865181015100227349">"Isikwele esincane esimnyama"</string>
+    <string name="spoken_emoji_25AB" msgid="6446532820937381457">"Isikwele esincane esimhlophe"</string>
+    <string name="spoken_emoji_25B6" msgid="2423897708496040947">"Unxande omnyama obheke ngakwesokudla"</string>
+    <string name="spoken_emoji_25C0" msgid="3595083440074484934">"Unxande omnyama obheke ngakwesokunxele"</string>
+    <string name="spoken_emoji_25FB" msgid="4838691986881215419">"Isikwele esimhlophe esimaphakathi"</string>
+    <string name="spoken_emoji_25FC" msgid="7008859564991191050">"Isikwele esimnyama esimaphakathi"</string>
+    <string name="spoken_emoji_25FD" msgid="7673439755069217479">"Isikwele esincane esimaphakathi esimhlophe"</string>
+    <string name="spoken_emoji_25FE" msgid="6782214109919768923">"Isikwele esincane esimaphakathi esimnyama"</string>
+    <string name="spoken_emoji_2600" msgid="2272722634618990413">"Ilanga elimnyama elinemisebe"</string>
+    <string name="spoken_emoji_2601" msgid="6205136889311537150">"Ifu"</string>
+    <string name="spoken_emoji_260E" msgid="8670395193046424238">"Ucingo olumnyama"</string>
+    <string name="spoken_emoji_2611" msgid="4530550203347054611">"Ibhokisi lokuvota nesheke"</string>
+    <string name="spoken_emoji_2614" msgid="1612791247861229500">"Isambulela esinamaconsi emvula"</string>
+    <string name="spoken_emoji_2615" msgid="3320562382424018588">"Isiphuzo esishisayo"</string>
+    <string name="spoken_emoji_261D" msgid="4690554173549768467">"Inkomba emhlophe ebheke phezulu"</string>
+    <string name="spoken_emoji_263A" msgid="3170094381521989300">"Ubuso obumhlophe obumomothekayo"</string>
+    <string name="spoken_emoji_2648" msgid="4621241062667020673">"I-Aries"</string>
+    <string name="spoken_emoji_2649" msgid="7694461245947059086">"I-Taurus"</string>
+    <string name="spoken_emoji_264A" msgid="1258074605878705030">"I-Gemini"</string>
+    <string name="spoken_emoji_264B" msgid="4409219914377810956">"I-Cancer"</string>
+    <string name="spoken_emoji_264C" msgid="6520255367817054163">"I-Leo"</string>
+    <string name="spoken_emoji_264D" msgid="1504758945499854018">"I-Virgo"</string>
+    <string name="spoken_emoji_264E" msgid="2354847104530633519">"I-Libra"</string>
+    <string name="spoken_emoji_264F" msgid="5822933280406416112">"I-Scorpius"</string>
+    <string name="spoken_emoji_2650" msgid="4832481156714796163">"I-Sagittarius"</string>
+    <string name="spoken_emoji_2651" msgid="840953134601595090">"I-Capricorn"</string>
+    <string name="spoken_emoji_2652" msgid="3586925968718775281">"I-Aquarius"</string>
+    <string name="spoken_emoji_2653" msgid="8420547731496254492">"I-Pisces"</string>
+    <string name="spoken_emoji_2660" msgid="4541170554542412536">"Isudi yesipedi esimnyama"</string>
+    <string name="spoken_emoji_2663" msgid="3669352721942285724">"Isudi yeklabhu emnyama"</string>
+    <string name="spoken_emoji_2665" msgid="6347941599683765843">"Isudi yenhliziyo emnyama"</string>
+    <string name="spoken_emoji_2666" msgid="8296769213401115999">"Isudi yedayimane elimnyama"</string>
+    <string name="spoken_emoji_2668" msgid="7063148281053820386">"Intwasanhlobo eshisayo"</string>
+    <string name="spoken_emoji_267B" msgid="21716857176812762">"Uphawu olumnyama lokusebenzisa kabusha jikelele"</string>
+    <string name="spoken_emoji_267F" msgid="8833496533226475443">"Uphawu lesihlalo sabakhubazekile"</string>
+    <string name="spoken_emoji_2693" msgid="7443148847598433088">"Ihange"</string>
+    <string name="spoken_emoji_26A0" msgid="6272635532992727510">"Uphawu lesexwayiso"</string>
+    <string name="spoken_emoji_26A1" msgid="5604749644693339145">"Uphawu lesilinganiso sikagesi esiphezulu"</string>
+    <string name="spoken_emoji_26AA" msgid="8005748091690377153">"Isiyingi esimhlophe okumaphakathi"</string>
+    <string name="spoken_emoji_26AB" msgid="1655910278422753244">"Isiyingi esimaphakathi esimnyama"</string>
+    <string name="spoken_emoji_26BD" msgid="1545218197938889737">"Ibhola lezinyawo"</string>
+    <string name="spoken_emoji_26BE" msgid="8959760533076498209">"I-Baseball"</string>
+    <string name="spoken_emoji_26C4" msgid="3045791757044255626">"Indoda yeqhwa engenalo iqhwa"</string>
+    <string name="spoken_emoji_26C5" msgid="5580129409712578639">"Ilanga ngemva kwefu"</string>
+    <string name="spoken_emoji_26CE" msgid="8963656417276062998">"I-Ophiuchus"</string>
+    <string name="spoken_emoji_26D4" msgid="2231451988209604130">"Akungenwa"</string>
+    <string name="spoken_emoji_26EA" msgid="7513319636103804907">"Isonto"</string>
+    <string name="spoken_emoji_26F2" msgid="7134115206158891037">"Umthombo"</string>
+    <string name="spoken_emoji_26F3" msgid="4912302210162075465">"Ifulegi kwimbobo"</string>
+    <string name="spoken_emoji_26F5" msgid="4766328116769075217">"Isikebhe"</string>
+    <string name="spoken_emoji_26FA" msgid="5888017494809199037">"Itende"</string>
+    <string name="spoken_emoji_26FD" msgid="2417060622927453534">"Isifutho sophethiloli"</string>
+    <string name="spoken_emoji_2702" msgid="4005741160717451912">"Izikele ezimnyama"</string>
+    <string name="spoken_emoji_2705" msgid="164605766946697759">"Uphawu lokuhlola olusindayo olumhlophe"</string>
+    <string name="spoken_emoji_2708" msgid="7153840886849268988">"Indiza"</string>
+    <string name="spoken_emoji_2709" msgid="2217319160724311369">"Imvilophi"</string>
+    <string name="spoken_emoji_270A" msgid="508347232762319473">"Ingqindi ephakanyisiwe"</string>
+    <string name="spoken_emoji_270B" msgid="6640562128327753423">"Isandla esiphakamisiwe"</string>
+    <string name="spoken_emoji_270C" msgid="1344288035704944581">"Isandla sokunqoba"</string>
+    <string name="spoken_emoji_270F" msgid="6108251586067318718">"Umsizi"</string>
+    <string name="spoken_emoji_2712" msgid="6320544535087710482">"Inibhu emnyama"</string>
+    <string name="spoken_emoji_2714" msgid="1968242800064001654">"Uphawu lokuhlola olusindayo"</string>
+    <string name="spoken_emoji_2716" msgid="511941294762977228">"U-x wokuphinda osindayo"</string>
+    <string name="spoken_emoji_2728" msgid="5650330815808691881">"Ukucwebezela"</string>
+    <string name="spoken_emoji_2733" msgid="8915809595141157327">"Izinkanyezi ezihlanganisiwe eziyisishiyagalombili"</string>
+    <string name="spoken_emoji_2734" msgid="4846583547980754332">"Inkanyezi emnyama yamaphoyinti ayisishiyagalombili"</string>
+    <string name="spoken_emoji_2744" msgid="4350636647760161042">"Iqhwa"</string>
+    <string name="spoken_emoji_2747" msgid="3718282973916474455">"Ukukhazimula"</string>
+    <string name="spoken_emoji_274C" msgid="2752145886733295314">"Uphawu lokushayisana"</string>
+    <string name="spoken_emoji_274E" msgid="4262918689871098338">"Uphawu lokushayisana lesikwele esingesihle"</string>
+    <string name="spoken_emoji_2753" msgid="6935897159942119808">"Umhlobiso wophawu lombuzo olumnyama"</string>
+    <string name="spoken_emoji_2754" msgid="7277504915105532954">"Umhlobiso wophawu lombuzo omhlophe"</string>
+    <string name="spoken_emoji_2755" msgid="6853076969826960210">"Umhlobisi wesibabazo esimhlophe"</string>
+    <string name="spoken_emoji_2757" msgid="3707907828776912174">"Uphawu lesibabazo olusindayo"</string>
+    <string name="spoken_emoji_2764" msgid="4214257843609432167">"Inhliziyo emnyama esindayo"</string>
+    <string name="spoken_emoji_2795" msgid="6563954833786162168">"Uphawu lokuhlanganisa olusindayo"</string>
+    <string name="spoken_emoji_2796" msgid="5990926508250772777">"Uphawu lokususa olusindayo"</string>
+    <string name="spoken_emoji_2797" msgid="24694184172879174">"Uphawu lokwehlukanisa olusindayo"</string>
+    <string name="spoken_emoji_27A1" msgid="3513434778263100580">"Umcibisholo ongakwesokudla omnyama"</string>
+    <string name="spoken_emoji_27B0" msgid="203395646864662198">"Umumo otshekile"</string>
+    <string name="spoken_emoji_27BF" msgid="4940514642375640510">"Umumo otshekile kabili"</string>
+    <string name="spoken_emoji_2934" msgid="9062130477982973457">"Umcibisholo obheke ngakwesokudla bese watsheka ngaphezulu"</string>
+    <string name="spoken_emoji_2935" msgid="6198710960720232074">"Umcibisholo obheke ngakwesokudla bese watsheka ngezansi"</string>
+    <string name="spoken_emoji_2B05" msgid="4813405635410707690">"Umcibisholo omnyama ongakwesokunxele"</string>
+    <string name="spoken_emoji_2B06" msgid="1223172079106250748">"Umncibisholo omnyama ongaphezulu"</string>
+    <string name="spoken_emoji_2B07" msgid="1599124424746596150">"Umcibisholo omnyama obheke phansi"</string>
+    <string name="spoken_emoji_2B1B" msgid="3461247311988501626">"Isikwele esikhulu esimnyama"</string>
+    <string name="spoken_emoji_2B1C" msgid="5793146430145248915">"Isikwele esikhulu esimhlophe"</string>
+    <string name="spoken_emoji_2B50" msgid="3850845519526950524">"Inkanyezi emaphakathi emhlophe"</string>
+    <string name="spoken_emoji_2B55" msgid="9137882158811541824">"Isiyingi esikhulu esisindayo"</string>
+    <string name="spoken_emoji_3030" msgid="4609172241893565639">"I-Wavy dash"</string>
+    <string name="spoken_emoji_303D" msgid="2545833934975907505">"Olunye uphawu lwengxenye"</string>
+    <string name="spoken_emoji_3297" msgid="928912923628973800">"Ukuhalalisa i-ideograph eyisiyingi"</string>
+    <string name="spoken_emoji_3299" msgid="3930347573693668426">"Imfihlo ye-ideograph eyisilingi"</string>
+    <string name="spoken_emoji_1F004" msgid="1705216181345894600">"Isilo esibomvu sethayili ye-Mahjong"</string>
+    <string name="spoken_emoji_1F0CF" msgid="7601493592085987866">"Ukudlala ikhadi le-joker omnyama"</string>
+    <string name="spoken_emoji_1F170" msgid="3817698686602826773">"Uhlobo legazi A"</string>
+    <string name="spoken_emoji_1F171" msgid="3684218589626650242">"Uhlobo legazi B"</string>
+    <string name="spoken_emoji_1F17E" msgid="2978809190364779029">"Uhlobo legazi O"</string>
+    <string name="spoken_emoji_1F17F" msgid="463634348668462040">"Indawo yokupaka"</string>
+    <string name="spoken_emoji_1F18E" msgid="1650705325221496768">"Uhlobo legazi AB"</string>
+    <string name="spoken_emoji_1F191" msgid="5386969264431429221">"I-CL eyisikwele"</string>
+    <string name="spoken_emoji_1F192" msgid="8324226436829162496">"Okupholile okuyisikwele"</string>
+    <string name="spoken_emoji_1F193" msgid="4731758603321515364">"Okuyisikwele kwamahhala"</string>
+    <string name="spoken_emoji_1F194" msgid="4903128609556175887">"I-ID eyisikwele"</string>
+    <string name="spoken_emoji_1F195" msgid="1433142500411060924">"Okuyisikwele okusha"</string>
+    <string name="spoken_emoji_1F196" msgid="8825160701159634202">"I-N G eyisikwele"</string>
+    <string name="spoken_emoji_1F197" msgid="7841079241554176535">"U-OK oyisikwele"</string>
+    <string name="spoken_emoji_1F198" msgid="7020298909426960622">"I-SOS eyisikwele"</string>
+    <string name="spoken_emoji_1F199" msgid="5971252667136235630">"Kuhlanganiswe nophawu lesibabazo"</string>
+    <string name="spoken_emoji_1F19A" msgid="4557270135899843959">"Okuyisikwele okumelene"</string>
+    <string name="spoken_emoji_1F201" msgid="7000490044681139002">"I-katakana eyisikwele lapha"</string>
+    <string name="spoken_emoji_1F202" msgid="8560906958695043947">"Isevisi ye-katakana eyisikwele"</string>
+    <string name="spoken_emoji_1F21A" msgid="1496435317324514033">"Inani lamahhala le-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F22F" msgid="609797148862445402">"Isihlalo esibekiwe se-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F232" msgid="8125716331632035820">"Ukuvinjelwa kwe-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F233" msgid="8749401090457355028">"Isikhala se-ideography eyisikwele"</string>
+    <string name="spoken_emoji_1F234" msgid="3546951604285970768">"Ukwamukelwa kwe-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F235" msgid="5320186982841793711">"Ukusetshenziswa ngokugcwele kwe-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F236" msgid="879755752069393034">"I-Ideograph eyisikwele ekhokhelwe"</string>
+    <string name="spoken_emoji_1F237" msgid="6741807001205851437">"I-Ideography eyisikwele yanyanga zonke"</string>
+    <string name="spoken_emoji_1F238" msgid="5504414186438196912">"Uhlelo lokusebenza le-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F239" msgid="1634067311597618959">"Isaphulelo se-ideograph eyisikwele"</string>
+    <string name="spoken_emoji_1F23A" msgid="3107862957630169536">"I-Ideograph eyisikwele kwezamabhizinisi"</string>
+    <string name="spoken_emoji_1F250" msgid="6586943922806727907">"Inzuzo ye-ideograph eyisiyingi"</string>
+    <string name="spoken_emoji_1F251" msgid="9099032855993346948">"Ukwamukela i-ideograph eyisiyingi"</string>
+    <string name="spoken_emoji_1F300" msgid="4720098285295840383">"Isihlwithi"</string>
+    <string name="spoken_emoji_1F301" msgid="3601962477653752974">"Nenkungu"</string>
+    <string name="spoken_emoji_1F302" msgid="3404357123421753593">"Isambulela esivaliwe"</string>
+    <string name="spoken_emoji_1F303" msgid="3899301321538188206">"Ubusuku obunezinkanyezi"</string>
+    <string name="spoken_emoji_1F304" msgid="2767148930689050040">"Ukuphuma kwelanga ezintabeni"</string>
+    <string name="spoken_emoji_1F305" msgid="9165812924292061196">"Ukuphuma kwelanga"</string>
+    <string name="spoken_emoji_1F306" msgid="5889294736109193104">"Ukubonakala kwedolobha lapho kuhlwa"</string>
+    <string name="spoken_emoji_1F307" msgid="2714290867291163713">"Ukushona kwelanga emabhilidini"</string>
+    <string name="spoken_emoji_1F308" msgid="688704703985173377">"Uthingo lwenkosazane"</string>
+    <string name="spoken_emoji_1F309" msgid="6217981957992313528">"Ibhuloho ebusuku"</string>
+    <string name="spoken_emoji_1F30A" msgid="4329309263152110893">"Igagasi lamanzi"</string>
+    <string name="spoken_emoji_1F30B" msgid="5729430693700923112">"Intabamlilo"</string>
+    <string name="spoken_emoji_1F30C" msgid="2961230863217543082">"Umthamo wezinkanyezi"</string>
+    <string name="spoken_emoji_1F30D" msgid="1113905673331547953">"Imbulunga yomhlaba waseyurophu ne-afrika"</string>
+    <string name="spoken_emoji_1F30E" msgid="5278512600749223671">"I-Amelika yembulunga yomhlaba"</string>
+    <string name="spoken_emoji_1F30F" msgid="5718144880978707493">"Imbulunga yomhlaba we-asia-australia"</string>
+    <string name="spoken_emoji_1F310" msgid="2959618582975247601">"Imbulunga ye-meridians"</string>
+    <string name="spoken_emoji_1F311" msgid="623906380914895542">"Uphawu lenyanga entsha"</string>
+    <string name="spoken_emoji_1F312" msgid="4458575672576125401">"Uphawu locwezana lenyanga egcwele"</string>
+    <string name="spoken_emoji_1F313" msgid="7599181787989497294">"Uphawu lenyanga yekota yokuqala"</string>
+    <string name="spoken_emoji_1F314" msgid="4898293184964365413">"Uphawu lenyanga egcwele ye-gibbous"</string>
+    <string name="spoken_emoji_1F315" msgid="3218117051779496309">"Uphawu lenyanga egcwele"</string>
+    <string name="spoken_emoji_1F316" msgid="2061317145777689569">"Uphawu lenyanga ye-gibbous eyehlayo"</string>
+    <string name="spoken_emoji_1F317" msgid="2721090687319539049">"Uphawu lenyanga yekota yokugcina"</string>
+    <string name="spoken_emoji_1F318" msgid="3814091755648887570">"Uphawu lenyanga yocwezana olwehlayo"</string>
+    <string name="spoken_emoji_1F319" msgid="4074299824890459465">"Ucwezana lenyanga"</string>
+    <string name="spoken_emoji_1F31A" msgid="3092285278116977103">"Inyanga entsha enobuso"</string>
+    <string name="spoken_emoji_1F31B" msgid="2658562138386927881">"Inyanga yekota yokuqala enobuso"</string>
+    <string name="spoken_emoji_1F31C" msgid="7914768515547867384">"Inyanga yekota yokugcina enobuso"</string>
+    <string name="spoken_emoji_1F31D" msgid="1925730459848297182">"Inyanga egcwele enobuso"</string>
+    <string name="spoken_emoji_1F31E" msgid="8022112382524084418">"Ilanga elinobuso"</string>
+    <string name="spoken_emoji_1F31F" msgid="1051661214137766369">"Inkanyezi ekhazimulayo"</string>
+    <string name="spoken_emoji_1F320" msgid="5450591979068216115">"Inkanyezi entwizayo"</string>
+    <string name="spoken_emoji_1F330" msgid="3115760035618051575">"I-Chestnut"</string>
+    <string name="spoken_emoji_1F331" msgid="5658888205290008691">"Isithombo"</string>
+    <string name="spoken_emoji_1F332" msgid="2935650450421165938">"Isihlahla esihlale siluhlaza"</string>
+    <string name="spoken_emoji_1F333" msgid="5898847427062482675">"Isihlahla esibunayo"</string>
+    <string name="spoken_emoji_1F334" msgid="6183375224678417894">"Isundu"</string>
+    <string name="spoken_emoji_1F335" msgid="5352418412103584941">"Umdolofiya"</string>
+    <string name="spoken_emoji_1F337" msgid="3839107352363566289">"I-Tulip"</string>
+    <string name="spoken_emoji_1F338" msgid="6389970364260468490">"Isithundu samathanduluka"</string>
+    <string name="spoken_emoji_1F339" msgid="9128891447985256151">"Irozi"</string>
+    <string name="spoken_emoji_1F33A" msgid="2025828400095233078">"I-Hibiscus"</string>
+    <string name="spoken_emoji_1F33B" msgid="8163868254348448552">"Ujikanelanga"</string>
+    <string name="spoken_emoji_1F33C" msgid="6850371206262335812">"Imbali"</string>
+    <string name="spoken_emoji_1F33D" msgid="9033484052864509610">"Indlebe yombila"</string>
+    <string name="spoken_emoji_1F33E" msgid="2540173396638444120">"Indlebe yelayisi"</string>
+    <string name="spoken_emoji_1F33F" msgid="4384823344364908558">"Isithombo"</string>
+    <string name="spoken_emoji_1F340" msgid="3494255459156499305">"I-Clover yamacembe amane"</string>
+    <string name="spoken_emoji_1F341" msgid="4581959481754990158">"Icembe le-maple"</string>
+    <string name="spoken_emoji_1F342" msgid="3119068426871821222">"Icembe eliwile"</string>
+    <string name="spoken_emoji_1F343" msgid="2663317495805149004">"Icembe eliphephezela emoyeni"</string>
+    <string name="spoken_emoji_1F344" msgid="2738517881678722159">"Inkowankowane"</string>
+    <string name="spoken_emoji_1F345" msgid="6135288642349085554">"Utamatisi"</string>
+    <string name="spoken_emoji_1F346" msgid="2075395322785406367">"I-Aubergine"</string>
+    <string name="spoken_emoji_1F347" msgid="7753453754963890571">"Amagilebhisi"</string>
+    <string name="spoken_emoji_1F348" msgid="1247076837284932788">"Ikhabe"</string>
+    <string name="spoken_emoji_1F349" msgid="5563054555180611086">"Ikhabe"</string>
+    <string name="spoken_emoji_1F34A" msgid="4688661208570160524">"I-Tangerine"</string>
+    <string name="spoken_emoji_1F34B" msgid="4335318423164185706">"Ilamuni"</string>
+    <string name="spoken_emoji_1F34C" msgid="3712827239858159474">"Ubhanana"</string>
+    <string name="spoken_emoji_1F34D" msgid="7712521967162622936">"Uphayinaphu"</string>
+    <string name="spoken_emoji_1F34E" msgid="1859466882598614228">"I-Apula elibomvu"</string>
+    <string name="spoken_emoji_1F34F" msgid="8251711032295005633">"I-Apula eliluhlaza okotshani"</string>
+    <string name="spoken_emoji_1F350" msgid="625802980159197701">"Iganandoda"</string>
+    <string name="spoken_emoji_1F351" msgid="4269460120610911895">"Ipentshisi"</string>
+    <string name="spoken_emoji_1F352" msgid="965600953360182635">"Amasheri"</string>
+    <string name="spoken_emoji_1F353" msgid="7068623879906925592">"Ijikijolo"</string>
+    <string name="spoken_emoji_1F354" msgid="45162285238888494">"I-Hamburger"</string>
+    <string name="spoken_emoji_1F355" msgid="9157587635526433283">"Ucezu le-pizza"</string>
+    <string name="spoken_emoji_1F356" msgid="2667196119149852244">"Inyama enethambo"</string>
+    <string name="spoken_emoji_1F357" msgid="8022817413851052256">"Umlenze wenkukhu"</string>
+    <string name="spoken_emoji_1F358" msgid="3042693264748036476">"Ikhekhe lelayisi"</string>
+    <string name="spoken_emoji_1F359" msgid="3988148661730121958">"Ilayisi eliyibhola"</string>
+    <string name="spoken_emoji_1F35A" msgid="1763824172198327268">"Ilayisi eliphekiwe"</string>
+    <string name="spoken_emoji_1F35B" msgid="62530406745717835">"Inani nelayisi"</string>
+    <string name="spoken_emoji_1F35C" msgid="7537756539198945509">"Isitsha sokubilisa"</string>
+    <string name="spoken_emoji_1F35D" msgid="8173523083861875196">"I-Spaghetti"</string>
+    <string name="spoken_emoji_1F35E" msgid="2935428307894662571">"Isinkwa"</string>
+    <string name="spoken_emoji_1F35F" msgid="4840297386785728443">"Amazambane athosiwe"</string>
+    <string name="spoken_emoji_1F360" msgid="4094659855684686801">"Ubhatata oyosiwe"</string>
+    <string name="spoken_emoji_1F361" msgid="6475486395784096109">"I-Dango"</string>
+    <string name="spoken_emoji_1F362" msgid="5004692577661076275">"I-Oden"</string>
+    <string name="spoken_emoji_1F363" msgid="1606603765717743806">"I-Sushi"</string>
+    <string name="spoken_emoji_1F364" msgid="6550457766169570811">"Imbaza ethosiwe"</string>
+    <string name="spoken_emoji_1F365" msgid="4963815540953316307">"Ikhekhe lenhlanzi elidizayinwe ngendlela eyaluzayo"</string>
+    <string name="spoken_emoji_1F366" msgid="7862401745277049404">"I-Asikhilimu ethambile"</string>
+    <string name="spoken_emoji_1F367" msgid="7447972978281980414">"Iqhwa eliphuciwe"</string>
+    <string name="spoken_emoji_1F368" msgid="7790003146142724913">"U-Ayisikhilimu"</string>
+    <string name="spoken_emoji_1F369" msgid="7383712944084857350">"Idonathi"</string>
+    <string name="spoken_emoji_1F36A" msgid="2726271795913042295">"Ikhukhi"</string>
+    <string name="spoken_emoji_1F36B" msgid="6342163604299875931">"Ibha yoshokholethi"</string>
+    <string name="spoken_emoji_1F36C" msgid="2168934753998218790">"Uswidi"</string>
+    <string name="spoken_emoji_1F36D" msgid="3671507903799975792">"I-Lollipop"</string>
+    <string name="spoken_emoji_1F36E" msgid="4630541402785165902">"Ukhastadi"</string>
+    <string name="spoken_emoji_1F36F" msgid="5577915387425169439">"Ibhodwe loju"</string>
+    <string name="spoken_emoji_1F370" msgid="7243244547866114951">"Okusaswidi"</string>
+    <string name="spoken_emoji_1F371" msgid="6731527040552916358">"Ibhokisi le-Bento"</string>
+    <string name="spoken_emoji_1F372" msgid="1635035323832181733">"Imbiza yokudla"</string>
+    <string name="spoken_emoji_1F373" msgid="7799289534289221045">"Ukupheka"</string>
+    <string name="spoken_emoji_1F374" msgid="5973820884987069131">"Imfoloko nommese"</string>
+    <string name="spoken_emoji_1F375" msgid="1074832087699617700">"Inkomishi engenaso isibambo"</string>
+    <string name="spoken_emoji_1F376" msgid="6499274685584852067">"Ibhodlela le-Sake nenkomishi"</string>
+    <string name="spoken_emoji_1F377" msgid="1762398562314172075">"Ingilasi yewayini"</string>
+    <string name="spoken_emoji_1F378" msgid="5528234560590117516">"Ingilasi ye-cocktail"</string>
+    <string name="spoken_emoji_1F379" msgid="790581290787943325">"Isiphuzo esinoshukela"</string>
+    <string name="spoken_emoji_1F37A" msgid="391966822450619516">"Inkomishi yobhiya"</string>
+    <string name="spoken_emoji_1F37B" msgid="9015043286465670662">"Ukuqhafaza izinkomishi zobhiya"</string>
+    <string name="spoken_emoji_1F37C" msgid="2532113819464508894">"Ibhodlela lomntwana"</string>
+    <string name="spoken_emoji_1F380" msgid="3487363857092458827">"Iribhoni"</string>
+    <string name="spoken_emoji_1F381" msgid="614180683680675444">"Isipho esigoqiwe"</string>
+    <string name="spoken_emoji_1F382" msgid="4720497171946687501">"Ikhekhe losuku lokuzalwa"</string>
+    <string name="spoken_emoji_1F383" msgid="3536505941578757623">"I-Jack-o-lantern"</string>
+    <string name="spoken_emoji_1F384" msgid="1797870204479059004">"Isihlahla sikakhisimusi"</string>
+    <string name="spoken_emoji_1F385" msgid="1754174063483626367">"Indoda yokhisimusi"</string>
+    <string name="spoken_emoji_1F386" msgid="2130445450758114746">"Iziqhumane"</string>
+    <string name="spoken_emoji_1F387" msgid="3403182563117999933">"Iziqhumane ezibanikayo"</string>
+    <string name="spoken_emoji_1F388" msgid="2903047203723251804">"Ibhamuza"</string>
+    <string name="spoken_emoji_1F389" msgid="2352830665883549388">"Umuntu oqeda ubumnandi"</string>
+    <string name="spoken_emoji_1F38A" msgid="6280428984773641322">"Ibhola le-confetti"</string>
+    <string name="spoken_emoji_1F38B" msgid="4902225837479015489">"Isihlahla se-Tanabata"</string>
+    <string name="spoken_emoji_1F38C" msgid="7623268024030989365">"Amafulegi ashayisanayo"</string>
+    <string name="spoken_emoji_1F38D" msgid="8237542796124408528">"Umhlobiso wephayini"</string>
+    <string name="spoken_emoji_1F38E" msgid="5373397476238212371">"Onodoli besi-Japanese"</string>
+    <string name="spoken_emoji_1F38F" msgid="8754091376829552844">"I-Carp streamer"</string>
+    <string name="spoken_emoji_1F390" msgid="8903307048095431374">"Ushimula"</string>
+    <string name="spoken_emoji_1F391" msgid="2134952069191911841">"Umkhosi wokubuka inyanga"</string>
+    <string name="spoken_emoji_1F392" msgid="6380405493914304737">"Isikhwama sesikole"</string>
+    <string name="spoken_emoji_1F393" msgid="6947890064872470996">"Isigqoko sokuthweswa iziqu"</string>
+    <string name="spoken_emoji_1F3A0" msgid="3572095190082826057">"Umbukiso wamahhashi"</string>
+    <string name="spoken_emoji_1F3A1" msgid="4300565511681058798">"Isondo lasepaki lokuzijabulisa"</string>
+    <string name="spoken_emoji_1F3A2" msgid="15486093912232140">"I-Roller coaster"</string>
+    <string name="spoken_emoji_1F3A3" msgid="921739319504942924">"Induku yokudoba nenhlanzi"</string>
+    <string name="spoken_emoji_1F3A4" msgid="7497596355346856950">"Imakrofoni"</string>
+    <string name="spoken_emoji_1F3A5" msgid="4290497821228183002">"Ikhamela ye-movie"</string>
+    <string name="spoken_emoji_1F3A6" msgid="26019057872319055">"Ibhayisikobho"</string>
+    <string name="spoken_emoji_1F3A7" msgid="837856608794094105">"Ihedfoni"</string>
+    <string name="spoken_emoji_1F3A8" msgid="2332260356509244587">"Iseceshana sompendi sokufaka upende"</string>
+    <string name="spoken_emoji_1F3A9" msgid="9045869366525115256">"Isigqoko esiphezulu"</string>
+    <string name="spoken_emoji_1F3AA" msgid="5728760354237132">"Itende lesekisi"</string>
+    <string name="spoken_emoji_1F3AB" msgid="1657997517193216284">"Ithikithi"</string>
+    <string name="spoken_emoji_1F3AC" msgid="4317366554314492152">"Idivayisi yokwenza ifilimu"</string>
+    <string name="spoken_emoji_1F3AD" msgid="607157286336130470">"Ukwenza ubuciko"</string>
+    <string name="spoken_emoji_1F3AE" msgid="2902308174671548150">"Igeyimu yevidiyo"</string>
+    <string name="spoken_emoji_1F3AF" msgid="5420539221790296407">"Ukushaya ngokuqondile"</string>
+    <string name="spoken_emoji_1F3B0" msgid="7440244806527891956">"Umshini wokugembula"</string>
+    <string name="spoken_emoji_1F3B1" msgid="545544382391379234">"Ama-Billiard"</string>
+    <string name="spoken_emoji_1F3B2" msgid="8302262034774787493">"Igeyimu yokufa"</string>
+    <string name="spoken_emoji_1F3B3" msgid="5180870610771027520">"I-Bowling"</string>
+    <string name="spoken_emoji_1F3B4" msgid="4723852033266071564">"Imbali yokudlala amakhadi"</string>
+    <string name="spoken_emoji_1F3B5" msgid="1998470239850548554">"Inothi yomculo"</string>
+    <string name="spoken_emoji_1F3B6" msgid="3827730457113941705">"Amanothi omculo amaningi"</string>
+    <string name="spoken_emoji_1F3B7" msgid="5503403099445042180">"Icilongo"</string>
+    <string name="spoken_emoji_1F3B8" msgid="3985658156795011430">"Isiginci"</string>
+    <string name="spoken_emoji_1F3B9" msgid="5596295757967881451">"Ikhibhodi yomculo"</string>
+    <string name="spoken_emoji_1F3BA" msgid="4284064120340683558">"Ithrampethi"</string>
+    <string name="spoken_emoji_1F3BB" msgid="2856598510069988745">"Ivayolini"</string>
+    <string name="spoken_emoji_1F3BC" msgid="1608424748821446230">"Isikolo somculo"</string>
+    <string name="spoken_emoji_1F3BD" msgid="5490786111375627777">"Ihembe lokugijima elinebhande"</string>
+    <string name="spoken_emoji_1F3BE" msgid="1851613105691627931">"Irakhethi yethenisi nebhola"</string>
+    <string name="spoken_emoji_1F3BF" msgid="6862405997423247921">"Ukusheleleza eqhweni nezicathulo zokusheleleza"</string>
+    <string name="spoken_emoji_1F3C0" msgid="7421420756115104085">"I-Basketball ne-hoop"</string>
+    <string name="spoken_emoji_1F3C1" msgid="6926537251677319922">"Ifulegi lemibala eminingi"</string>
+    <string name="spoken_emoji_1F3C2" msgid="5708596929237987082">"Ibhodi lokusheleleza eqhweni"</string>
+    <string name="spoken_emoji_1F3C3" msgid="5850982999510115824">"Umgijimi"</string>
+    <string name="spoken_emoji_1F3C4" msgid="8468355585994639838">"Umtshuzi"</string>
+    <string name="spoken_emoji_1F3C6" msgid="9094474706847545409">"Indondo"</string>
+    <string name="spoken_emoji_1F3C7" msgid="8172206200368370116">"Umjaho wamahhashi"</string>
+    <string name="spoken_emoji_1F3C8" msgid="5619171461277597709">"Ibhola lase-America"</string>
+    <string name="spoken_emoji_1F3C9" msgid="6371294008765871043">"Ibhola lombhoxo"</string>
+    <string name="spoken_emoji_1F3CA" msgid="130977831787806932">"Umbhukudi"</string>
+    <string name="spoken_emoji_1F3E0" msgid="6277213201655811842">"Isakhiwo sendlu"</string>
+    <string name="spoken_emoji_1F3E1" msgid="233476176077538885">"Indlu enengadi"</string>
+    <string name="spoken_emoji_1F3E2" msgid="919736380093964570">"Ibhilidi lehhovisi"</string>
+    <string name="spoken_emoji_1F3E3" msgid="6177606081825094184">"Iposi lase-Japanese"</string>
+    <string name="spoken_emoji_1F3E4" msgid="717377871070970293">"Iposi lase-European"</string>
+    <string name="spoken_emoji_1F3E5" msgid="1350532500431776780">"Isibhedlela"</string>
+    <string name="spoken_emoji_1F3E6" msgid="342132788513806214">"Ibhange"</string>
+    <string name="spoken_emoji_1F3E7" msgid="6322352038284944265">"Umshini ozenzakalelayo womthengisi"</string>
+    <string name="spoken_emoji_1F3E8" msgid="5864918444350599907">"Ihotela"</string>
+    <string name="spoken_emoji_1F3E9" msgid="7830416185375326938">"Ihotela lothando"</string>
+    <string name="spoken_emoji_1F3EA" msgid="5081084413084360479">"Isitolo esiphethe zonke izinto"</string>
+    <string name="spoken_emoji_1F3EB" msgid="7010966528205150525">"Isikole"</string>
+    <string name="spoken_emoji_1F3EC" msgid="4845978861878295154">"Isitolo somnyango"</string>
+    <string name="spoken_emoji_1F3ED" msgid="3980316226665215370">"Imboni"</string>
+    <string name="spoken_emoji_1F3EE" msgid="1253964276770550248">"I-Izakaya lantern"</string>
+    <string name="spoken_emoji_1F3EF" msgid="1128975573507389883">"Inqaba yesi-Japanese"</string>
+    <string name="spoken_emoji_1F3F0" msgid="1544632297502291578">"Inqaba yesi-European"</string>
+    <string name="spoken_emoji_1F400" msgid="2063034795679578294">"Igundane"</string>
+    <string name="spoken_emoji_1F401" msgid="6736421616217369594">"Igundane"</string>
+    <string name="spoken_emoji_1F402" msgid="7276670995895485604">"Inkabi"</string>
+    <string name="spoken_emoji_1F403" msgid="8045709541897118928">"Izinyathi"</string>
+    <string name="spoken_emoji_1F404" msgid="5240777285676662335">"Inkomo"</string>
+    <string name="spoken_emoji_1F406" msgid="5163461930159540018">"Ingwe"</string>
+    <string name="spoken_emoji_1F407" msgid="6905370221172708160">"Unogwaja"</string>
+    <string name="spoken_emoji_1F408" msgid="1362164550508207284">"Ikati"</string>
+    <string name="spoken_emoji_1F409" msgid="8476130983168866013">"Isilo"</string>
+    <string name="spoken_emoji_1F40A" msgid="1149626786411545043">"Ingwenya"</string>
+    <string name="spoken_emoji_1F40B" msgid="5199104921208397643">"Umkhomo"</string>
+    <string name="spoken_emoji_1F40C" msgid="2704006052881702675">"Umnenke"</string>
+    <string name="spoken_emoji_1F40D" msgid="8648186663643157522">"Inyoka"</string>
+    <string name="spoken_emoji_1F40E" msgid="7219137467573327268">"Ihhashi"</string>
+    <string name="spoken_emoji_1F40F" msgid="7834336676729040395">"Inyamazane yenduna"</string>
+    <string name="spoken_emoji_1F410" msgid="8686765722255775031">"Imbuzi"</string>
+    <string name="spoken_emoji_1F411" msgid="3585715397876383525">"Imvu"</string>
+    <string name="spoken_emoji_1F412" msgid="4924794582980077838">"Inkawu"</string>
+    <string name="spoken_emoji_1F413" msgid="1460475310405677377">"Iqhude"</string>
+    <string name="spoken_emoji_1F414" msgid="5857296282631892219">"Inkukhu"</string>
+    <string name="spoken_emoji_1F415" msgid="5920041074892949527">"Inja"</string>
+    <string name="spoken_emoji_1F416" msgid="4362403392912540286">"Ingulube"</string>
+    <string name="spoken_emoji_1F417" msgid="6836978415840795128">"Izingulube"</string>
+    <string name="spoken_emoji_1F418" msgid="7926161463897783691">"Indlovu"</string>
+    <string name="spoken_emoji_1F419" msgid="1055233959755784186">"Ingwane"</string>
+    <string name="spoken_emoji_1F41A" msgid="5195666556511558060">"I-Shell Spiral"</string>
+    <string name="spoken_emoji_1F41B" msgid="7652480167465557832">"Imbungulu"</string>
+    <string name="spoken_emoji_1F41C" msgid="1123461148697574239">"Intuthwane"</string>
+    <string name="spoken_emoji_1F41D" msgid="718579308764058851">"Inyosi"</string>
+    <string name="spoken_emoji_1F41E" msgid="6766305509608115467">"Omanqulwane"</string>
+    <string name="spoken_emoji_1F41F" msgid="1207261298343160838">"Inhlanzi"</string>
+    <string name="spoken_emoji_1F420" msgid="1041145003133609221">"Inhlanzi yasendaweni eshisayo"</string>
+    <string name="spoken_emoji_1F421" msgid="1748378324417438751">"I-Blowfish"</string>
+    <string name="spoken_emoji_1F422" msgid="4106724877523329148">"Ufudu"</string>
+    <string name="spoken_emoji_1F423" msgid="4077407945958691907">"Ukuchamisela ichwane"</string>
+    <string name="spoken_emoji_1F424" msgid="6911326019270172283">"Ichwane"</string>
+    <string name="spoken_emoji_1F425" msgid="5466514196557885577">"Ichwane elibheke ngaphambili"</string>
+    <string name="spoken_emoji_1F426" msgid="2163979138772892755">"Inyoni"</string>
+    <string name="spoken_emoji_1F427" msgid="3585670324511212961">"Ihlengethwa"</string>
+    <string name="spoken_emoji_1F428" msgid="7955440808647898579">"I-Koala"</string>
+    <string name="spoken_emoji_1F429" msgid="5028269352809819035">"Uhlobo ou"</string>
+    <string name="spoken_emoji_1F42A" msgid="4681926706404032484">"Ikamela le-Dromedary"</string>
+    <string name="spoken_emoji_1F42B" msgid="2725166074981558322">"Ikamela le-Bactrian"</string>
+    <string name="spoken_emoji_1F42C" msgid="6764791873413727085">"Ihlengethwa"</string>
+    <string name="spoken_emoji_1F42D" msgid="1033643138546864251">"Ubuso begundane"</string>
+    <string name="spoken_emoji_1F42E" msgid="8099223337120508820">"Ubuso benkomo"</string>
+    <string name="spoken_emoji_1F42F" msgid="2104743989330781572">"Ingwe"</string>
+    <string name="spoken_emoji_1F430" msgid="525492897063150160">"Ubuso bonogwaja"</string>
+    <string name="spoken_emoji_1F431" msgid="6051358666235016851">"Ubuso bekati"</string>
+    <string name="spoken_emoji_1F432" msgid="7698001871193018305">"Ubuso besilo"</string>
+    <string name="spoken_emoji_1F433" msgid="3762356053512899326">"Umkhomo otshuzayo"</string>
+    <string name="spoken_emoji_1F434" msgid="3619943222159943226">"Ubuso behhashi"</string>
+    <string name="spoken_emoji_1F435" msgid="59199202683252958">"Ubuso bonogwaja"</string>
+    <string name="spoken_emoji_1F436" msgid="340544719369009828">"Ubuso benja"</string>
+    <string name="spoken_emoji_1F437" msgid="1219818379784982585">"Ubuso bengulube"</string>
+    <string name="spoken_emoji_1F438" msgid="9128124743321008210">"Ubuso bexoxo"</string>
+    <string name="spoken_emoji_1F439" msgid="1424161319554642266">"Ubuso be-hamster"</string>
+    <string name="spoken_emoji_1F43A" msgid="6727645488430385584">"Ubuso bempisi"</string>
+    <string name="spoken_emoji_1F43B" msgid="5397170068392865167">"Ubuso bebhele"</string>
+    <string name="spoken_emoji_1F43C" msgid="2715995734367032431">"Ubuso be-Panda"</string>
+    <string name="spoken_emoji_1F43D" msgid="6005480717951776597">"Ikhala lengulube"</string>
+    <string name="spoken_emoji_1F43E" msgid="8917626103219080547">"Imikhondo yesidladla"</string>
+    <string name="spoken_emoji_1F440" msgid="7144338258163384433">"Amehlo"</string>
+    <string name="spoken_emoji_1F442" msgid="1905515392292676124">"Indlebe"</string>
+    <string name="spoken_emoji_1F443" msgid="1491504447758933115">"Ikhala"</string>
+    <string name="spoken_emoji_1F444" msgid="3654613047946080332">"Umlomo"</string>
+    <string name="spoken_emoji_1F445" msgid="7024905244040509204">"Ulimi"</string>
+    <string name="spoken_emoji_1F446" msgid="2150365643636471745">"Okumhlophe okubheke inkomba yesandla sasemuva"</string>
+    <string name="spoken_emoji_1F447" msgid="8794022344940891388">"Okumhlophe okuphasni okubheke inkomba yesandla sasemuva"</string>
+    <string name="spoken_emoji_1F448" msgid="3261812959215550650">"Okumhlophe kwesokunxele okubheke inkomba yesandla sasemuva"</string>
+    <string name="spoken_emoji_1F449" msgid="4764447975177805991">"Okumhlophe kwesokudla okubheke inkomba yesandla sasemuva"</string>
+    <string name="spoken_emoji_1F44A" msgid="7197417095486424841">"Uphawu lwesandla esiyingqindi"</string>
+    <string name="spoken_emoji_1F44B" msgid="1975968945250833117">"Uphawu lwesandla esiphephezelayo"</string>
+    <string name="spoken_emoji_1F44C" msgid="3185919567897876562">"Uphawu lwesandla esibonisa ukuthi kulungile"</string>
+    <string name="spoken_emoji_1F44D" msgid="6182553970602667815">"Uphawu lokushaphu"</string>
+    <string name="spoken_emoji_1F44E" msgid="8030851867365111809">"Uphawu lokungekho shaphu"</string>
+    <string name="spoken_emoji_1F44F" msgid="5148753662268213389">"Uphawu lokushaya izandla"</string>
+    <string name="spoken_emoji_1F450" msgid="1012021072085157054">"Uphawu lwezandla ezivulekile"</string>
+    <string name="spoken_emoji_1F451" msgid="8257466714629051320">"Umqhele"</string>
+    <string name="spoken_emoji_1F452" msgid="4567394011149905466">"Isigqoko sowesifazane"</string>
+    <string name="spoken_emoji_1F453" msgid="5978410551173163010">"Izibuko zamehlo"</string>
+    <string name="spoken_emoji_1F454" msgid="348469036193323252">"Uthayi"</string>
+    <string name="spoken_emoji_1F455" msgid="5665118831861433578">"Isikibha"</string>
+    <string name="spoken_emoji_1F456" msgid="1890991330923356408">"Obhokhathi"</string>
+    <string name="spoken_emoji_1F457" msgid="3904310482655702620">"Ingubo"</string>
+    <string name="spoken_emoji_1F458" msgid="5704243858031107692">"I-Kimono"</string>
+    <string name="spoken_emoji_1F459" msgid="3553148747050035251">"Ibhikhini"</string>
+    <string name="spoken_emoji_1F45A" msgid="1389654639484716101">"Izingubo zabesifazane"</string>
+    <string name="spoken_emoji_1F45B" msgid="1113293170254222904">"Isikhwama semali"</string>
+    <string name="spoken_emoji_1F45C" msgid="3410257778598006936">"Isikhwama"</string>
+    <string name="spoken_emoji_1F45D" msgid="812176504300064819">"Isikhwama esincane"</string>
+    <string name="spoken_emoji_1F45E" msgid="2901741399934723562">"Izicathulo zabesilisa"</string>
+    <string name="spoken_emoji_1F45F" msgid="6828566359287798863">"Izicathulo zabadlali"</string>
+    <string name="spoken_emoji_1F460" msgid="305863879170420855">"Isicathulo sesithende esiphezulu"</string>
+    <string name="spoken_emoji_1F461" msgid="5160493217831417630">"Izicathulo ezivulekile zabesifazane"</string>
+    <string name="spoken_emoji_1F462" msgid="1722897795554863734">"Amabhuthi abesifazane"</string>
+    <string name="spoken_emoji_1F463" msgid="5850772903593010699">"Izinyathelo"</string>
+    <string name="spoken_emoji_1F464" msgid="1228335905487734913">"Isithombe esibonisa ikhanda namahlombe"</string>
+    <string name="spoken_emoji_1F465" msgid="4461307702499679879">"Isithombe esibonisa ikhanda namahlombe"</string>
+    <string name="spoken_emoji_1F466" msgid="1938873085514108889">"Umfana"</string>
+    <string name="spoken_emoji_1F467" msgid="8237080594860144998">"Intombazane"</string>
+    <string name="spoken_emoji_1F468" msgid="6081300722526675382">"Indoda"</string>
+    <string name="spoken_emoji_1F469" msgid="1090140923076108158">"Owesifazane"</string>
+    <string name="spoken_emoji_1F46A" msgid="5063570981942606595">"Umndeni"</string>
+    <string name="spoken_emoji_1F46B" msgid="6795882374287327952">"Indoda nowesifazane ababambene izandla"</string>
+    <string name="spoken_emoji_1F46C" msgid="6844464165783964495">"Amadoda amabili abambene izandla"</string>
+    <string name="spoken_emoji_1F46D" msgid="2316773068014053180">"Abesifazane ababili ababambene izandla"</string>
+    <string name="spoken_emoji_1F46E" msgid="5897625605860822401">"Ihhovisi"</string>
+    <string name="spoken_emoji_1F46F" msgid="7716871657717641490">"Owesifazane onezindlebe ezindizayo"</string>
+    <string name="spoken_emoji_1F470" msgid="6409995400510338892">"Umakoti ofake umgubuzelo"</string>
+    <string name="spoken_emoji_1F471" msgid="3058247860441670806">"Umuntu onezinwele ezimhloshana"</string>
+    <string name="spoken_emoji_1F472" msgid="3928854667819339142">"Indoda ene-gua pi mao"</string>
+    <string name="spoken_emoji_1F473" msgid="5921952095808988381">"Indoda enomshuqulo"</string>
+    <string name="spoken_emoji_1F474" msgid="1082237499496725183">"Indoda esekhulile"</string>
+    <string name="spoken_emoji_1F475" msgid="7280323988642212761">"Owesifazane osekhulile"</string>
+    <string name="spoken_emoji_1F476" msgid="4713322657821088296">"Umntwana"</string>
+    <string name="spoken_emoji_1F477" msgid="2197036131029221370">"Isisebenzi sezokwakha"</string>
+    <string name="spoken_emoji_1F478" msgid="7245521193493488875">"Inkosazana"</string>
+    <string name="spoken_emoji_1F479" msgid="6876475321015553972">"Isilwane esisabekayo sesi-Japanese"</string>
+    <string name="spoken_emoji_1F47A" msgid="3900813633102703571">"Isichwe sesi-Japanese"</string>
+    <string name="spoken_emoji_1F47B" msgid="2608250873194079390">"Isipoki"</string>
+    <string name="spoken_emoji_1F47C" msgid="3838699131276537421">"Ingelosi yomntwana"</string>
+    <string name="spoken_emoji_1F47D" msgid="2874077455888369538">"I-Alien esemkhathini"</string>
+    <string name="spoken_emoji_1F47E" msgid="3642607168625579507">"I-Alien esabekayo"</string>
+    <string name="spoken_emoji_1F47F" msgid="441605977269926252">"Idemoni"</string>
+    <string name="spoken_emoji_1F480" msgid="3696253485164878739">"Ukhakhayi"</string>
+    <string name="spoken_emoji_1F481" msgid="320408708521966893">"Umuntu wendawo yosizo"</string>
+    <string name="spoken_emoji_1F482" msgid="3424354860245608949">"Ibutho"</string>
+    <string name="spoken_emoji_1F483" msgid="3221113594843849083">"Umdansi"</string>
+    <string name="spoken_emoji_1F484" msgid="7348014979080444885">"Iluji"</string>
+    <string name="spoken_emoji_1F485" msgid="6133507975565116339">"Ipholishi yenzipho"</string>
+    <string name="spoken_emoji_1F486" msgid="9085459968247394155">"Ukubhucunga ubuso"</string>
+    <string name="spoken_emoji_1F487" msgid="1479113637259592150">"Ukugunda izinwele"</string>
+    <string name="spoken_emoji_1F488" msgid="6922559285234100252">"Uphawu lasendaweni yokugunda"</string>
+    <string name="spoken_emoji_1F489" msgid="8114863680950147305">"Isichatha"</string>
+    <string name="spoken_emoji_1F48A" msgid="8526843630145963032">"Iphilisi"</string>
+    <string name="spoken_emoji_1F48B" msgid="2538528967897640292">"Uphawu lokuqabula"</string>
+    <string name="spoken_emoji_1F48C" msgid="1681173271652890232">"Incwadi yothando"</string>
+    <string name="spoken_emoji_1F48D" msgid="8259886164999042373">"Khalisa"</string>
+    <string name="spoken_emoji_1F48E" msgid="8777981696011111101">"Itshe eliyigugu"</string>
+    <string name="spoken_emoji_1F48F" msgid="741593675183677907">"Qabula"</string>
+    <string name="spoken_emoji_1F490" msgid="4482549128959806736">"Umqulu wezimbali"</string>
+    <string name="spoken_emoji_1F491" msgid="2305245307882441500">"Izithandani ezinenhliziyo"</string>
+    <string name="spoken_emoji_1F492" msgid="3884119934804475732">"Umshado"</string>
+    <string name="spoken_emoji_1F493" msgid="1208828371565525121">"Inhliziyo eshayayo"</string>
+    <string name="spoken_emoji_1F494" msgid="6198876398509338718">"Inhliziyo ephukile"</string>
+    <string name="spoken_emoji_1F495" msgid="9206202744967130919">"Izinhliziyo ezimbili"</string>
+    <string name="spoken_emoji_1F496" msgid="5436953041732207775">"Inhliziyo ekhazimulayo"</string>
+    <string name="spoken_emoji_1F497" msgid="7285142863951448473">"Inhliziyo ekhulayo"</string>
+    <string name="spoken_emoji_1F498" msgid="7940131245037575715">"Inhliziyo enomcibisholo"</string>
+    <string name="spoken_emoji_1F499" msgid="4453235040265550009">"Inhliziyo eluhlaza okwesibhakabha"</string>
+    <string name="spoken_emoji_1F49A" msgid="6262178648366971405">"Inhliziyo eluhlaza okotshani"</string>
+    <string name="spoken_emoji_1F49B" msgid="8085384999750714368">"Inhliziyo eliphuzi"</string>
+    <string name="spoken_emoji_1F49C" msgid="453829540120898698">"Inhliziyo ebumsomi"</string>
+    <string name="spoken_emoji_1F49D" msgid="3460534750224161888">"Inhliziyo eneribhoni"</string>
+    <string name="spoken_emoji_1F49E" msgid="4490636226072523867">"Izinhliziyo ezijikelezayo"</string>
+    <string name="spoken_emoji_1F49F" msgid="2059319756421226336">"Umhlobiso wenhliziyo"</string>
+    <string name="spoken_emoji_1F4A0" msgid="1954850380550212038">"Umumo wedayimane onechashazi ngaphakathi"</string>
+    <string name="spoken_emoji_1F4A1" msgid="403137413540909021">"Igilobhu yogesi yokukhanyisa"</string>
+    <string name="spoken_emoji_1F4A2" msgid="2604192053295622063">"Uphawu lentukuthelo"</string>
+    <string name="spoken_emoji_1F4A3" msgid="6378351742957821735">"Ibhomu"</string>
+    <string name="spoken_emoji_1F4A4" msgid="7217736258870346625">"Uphawu lokulala"</string>
+    <string name="spoken_emoji_1F4A5" msgid="5401995723541239858">"Uphawu lokushayisana"</string>
+    <string name="spoken_emoji_1F4A6" msgid="3837802182716483848">"Uphawu lokukhipha umjuluko"</string>
+    <string name="spoken_emoji_1F4A7" msgid="5718438987757885141">"Iconsi"</string>
+    <string name="spoken_emoji_1F4A8" msgid="4472108229720006377">"Uphawu lodwi"</string>
+    <string name="spoken_emoji_1F4A9" msgid="1240958472788430032">"Inqwaba yendle"</string>
+    <string name="spoken_emoji_1F4AA" msgid="8427525538635146416">"Izinkonyane ezigobile"</string>
+    <string name="spoken_emoji_1F4AB" msgid="5484114759939427459">"Uphawu lwesiyezi"</string>
+    <string name="spoken_emoji_1F4AC" msgid="5571196638219612682">"Ibhamuza lenkulumo"</string>
+    <string name="spoken_emoji_1F4AD" msgid="353174619257798652">"Ibhamuza lomncabango"</string>
+    <string name="spoken_emoji_1F4AE" msgid="1223142786927162641">"Imbali emhlophe"</string>
+    <string name="spoken_emoji_1F4AF" msgid="3526278354452138397">"Uphawu lamaphoyinti ayikhulu"</string>
+    <string name="spoken_emoji_1F4B0" msgid="4124102195175124156">"Isikhwama semali"</string>
+    <string name="spoken_emoji_1F4B1" msgid="8339494003418572905">"Ukushintshwa kohlobo lemali"</string>
+    <string name="spoken_emoji_1F4B2" msgid="3179159430187243132">"Uphawu lwedola esindayo"</string>
+    <string name="spoken_emoji_1F4B3" msgid="5375412518221759596">"Ikhadi lesikweletu"</string>
+    <string name="spoken_emoji_1F4B4" msgid="1068592463669453204">"Uphawu lemali ye-yen"</string>
+    <string name="spoken_emoji_1F4B5" msgid="1426708699891832564">"Imali enophawu ledola"</string>
+    <string name="spoken_emoji_1F4B6" msgid="8289249930736444837">"Uphawu lemali ye-euro"</string>
+    <string name="spoken_emoji_1F4B7" msgid="5245100496860739429">"Uphawu lemali yephawundi"</string>
+    <string name="spoken_emoji_1F4B8" msgid="4401099580477164440">"Imali enamaphiko"</string>
+    <string name="spoken_emoji_1F4B9" msgid="647509393536679903">"Ishadi elinomkhuba obheke phezulu nophawu le-yen"</string>
+    <string name="spoken_emoji_1F4BA" msgid="1269737854891046321">"Isihlalo"</string>
+    <string name="spoken_emoji_1F4BB" msgid="6252883563347816451">"Ikhompyutha yokomuntu siqu"</string>
+    <string name="spoken_emoji_1F4BC" msgid="6182597732218446206">"Isikhwama"</string>
+    <string name="spoken_emoji_1F4BD" msgid="5820961044768829176">"Idiski encane"</string>
+    <string name="spoken_emoji_1F4BE" msgid="4754542485835379808">"Iflophidiski"</string>
+    <string name="spoken_emoji_1F4BF" msgid="2237481756984721795">"Idiski ebonakalayo"</string>
+    <string name="spoken_emoji_1F4C0" msgid="491582501089694461">"I-DVD"</string>
+    <string name="spoken_emoji_1F4C1" msgid="6645461382494158111">"Ifolda yefayela"</string>
+    <string name="spoken_emoji_1F4C2" msgid="8095638715523765338">"Vula ifolda yefayela"</string>
+    <string name="spoken_emoji_1F4C3" msgid="3727274466173970142">"Ikhasi eligoqekile"</string>
+    <string name="spoken_emoji_1F4C4" msgid="4382570710795501612">"Ikhasi elibheke phezulu"</string>
+    <string name="spoken_emoji_1F4C5" msgid="8693944622627762487">"Ikhalenda"</string>
+    <string name="spoken_emoji_1F4C6" msgid="8469908708708424640">"Ikhalenda yokukhipha"</string>
+    <string name="spoken_emoji_1F4C7" msgid="2665313547987324495">"Inkomba yekhadi"</string>
+    <string name="spoken_emoji_1F4C8" msgid="8007686702282833600">"Ishadi enomkhuba obheke phezulu"</string>
+    <string name="spoken_emoji_1F4C9" msgid="2271951411192893684">"Ishadi elinomkhuba obheke phasni"</string>
+    <string name="spoken_emoji_1F4CA" msgid="3525692829622381444">"Ishadi lebha"</string>
+    <string name="spoken_emoji_1F4CB" msgid="977639227554095521">"Ibhodi lokumanathisela"</string>
+    <string name="spoken_emoji_1F4CC" msgid="156107396088741574">"Iphini"</string>
+    <string name="spoken_emoji_1F4CD" msgid="4266572175361190231">"Iphini eyindilinga"</string>
+    <string name="spoken_emoji_1F4CE" msgid="6294288509864968290">"Okokubamba iphepha"</string>
+    <string name="spoken_emoji_1F4CF" msgid="149679400831136810">"Umbusi oqondile"</string>
+    <string name="spoken_emoji_1F4D0" msgid="8130339336619202915">"Umbusi ongunxantathu"</string>
+    <string name="spoken_emoji_1F4D1" msgid="5852176364856284968">"Amathebhu ebhukhimakhi"</string>
+    <string name="spoken_emoji_1F4D2" msgid="2276810154105920052">"Ileja"</string>
+    <string name="spoken_emoji_1F4D3" msgid="5873386492793610808">"Inothibhuku"</string>
+    <string name="spoken_emoji_1F4D4" msgid="4754469936418776360">"Inothibhuku enekhava ehlotshisiwe"</string>
+    <string name="spoken_emoji_1F4D5" msgid="4642713351802778905">"Ibhuku elivaliwe"</string>
+    <string name="spoken_emoji_1F4D6" msgid="6987347918381807186">"Vula ibhuku"</string>
+    <string name="spoken_emoji_1F4D7" msgid="7813394163241379223">"Ibhuku eliluhlaza okotshani"</string>
+    <string name="spoken_emoji_1F4D8" msgid="7189799718984979521">"Ibhuku eliluhlaza okwesibhakabhaka"</string>
+    <string name="spoken_emoji_1F4D9" msgid="3874664073186440225">"Ibhuku elisawonlintshi"</string>
+    <string name="spoken_emoji_1F4DA" msgid="872212072924287762">"Amabhuku"</string>
+    <string name="spoken_emoji_1F4DB" msgid="2015183603583392969">"Ibheji legama"</string>
+    <string name="spoken_emoji_1F4DC" msgid="5075845110932456783">"Phenya"</string>
+    <string name="spoken_emoji_1F4DD" msgid="2494006707147586786">"Imemo"</string>
+    <string name="spoken_emoji_1F4DE" msgid="7883008605002117671">"Isamukeli socingo"</string>
+    <string name="spoken_emoji_1F4DF" msgid="3538610110623780465">"Ipheyi"</string>
+    <string name="spoken_emoji_1F4E0" msgid="2960778342609543077">"Umshini wefeksi"</string>
+    <string name="spoken_emoji_1F4E1" msgid="6269733703719242108">"I-Antenna yesethalaythi"</string>
+    <string name="spoken_emoji_1F4E2" msgid="1987535386302883116">"Isandisizwi sekheli elisesidlangalaleni"</string>
+    <string name="spoken_emoji_1F4E3" msgid="5588916572878599224">"I-Megaphone yenjabulo"</string>
+    <string name="spoken_emoji_1F4E4" msgid="2063561529097749707">"Itreyi lokuphumayo"</string>
+    <string name="spoken_emoji_1F4E5" msgid="3232462702926143576">"Itreyi lebhokisi lokungenayo"</string>
+    <string name="spoken_emoji_1F4E6" msgid="3399454337197561635">"Iphakeji"</string>
+    <string name="spoken_emoji_1F4E7" msgid="5557136988503873238">"Uphawu lwe-imeyili"</string>
+    <string name="spoken_emoji_1F4E8" msgid="30698793974124123">"Imvilophi yokungenayo"</string>
+    <string name="spoken_emoji_1F4E9" msgid="5947550337678643166">"Imvilophi engenhla enomcibisholo obheke phansi"</string>
+    <string name="spoken_emoji_1F4EA" msgid="772614045207213751">"Ibhokisi lemeyili elivaliwe elinefulegi eyehlisiwe"</string>
+    <string name="spoken_emoji_1F4EB" msgid="6491414165464146137">"Ibhokisi lemeyili elivaliwe elinefulegi ekhushuliwe"</string>
+    <string name="spoken_emoji_1F4EC" msgid="7369517138779988438">"Vula ibhokisi lemeyili elinefulegi ekhushuliwe"</string>
+    <string name="spoken_emoji_1F4ED" msgid="5657520436285454241">"Vula ibhokisi lemeyili elinefulegi eyehlisiwe"</string>
+    <string name="spoken_emoji_1F4EE" msgid="8464138906243608614">"Isigxobo seposi"</string>
+    <string name="spoken_emoji_1F4EF" msgid="8801427577198798226">"Uphondo lweposi"</string>
+    <string name="spoken_emoji_1F4F0" msgid="6330208624731662525">"Iphephandaba"</string>
+    <string name="spoken_emoji_1F4F1" msgid="3966503935581675695">"Iselula"</string>
+    <string name="spoken_emoji_1F4F2" msgid="1057540341746100087">"Iselula yomcibisholo wokwesokudla ngakwesokunxele"</string>
+    <string name="spoken_emoji_1F4F3" msgid="5003984447315754658">"Imodi yokudlidliza"</string>
+    <string name="spoken_emoji_1F4F4" msgid="5549847566968306253">"Iselula icishiwe"</string>
+    <string name="spoken_emoji_1F4F5" msgid="3660199448671699238">"Awekho amaselula"</string>
+    <string name="spoken_emoji_1F4F6" msgid="2676974903233268860">"I-Antenna enamabha"</string>
+    <string name="spoken_emoji_1F4F7" msgid="2643891943105989039">"Ikhamela"</string>
+    <string name="spoken_emoji_1F4F9" msgid="4475626303058218048">"Ikhamela yevidiyo"</string>
+    <string name="spoken_emoji_1F4FA" msgid="1079796186652960775">"Umabonakude"</string>
+    <string name="spoken_emoji_1F4FB" msgid="3848729587403760645">"Irediyo"</string>
+    <string name="spoken_emoji_1F4FC" msgid="8370432508874310054">"Ikhasethi yevidiyo"</string>
+    <string name="spoken_emoji_1F500" msgid="2389947994502144547">"Imicibisholo ejikiswe ngakwesokudla"</string>
+    <string name="spoken_emoji_1F501" msgid="2132188352433347009">"Imicibisholo yendilinga evulwe ngakwesokudla nangakwesokunxele"</string>
+    <string name="spoken_emoji_1F502" msgid="2361976580513178391">"Imicibisholo yendilinga evulwe ngakwesokudla nangakwesokunxele enombondela eyodwa ezungezile"</string>
+    <string name="spoken_emoji_1F503" msgid="8936283551917858793">"Imicibisholo yendilinga evulwe ngezansi nangaphezulu ehamba njengewashi"</string>
+    <string name="spoken_emoji_1F504" msgid="708290317843535943">"Imicibisholo yendilinga evulwe ngezansi nangaphezulu ehamba ngokuphambene newashi"</string>
+    <string name="spoken_emoji_1F505" msgid="6348909939004951860">"Uphawu lokukhanya okuphansi"</string>
+    <string name="spoken_emoji_1F506" msgid="4449609297521280173">"Uphawu lokukhanya okuphezulu"</string>
+    <string name="spoken_emoji_1F507" msgid="7136386694923708448">"Isipikha esinomudwa wokukhansela"</string>
+    <string name="spoken_emoji_1F508" msgid="5063567689831527865">"Isipikha"</string>
+    <string name="spoken_emoji_1F509" msgid="3948050077992370791">"Isipikha esinegagasi lomsindo elilodwa"</string>
+    <string name="spoken_emoji_1F50A" msgid="5818194948677277197">"Isipikha esinamagagasi omsindo amathathu"</string>
+    <string name="spoken_emoji_1F50B" msgid="8083470451266295876">"Ibhethri"</string>
+    <string name="spoken_emoji_1F50C" msgid="7793219132036431680">"Ipulagi kagesi"</string>
+    <string name="spoken_emoji_1F50D" msgid="8140244710637926780">"Isibonisakhulu esikhombe ngakwesokunxele"</string>
+    <string name="spoken_emoji_1F50E" msgid="4751821352839693365">"Isibonisakhulu esikhombe ngakwesokudla"</string>
+    <string name="spoken_emoji_1F50F" msgid="915079280472199605">"Khiya ngepeni loyinki"</string>
+    <string name="spoken_emoji_1F510" msgid="7658381761691758318">"Ilokhi evalwe ngokhiye"</string>
+    <string name="spoken_emoji_1F511" msgid="262319867774655688">"Ukhiye"</string>
+    <string name="spoken_emoji_1F512" msgid="5628688337255115175">"Khiya"</string>
+    <string name="spoken_emoji_1F513" msgid="8579201846619420981">"Vula ilokhi"</string>
+    <string name="spoken_emoji_1F514" msgid="7027268683047322521">"Isikhalisi"</string>
+    <string name="spoken_emoji_1F515" msgid="8903179856036069242">"Isikhalisi esinomudwa wokukhansela"</string>
+    <string name="spoken_emoji_1F516" msgid="108097933937925381">"Ibhukhimakhi"</string>
+    <string name="spoken_emoji_1F517" msgid="2450846665734313397">"Isixhumanisi sophawu"</string>
+    <string name="spoken_emoji_1F518" msgid="7028220286841437832">"Inkinobho yerediyo"</string>
+    <string name="spoken_emoji_1F519" msgid="8211189165075445687">"Ngemuva ngomcibisholo ongakwesokunxele ngenhla"</string>
+    <string name="spoken_emoji_1F51A" msgid="823966751787338892">"Phetha ngomcibisholo ongakwesokunxele ngenhla"</string>
+    <string name="spoken_emoji_1F51B" msgid="5920570742107943382">"Kuvulwe ngesibabazo esinomcibisholo ongakwesokunxele nesokudla ngenhla"</string>
+    <string name="spoken_emoji_1F51C" msgid="110609810659826676">"Maduze ngomcibisholo ongakwesokudla ngenhla"</string>
+    <string name="spoken_emoji_1F51D" msgid="4087697222026095447">"Ngaphezulu ngomcibisholo opheke phezulu ngenhla"</string>
+    <string name="spoken_emoji_1F51E" msgid="8512873526157201775">"Akekho ongaphansi kophawu leshumi nesishiyagalombili"</string>
+    <string name="spoken_emoji_1F51F" msgid="8673370823728653973">"I-Keycap yeshumi"</string>
+    <string name="spoken_emoji_1F520" msgid="7335109890337048900">"Uphawu lokokufaka lamagama ofeleba be-latin"</string>
+    <string name="spoken_emoji_1F521" msgid="2693185864450925778">"Uphawu lokokufaka lamagama amancane e-latin"</string>
+    <string name="spoken_emoji_1F522" msgid="8419130286280673347">"Uphawu lokokufaka lezinombolo"</string>
+    <string name="spoken_emoji_1F523" msgid="3318053476401719421">"Uphawu lokokufaka lezimpawu"</string>
+    <string name="spoken_emoji_1F524" msgid="1625073997522316331">"Uphawu lokokufaka lamagama e-latin"</string>
+    <string name="spoken_emoji_1F525" msgid="4083884189172963790">"Umlilo"</string>
+    <string name="spoken_emoji_1F526" msgid="2035494936742643580">"Ithoshi logesi"</string>
+    <string name="spoken_emoji_1F527" msgid="134257142354034271">"Ukudonsa"</string>
+    <string name="spoken_emoji_1F528" msgid="700627429570609375">"Isando"</string>
+    <string name="spoken_emoji_1F529" msgid="7480548235904988573">"Insinjana nomshudo"</string>
+    <string name="spoken_emoji_1F52A" msgid="7613580031502317893">"I-Hocho"</string>
+    <string name="spoken_emoji_1F52B" msgid="4554906608328118613">"Iphistoli"</string>
+    <string name="spoken_emoji_1F52C" msgid="1330294501371770790">"Isibonakhulu"</string>
+    <string name="spoken_emoji_1F52D" msgid="7549551775445177140">"Isibonakude"</string>
+    <string name="spoken_emoji_1F52E" msgid="4457099417872625141">"Ibhola le-Crystal"</string>
+    <string name="spoken_emoji_1F52F" msgid="8899031001317442792">"Inkanyezi enamaphoyinti ayisithupha nechashazi eliphakathi nendawo"</string>
+    <string name="spoken_emoji_1F530" msgid="3572898444281774023">"Uphawu lesi-Japanese lomqali"</string>
+    <string name="spoken_emoji_1F531" msgid="5225633376450025396">"Isibonakaliso se-Trident"</string>
+    <string name="spoken_emoji_1F532" msgid="9169568490485180779">"Inkinobho emnyama eyisikwele"</string>
+    <string name="spoken_emoji_1F533" msgid="6554193837201918598">"Inkinobho emhlophe eyisikwele"</string>
+    <string name="spoken_emoji_1F534" msgid="8339298801331865340">"Isiyingi esikhulu esibomvu"</string>
+    <string name="spoken_emoji_1F535" msgid="1227403104835533512">"Isiyingi esikhulu esiluhlaza okwesibhakabhaka"</string>
+    <string name="spoken_emoji_1F536" msgid="5477372445510469331">"Idayimane enkulu esawolintshi"</string>
+    <string name="spoken_emoji_1F537" msgid="3158915214347274626">"Idayimane elikhulu eliluhlaza okwesibhakabhaka"</string>
+    <string name="spoken_emoji_1F538" msgid="4300084249474451991">"Idayimane elincane elisawolintshi"</string>
+    <string name="spoken_emoji_1F539" msgid="6535159756325742275">"Idayimane elincane eliluhlaza okwesibhakabhaka"</string>
+    <string name="spoken_emoji_1F53A" msgid="3728196273988781389">"Unxande obomvu obheke phezulu"</string>
+    <string name="spoken_emoji_1F53B" msgid="7182097039614128707">"Unxande obomvu obheke phansi"</string>
+    <string name="spoken_emoji_1F53C" msgid="4077022046319615029">"Unxande omncane obomvu obheke phezulu"</string>
+    <string name="spoken_emoji_1F53D" msgid="3939112784894620713">"Unxande omncane obomvu obheke phansi"</string>
+    <string name="spoken_emoji_1F550" msgid="7761392621689986218">"Ubuso bewashi lehora lokuqala ezimpondweni"</string>
+    <string name="spoken_emoji_1F551" msgid="2699448504113431716">"Ubuso bewashi lehora lesibili ezimpondweni"</string>
+    <string name="spoken_emoji_1F552" msgid="5872107867411853750">"Ubuso bewashi lehora lesithathu ezimpondweni"</string>
+    <string name="spoken_emoji_1F553" msgid="8490966286158640743">"Ubuso bewashi lehora lesine ezimpondweni"</string>
+    <string name="spoken_emoji_1F554" msgid="7662585417832909280">"Ubuso bewashi lehora lesithathu ezimpondweni"</string>
+    <string name="spoken_emoji_1F555" msgid="5564698204520412009">"Ubuso bewashi lehora lesithupha ezimpondweni"</string>
+    <string name="spoken_emoji_1F556" msgid="7325712194836512205">"Ubuso bewashi lehora lesikhombisa ezimpondweni"</string>
+    <string name="spoken_emoji_1F557" msgid="4398343183682848693">"Ubuso bewashi lehora lesishiyagalombili ezimpondweni"</string>
+    <string name="spoken_emoji_1F558" msgid="3110507820404018172">"Ubuso bewashi lehora lesishiyagalolunye ezimpondweni"</string>
+    <string name="spoken_emoji_1F559" msgid="2972160366448337839">"Ubuso bewashi lehora leshumi ezimpondweni"</string>
+    <string name="spoken_emoji_1F55A" msgid="5568112876681714834">"Ubuso bewashi lehora leshumi nanye ezimpondweni"</string>
+    <string name="spoken_emoji_1F55B" msgid="6731739890330659276">"Ubuso bewashi lehora leshumi nambili ezimpondweni"</string>
+    <string name="spoken_emoji_1F55C" msgid="7838853679879115890">"Ubuso bewashi bamashumi amathathu nanye"</string>
+    <string name="spoken_emoji_1F55D" msgid="3518832144255922544">"Ubuso bewashi bamashumi amathathu nambili"</string>
+    <string name="spoken_emoji_1F55E" msgid="3092760695634993002">"Ubuso bewashi bamashumi amathathu nantathu"</string>
+    <string name="spoken_emoji_1F55F" msgid="2326720311892906763">"Ubuso bewashi bamashumi amathathu nane"</string>
+    <string name="spoken_emoji_1F560" msgid="5771339179963924448">"Ubuso bewashi bamashumi amathathu nanhlanu"</string>
+    <string name="spoken_emoji_1F561" msgid="3139944777062475382">"Ubuso bewashi bamashumi amathathu nesithupha"</string>
+    <string name="spoken_emoji_1F562" msgid="8273944611162457084">"Ubuso bewashi bamashumi amathathu nesikhombisa"</string>
+    <string name="spoken_emoji_1F563" msgid="8643976903718136299">"Ubuso bewashi bamashumi amathathu nesishiyagalombili"</string>
+    <string name="spoken_emoji_1F564" msgid="3511070239796141638">"Ubuso bewashi bamashumi amathathu nesishiyagalolunye"</string>
+    <string name="spoken_emoji_1F565" msgid="4567451985272963088">"Ubuso bewashi bamashumi amathathu neshumi"</string>
+    <string name="spoken_emoji_1F566" msgid="2790552288169929810">"Ubuso bewashi bamashumi amathathu neshumi nanye"</string>
+    <string name="spoken_emoji_1F567" msgid="9026037362100689337">"Ubuso bewashi bamashumi amathathu neshumi nambili"</string>
+    <string name="spoken_emoji_1F5FB" msgid="9037503671676124015">"I-Mount fuji"</string>
+    <string name="spoken_emoji_1F5FC" msgid="1409415995817242150">"Inqaba yase-Tokyo"</string>
+    <string name="spoken_emoji_1F5FD" msgid="2562726956654429582">"Isithombe senkululeko"</string>
+    <string name="spoken_emoji_1F5FE" msgid="1184469756905210580">"I-Silhouette yase-japan"</string>
+    <string name="spoken_emoji_1F5FF" msgid="6003594799354942297">"I-Moyai"</string>
+    <string name="spoken_emoji_1F600" msgid="7601109464776835283">"Ubuso obuhlinile"</string>
+    <string name="spoken_emoji_1F601" msgid="746026523967444503">"Ubuso obuhlinile namehlo amomothekayo"</string>
+    <string name="spoken_emoji_1F602" msgid="8354558091785198246">"Ubuso obunezinyembezi zenjabulo"</string>
+    <string name="spoken_emoji_1F603" msgid="3861022912544159823">"Ubuso obumomothekayo nomlomo ovuliwe"</string>
+    <string name="spoken_emoji_1F604" msgid="5119021072966343531">"Ubuso obumomothekayo nomlomo ovuliwe namehlo amomothekyo"</string>
+    <string name="spoken_emoji_1F605" msgid="6140813923973561735">"Ubuso obumomothekayo nomlomo ovulekile nomjuluko obandayo"</string>
+    <string name="spoken_emoji_1F606" msgid="3549936813966832799">"Ubuso obumomothekayo nomlomo ovulekile namehlo avalwe kakhulu"</string>
+    <string name="spoken_emoji_1F607" msgid="2826424078212384817">"Umlomo obumomothekayo obingelelayo"</string>
+    <string name="spoken_emoji_1F608" msgid="7343559595089811640">"Ubuso obumomothekayo obunezimpondo"</string>
+    <string name="spoken_emoji_1F609" msgid="5481030187207504405">"Ubuso obucimezayo"</string>
+    <string name="spoken_emoji_1F60A" msgid="5023337769148679767">"Ubuso obumomothekayo namehlo amomothekayo"</string>
+    <string name="spoken_emoji_1F60B" msgid="3005248217216195694">"Ubuso obujabulela ukudla okumnandi"</string>
+    <string name="spoken_emoji_1F60C" msgid="349384012958268496">"Ubuso obukhululekile"</string>
+    <string name="spoken_emoji_1F60D" msgid="7921853137164938391">"Ubuso obumomothekayo namehla amise okwenhliziyo"</string>
+    <string name="spoken_emoji_1F60E" msgid="441718886380605643">"Ubuso obumomothekayo nezibuko zelanga"</string>
+    <string name="spoken_emoji_1F60F" msgid="2674453144890180538">"Ubuso obusinekayo"</string>
+    <string name="spoken_emoji_1F610" msgid="3225675825334102369">"Ubuso obungathathi hlangothi"</string>
+    <string name="spoken_emoji_1F611" msgid="7199179827619679668">"Ubuso obungabonisi mizwa"</string>
+    <string name="spoken_emoji_1F612" msgid="985081329745137998">"Ubuso obungajabulile"</string>
+    <string name="spoken_emoji_1F613" msgid="5548607684830303562">"Ubuso obunomjuluko obondayo"</string>
+    <string name="spoken_emoji_1F614" msgid="3196305665259916390">"Ubuso obujulayo"</string>
+    <string name="spoken_emoji_1F615" msgid="3051674239303969101">"Ubuso obudidekile"</string>
+    <string name="spoken_emoji_1F616" msgid="8124887056243813089">"Ubuso bokugcizelela"</string>
+    <string name="spoken_emoji_1F617" msgid="7052733625511122870">"Ubuso bokuqabula"</string>
+    <string name="spoken_emoji_1F618" msgid="408207170572303753">"Ubuso obufutha ukuqabula"</string>
+    <string name="spoken_emoji_1F619" msgid="8645430335143153645">"Ubuso obuqabulayo namehlo amomothekayo"</string>
+    <string name="spoken_emoji_1F61A" msgid="2882157190974340247">"Ubuso obuqabulayo namehlo avaliwe"</string>
+    <string name="spoken_emoji_1F61B" msgid="3765927202787211499">"Ubuso bolimi obukhishwe ngaphandle"</string>
+    <string name="spoken_emoji_1F61C" msgid="198943912107589389">"Ubuso bolimi olukhishwe ngaphandle nehlo elicwayizayo"</string>
+    <string name="spoken_emoji_1F61D" msgid="7643546385877816182">"Ubuso nolimi olukhishwe ngaphandle namehlo avalwe kakhulu"</string>
+    <string name="spoken_emoji_1F61E" msgid="1528732952202098364">"Ubuso obudumele"</string>
+    <string name="spoken_emoji_1F61F" msgid="1853664164636082404">"Ubuso obukhathazekile"</string>
+    <string name="spoken_emoji_1F620" msgid="6051942001307375830">"Ubuso obucasukile"</string>
+    <string name="spoken_emoji_1F621" msgid="2114711878097257704">"Ubuso bomlomo ophukuliwe"</string>
+    <string name="spoken_emoji_1F622" msgid="29291014645931822">"Ubuso obukhalayo"</string>
+    <string name="spoken_emoji_1F623" msgid="7803959833595184773">"Ubuso obubekezelayo"</string>
+    <string name="spoken_emoji_1F624" msgid="8637637647725752799">"Ubuso bokunqoba"</string>
+    <string name="spoken_emoji_1F625" msgid="6153625183493635030">"Ubuso obuphoxekile kodwa obukhululekile"</string>
+    <string name="spoken_emoji_1F626" msgid="6179485689935562950">"Ubuso obuhlinayo nomlomo ovuliwe"</string>
+    <string name="spoken_emoji_1F627" msgid="8566204052903012809">"Ubuso obukhathazekile"</string>
+    <string name="spoken_emoji_1F628" msgid="8875777401624904224">"Ubuso obethukile"</string>
+    <string name="spoken_emoji_1F629" msgid="1411538490319190118">"Ubuso obukhathele"</string>
+    <string name="spoken_emoji_1F62A" msgid="4726686726690289969">"Ubuso obuzelayo"</string>
+    <string name="spoken_emoji_1F62B" msgid="3221980473921623613">"Ubuso obukhathele"</string>
+    <string name="spoken_emoji_1F62C" msgid="4616356691941225182">"Ubuso obuhlinayo"</string>
+    <string name="spoken_emoji_1F62D" msgid="4283677508698812232">"Ubuso obukhalela phezulu"</string>
+    <string name="spoken_emoji_1F62E" msgid="726083405284353894">"Ubuso bomlomo ovulekile"</string>
+    <string name="spoken_emoji_1F62F" msgid="7746620088234710962">"Ubuso obugcwele usizi"</string>
+    <string name="spoken_emoji_1F630" msgid="3298804852155581163">"Ubuso bomlomo ovulekile nomjuluko obandayo"</string>
+    <string name="spoken_emoji_1F631" msgid="1603391150954646779">"Ubuso obumemezayo ngenxa yokwesaba"</string>
+    <string name="spoken_emoji_1F632" msgid="4846193232203976013">"Ubuso obumangele"</string>
+    <string name="spoken_emoji_1F633" msgid="4023593836629700443">"Ubuso obucobekile"</string>
+    <string name="spoken_emoji_1F634" msgid="3155265083246248129">"Ubuso obulele"</string>
+    <string name="spoken_emoji_1F635" msgid="4616691133452764482">"Ubuso obunesiyezi"</string>
+    <string name="spoken_emoji_1F636" msgid="947000211822375683">"Ubuso obungenawo umlomo"</string>
+    <string name="spoken_emoji_1F637" msgid="1269551267347165774">"Ubuso obunesembozo sezempilo"</string>
+    <string name="spoken_emoji_1F638" msgid="3410766467496872301">"Ubuso bekati elihlinile namehlo amomothekayo"</string>
+    <string name="spoken_emoji_1F639" msgid="1833417519781022031">"Ubuso bekati nezinyembezi zenjabulo"</string>
+    <string name="spoken_emoji_1F63A" msgid="8566294484007152613">"Ubuso bekati nomlomo ovulekile"</string>
+    <string name="spoken_emoji_1F63B" msgid="74417995938927571">"Ubuso bekati obumomothekayo namehlo amise okwenhliziyo"</string>
+    <string name="spoken_emoji_1F63C" msgid="6472812005729468870">"Ubuso bekati nokumomotheka obubhuqayo"</string>
+    <string name="spoken_emoji_1F63D" msgid="1638398369553349509">"Ubuso bekati bokuqabula namehlo avaliwe"</string>
+    <string name="spoken_emoji_1F63E" msgid="6788969063020278986">"Ubuso bekati bokuphukula"</string>
+    <string name="spoken_emoji_1F63F" msgid="1207234562459550185">"Ubuso bekati obukhalayo"</string>
+    <string name="spoken_emoji_1F640" msgid="6023054549904329638">"Ubuso bekati obukhathele"</string>
+    <string name="spoken_emoji_1F645" msgid="5202090629227587076">"Ubuso obungenaso isenzo esihle"</string>
+    <string name="spoken_emoji_1F646" msgid="6734425134415138134">"Ubuso besenzo esilungile"</string>
+    <string name="spoken_emoji_1F647" msgid="1090285518444205483">"Umuntu ogobe ngokujulile"</string>
+    <string name="spoken_emoji_1F648" msgid="8978535230610522356">"Ukungaboni unogwaja omubi"</string>
+    <string name="spoken_emoji_1F649" msgid="8486145279809495102">"Ukungezwa unogwaja omubi"</string>
+    <string name="spoken_emoji_1F64A" msgid="1237524974033228660">"Ungakhulumi unogwaja omubi"</string>
+    <string name="spoken_emoji_1F64B" msgid="4251150782016370475">"Umuntu ojabulile ophakamisa isandla esisodwa"</string>
+    <string name="spoken_emoji_1F64C" msgid="5446231430684558344">"Umuntu ophakamise izandla ezimbili ngenxa yenjabulo"</string>
+    <string name="spoken_emoji_1F64D" msgid="4646485595309482342">"Umuntu ohlinayo"</string>
+    <string name="spoken_emoji_1F64E" msgid="3376579939836656097">"Umuntu onobuso obuphukulayo"</string>
+    <string name="spoken_emoji_1F64F" msgid="1044439574356230711">"Umuntu nezandla ezigoqiwe"</string>
+    <string name="spoken_emoji_1F680" msgid="513263736012689059">"Irokhethi"</string>
+    <string name="spoken_emoji_1F681" msgid="9201341783850525339">"Indiza"</string>
+    <string name="spoken_emoji_1F682" msgid="8046933583867498698">"Intuthu yesitimela"</string>
+    <string name="spoken_emoji_1F683" msgid="8772750354339223092">"Imoto yojantshi"</string>
+    <string name="spoken_emoji_1F684" msgid="346396777356203608">"Isitimela sejubane elisheshayo"</string>
+    <string name="spoken_emoji_1F685" msgid="1237059817190832730">"Isitimela sejubane elisheshayo nekhala elicijile"</string>
+    <string name="spoken_emoji_1F686" msgid="3525197227223620343">"Isitimela"</string>
+    <string name="spoken_emoji_1F687" msgid="5110143437960392837">"I-Metro"</string>
+    <string name="spoken_emoji_1F688" msgid="4702085029871797965">"Ujantshi olula"</string>
+    <string name="spoken_emoji_1F689" msgid="2375851019798817094">"Isiteshi"</string>
+    <string name="spoken_emoji_1F68A" msgid="6368370859718717198">"Ithilamu"</string>
+    <string name="spoken_emoji_1F68B" msgid="2920160427117436633">"Imoto yethilamu"</string>
+    <string name="spoken_emoji_1F68C" msgid="1061520934758810864">"Ibhasi"</string>
+    <string name="spoken_emoji_1F68D" msgid="2890059031360969304">"Ibhasi ezayo"</string>
+    <string name="spoken_emoji_1F68E" msgid="6234042976027309654">"Ibhasi yenqola"</string>
+    <string name="spoken_emoji_1F68F" msgid="5871099334672012107">"Isitobhi sebhasi"</string>
+    <string name="spoken_emoji_1F690" msgid="8080964620200195262">"Ikhumbi"</string>
+    <string name="spoken_emoji_1F691" msgid="999173032408730501">"I-Ambulensi"</string>
+    <string name="spoken_emoji_1F692" msgid="1712863785341849487">"Injini yomlilo"</string>
+    <string name="spoken_emoji_1F693" msgid="7987109037389768934">"Imoto yamaphoyisa"</string>
+    <string name="spoken_emoji_1F694" msgid="6061658916653884608">"Imoto yamaphoyisa ezayo"</string>
+    <string name="spoken_emoji_1F695" msgid="6913445460364247283">"Itekisi"</string>
+    <string name="spoken_emoji_1F696" msgid="6391604457418285404">"Itekisi ezayo"</string>
+    <string name="spoken_emoji_1F697" msgid="7978399334396733790">"Izimoto"</string>
+    <string name="spoken_emoji_1F698" msgid="7006050861129732018">"Izimoto ezizayo"</string>
+    <string name="spoken_emoji_1F699" msgid="630317052666590607">"Imoto yokuzithokozisa"</string>
+    <string name="spoken_emoji_1F69A" msgid="4739797891735823577">"Iloli yokuthumela"</string>
+    <string name="spoken_emoji_1F69B" msgid="4715997280786620649">"Iloli enezingxenye ezimbili"</string>
+    <string name="spoken_emoji_1F69C" msgid="5557395610750818161">"Ugandaganda"</string>
+    <string name="spoken_emoji_1F69D" msgid="5467164189942951047">"Ujantshi omncane"</string>
+    <string name="spoken_emoji_1F69E" msgid="169238196389832234">"Ujantshi wasentabeni"</string>
+    <string name="spoken_emoji_1F69F" msgid="7508128757012845102">"Ukumiswa kojantshi"</string>
+    <string name="spoken_emoji_1F6A0" msgid="8733056213790160147">"Imoto yekhubula yasentabeni"</string>
+    <string name="spoken_emoji_1F6A1" msgid="4666516337749347253">"Indlela yethilamu ye-Aerial"</string>
+    <string name="spoken_emoji_1F6A2" msgid="4511220588943129583">"Umkhumbi"</string>
+    <string name="spoken_emoji_1F6A3" msgid="8412962252222205387">"Isikebhe somdlalo"</string>
+    <string name="spoken_emoji_1F6A4" msgid="8867571300266339211">"Isikebhe esigijimayo"</string>
+    <string name="spoken_emoji_1F6A5" msgid="7650260812741963884">"Ilobhothi elivundlile"</string>
+    <string name="spoken_emoji_1F6A6" msgid="485575967773793454">"Ilobhothi emile"</string>
+    <string name="spoken_emoji_1F6A7" msgid="6411048933816976794">"Uphawu lesakhiwo"</string>
+    <string name="spoken_emoji_1F6A8" msgid="6345717218374788364">"Izimoto zamaphoyisa ezikhanyisayo"</string>
+    <string name="spoken_emoji_1F6A9" msgid="6586380356807600412">"Ifulegi engunxantathu eposini"</string>
+    <string name="spoken_emoji_1F6AA" msgid="8954448167261738885">"Umnyango"</string>
+    <string name="spoken_emoji_1F6AB" msgid="5313946262888343544">"Alukho uphawu lokungena"</string>
+    <string name="spoken_emoji_1F6AC" msgid="6946858177965948288">"Uphawu lokubhema"</string>
+    <string name="spoken_emoji_1F6AD" msgid="6320088669185507241">"Uphawu lokungabhemi"</string>
+    <string name="spoken_emoji_1F6AE" msgid="1062469925352817189">"Uphawu lokubeka udoti endaweni yawo"</string>
+    <string name="spoken_emoji_1F6AF" msgid="2286668056123642208">"Uphawu lokungalahleli phansi"</string>
+    <string name="spoken_emoji_1F6B0" msgid="179424763882990952">"Uphawu lamanzi aphuzwayo"</string>
+    <string name="spoken_emoji_1F6B1" msgid="5585212805429161877">"Uphawu lamanzi angaphuzwa"</string>
+    <string name="spoken_emoji_1F6B2" msgid="1771885082068421875">"Ibhayisikili"</string>
+    <string name="spoken_emoji_1F6B3" msgid="8033779581263314408">"Awekho amabhayisikili"</string>
+    <string name="spoken_emoji_1F6B4" msgid="1999538449018476947">"Umqhubi webhayisikili"</string>
+    <string name="spoken_emoji_1F6B5" msgid="340846352660993117">"Umqhubi webhayisikili entabeni"</string>
+    <string name="spoken_emoji_1F6B6" msgid="4351024386495098336">"Abahamba ngezinyawo"</string>
+    <string name="spoken_emoji_1F6B7" msgid="4564800655866838802">"Abavumelekile abahamba ngezinyawo"</string>
+    <string name="spoken_emoji_1F6B8" msgid="3020531906940267349">"Indawo yokuhamba izingane"</string>
+    <string name="spoken_emoji_1F6B9" msgid="1207095844125041251">"Uphawu lamadoda"</string>
+    <string name="spoken_emoji_1F6BA" msgid="2346879310071017531">"Uphawu labesifazane"</string>
+    <string name="spoken_emoji_1F6BB" msgid="2370172469642078526">"Indawo yangasese"</string>
+    <string name="spoken_emoji_1F6BC" msgid="5558827593563530851">"Uphawu labantwana"</string>
+    <string name="spoken_emoji_1F6BD" msgid="9213590243049835957">"Indlu yangasese"</string>
+    <string name="spoken_emoji_1F6BE" msgid="394016533781742491">"Ikhosambana lamanzi"</string>
+    <string name="spoken_emoji_1F6BF" msgid="906336365928291207">"Ishawa"</string>
+    <string name="spoken_emoji_1F6C0" msgid="4592099854378821599">"Ubhavu"</string>
+    <string name="spoken_emoji_1F6C1" msgid="2845056048320031158">"Ubhavu"</string>
+    <string name="spoken_emoji_1F6C2" msgid="8117262514698011877">"Ukulawula iphasiphothi"</string>
+    <string name="spoken_emoji_1F6C3" msgid="1176342001834630675">"Umnyango wezimpahla"</string>
+    <string name="spoken_emoji_1F6C4" msgid="1477622834179978886">"Ukulanda umthwalo"</string>
+    <string name="spoken_emoji_1F6C5" msgid="2495834050856617451">"Umthwalo oshiyiwe"</string>
+</resources>
diff --git a/java/res/values-zu/strings-talkback-descriptions.xml b/java/res/values-zu/strings-talkback-descriptions.xml
index 6d3de70..0673405 100644
--- a/java/res/values-zu/strings-talkback-descriptions.xml
+++ b/java/res/values-zu/strings-talkback-descriptions.xml
@@ -25,6 +25,7 @@
     <string name="spoken_no_text_entered" msgid="1711276837961785646">"Awukho umbhalo ofakiwe"</string>
     <string name="spoken_auto_correct" msgid="8989324692167993804">"I-<xliff:g id="KEY_NAME">%1$s</xliff:g> ilungisa i-<xliff:g id="ORIGINAL_WORD">%2$s</xliff:g> kube yi-<xliff:g id="CORRECTED_WORD">%3$s</xliff:g>"</string>
     <string name="spoken_auto_correct_obscured" msgid="7769449372355268412">"I-<xliff:g id="KEY_NAME">%1$s</xliff:g> yenza ukulungisa okuzenzakalelayo"</string>
+    <string name="spoken_empty_suggestion" msgid="4250215619373459752">"Asikho isiphakamiso"</string>
     <string name="spoken_description_unknown" msgid="5139930082759824442">"Uhlamvu olungaziwa"</string>
     <string name="spoken_description_shift" msgid="7209798151676638728">"U-Shift"</string>
     <string name="spoken_description_symbols_shift" msgid="3483198879916435717">"Amasimbuli amaningi"</string>
@@ -76,6 +77,12 @@
     <string name="spoken_letter_0130" msgid="4766619646231612274">"Ufeleba I, icashazi ngenhla"</string>
     <string name="spoken_symbol_unknown" msgid="717298227061173706">"Uphawu olungaziwa"</string>
     <string name="spoken_emoji_unknown" msgid="5981009928135394306">"I-emoji engaziwa"</string>
+    <string name="spoken_emoticon_3A_2D_21_20" msgid="2410905667389534573">"Ubuso obunesithukuthezi"</string>
+    <string name="spoken_emoticon_3A_2D_24_20" msgid="2481260475945560438">"Ubuso obuphoxekile"</string>
+    <string name="spoken_emoticon_42_2D_29_20" msgid="1063205250387128068">"Ubuso obugqoke izibuko"</string>
+    <string name="spoken_emoticon_3A_4F_20" msgid="532695091593447238">"Ubuso obumangele"</string>
+    <string name="spoken_emoticon_3A_2D_2A_20" msgid="5612342617244114291">"Ukubso bokuqabula"</string>
+    <string name="spoken_emoticon_3A_2D_5B_20" msgid="2223507987759905920">"Ubuso obuswacile"</string>
     <string name="spoken_open_more_keys_keyboard" msgid="6832897688371903747">"Ezinye izinhlamvu ziyatholakala"</string>
     <string name="spoken_close_more_keys_keyboard" msgid="3524914657934712026">"Ezinye izinhlamvu ziyalahlwa"</string>
     <string name="spoken_open_more_suggestions" msgid="4231720702882969760">"Ezinye iziphakamiso ziyatholakala"</string>
diff --git a/java/res/values-zu/strings.xml b/java/res/values-zu/strings.xml
index e644a12..9ed9742 100644
--- a/java/res/values-zu/strings.xml
+++ b/java/res/values-zu/strings.xml
@@ -26,24 +26,29 @@
     <string name="vibrate_on_keypress" msgid="5258079494276955460">"Dlidlizelisa ngokucindezela inkinobho"</string>
     <string name="sound_on_keypress" msgid="6093592297198243644">"Umsindo wokucindezela ukhiye"</string>
     <string name="popup_on_keypress" msgid="123894815723512944">"Ugaxekile ngokucindezela ukhiye"</string>
-    <!-- no translation found for settings_screen_input (2808654300248306866) -->
-    <skip />
-    <!-- no translation found for settings_screen_appearances (3611951947835553700) -->
-    <skip />
-    <!-- no translation found for settings_screen_multi_lingual (6829970893413937235) -->
-    <skip />
-    <!-- no translation found for settings_screen_gesture (9113437621722871665) -->
-    <skip />
-    <!-- no translation found for settings_screen_correction (1616818407747682955) -->
-    <skip />
-    <!-- no translation found for settings_screen_advanced (7472408607625972994) -->
-    <skip />
+    <string name="settings_screen_preferences" msgid="2696713156722014624">"Izintandokazi"</string>
+    <string name="settings_screen_accounts" msgid="2786418968536696670">"Ama-akhawunti nobumfihlo"</string>
+    <string name="settings_screen_appearance" msgid="7358046399111611615">"Ukubonakala nezakhiwo"</string>
+    <string name="settings_screen_gesture" msgid="8826372746901183556">"Ukuthayipha ngokuthinta"</string>
+    <string name="settings_screen_correction" msgid="1616818407747682955">"Ukulungisa umbhalo"</string>
+    <string name="settings_screen_advanced" msgid="7472408607625972994">"Okuthuthukisiwe"</string>
+    <string name="settings_screen_theme" msgid="2137262503543943871">"Itimu"</string>
+    <string name="enable_split_keyboard" msgid="4177264923999493614">"Nika amandla ikhibhodi yokuhlukanisa"</string>
+    <string name="cloud_sync_title" msgid="8579271074443847055">"Ukuvumlanisa kwekhibhodi ye-Google"</string>
+    <string name="cloud_sync_summary" msgid="7684887161145650857">"Ukuvumelanisa kuvuliwe"</string>
+    <string name="cloud_sync_summary_disabled" msgid="4553338970382825796">"Vumelanisa isichazamazwi sakho kuwo wonke amadivayisi wakho"</string>
+    <string name="sync_now_title" msgid="3088838136743277721">"Vumelanisa manje"</string>
+    <string name="clear_sync_data_title" msgid="8582001557037069154">"Susa idatha yamafu"</string>
+    <string name="clear_sync_data_summary" msgid="993477139012576584">"Susa idatha yakho evumelanisiwe esuka ku-Google"</string>
+    <string name="clear_sync_data_confirmation" msgid="2811931135574727678">"Idatha yakho evumelanisiwe izosuswa emafini. Ingabe uqinisekile?"</string>
+    <string name="clear_sync_data_ok" msgid="613104067705915132">"Susa"</string>
+    <string name="cloud_sync_cancel" msgid="5877481252150919037">"Khansela"</string>
+    <string name="cloud_sync_opt_in_text" msgid="9176039655776298248">"Isichazamazwi sakho somuntu siqu sizovumelaniswa siphinde senziwe isipele kumaseva we-Google. Ulwazi lezibalo lemvamisa yegama lingaqoqwa ukusiza ukuthuthukisa imikhiqizo yethu. Ukuqoqwa nokusetshenziswa kwalo lonke ulwazi kuzohambisana ne-"<a href="https://www.google.com/policies/privacy">"Inqubomgomo Yobumfihlo ye-Google"</a>"."</string>
+    <string name="add_account_to_enable_sync" msgid="7836932571852055265">"Sicela ungeze i-akhawunti ye-Google kule divayisi ukuze unike amandla lesi sici"</string>
     <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Shintshela kwezinye izindlela zokungena"</string>
     <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ukhiye wokushintsha ulimi ubandakanya ezinye izindlela zokungenayo"</string>
     <string name="show_language_switch_key" msgid="5915478828318774384">"Ukhiye wokushintsha ullimi"</string>
     <string name="show_language_switch_key_summary" msgid="7343403647474265713">"Bonisa uma izilimi zokufaka zinikwe amandla"</string>
-    <string name="sliding_key_input_preview" msgid="6604262359510068370">"Bonisa isikhombi sesilayidi"</string>
-    <string name="sliding_key_input_preview_summary" msgid="6340524345729093886">"Bonisa isiboniso ngenkathi uslayida kusukela kukhiye ongu-Shift noma i-Symbol"</string>
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Ukuvela kokhiye cashisa ukulibazisa"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Cha ukulibazisa"</string>
     <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Okuzenzakalelayo"</string>
@@ -62,9 +67,6 @@
     <string name="main_dictionary" msgid="4798763781818361168">"Isichazamazwi sakho ngqangi"</string>
     <string name="prefs_show_suggestions" msgid="8026799663445531637">"Bonisa ukusikesela kokulungisa"</string>
     <string name="prefs_show_suggestions_summary" msgid="1583132279498502825">"Bonisa amagama aphakamisiwe ngenkathi uthayipha"</string>
-    <string name="prefs_suggestion_visibility_show_name" msgid="3219916594067551303">"Bonisa njalo"</string>
-    <string name="prefs_suggestion_visibility_show_only_portrait_name" msgid="3859783767435239118">"Bonisa ngomumo oqondile"</string>
-    <string name="prefs_suggestion_visibility_hide_name" msgid="6309143926422234673">"Fihla njalo"</string>
     <string name="prefs_block_potentially_offensive_title" msgid="5078480071057408934">"Vimba amagama ahlaselayo"</string>
     <string name="prefs_block_potentially_offensive_summary" msgid="2371835479734991364">"Ungaphakamisi amagama angaba nokuhlaselayo"</string>
     <string name="auto_correction" msgid="7630720885194996950">"Ukulungisa okuzenzakalelayo"</string>
@@ -85,21 +87,32 @@
     <string name="voice_input" msgid="3583258583521397548">"Inkinobho yokufaka izwi"</string>
     <string name="voice_input_disabled_summary" msgid="8141750303464726129">"Azikho izindlela zokufaka zezwi ezinikwe amandla. Hlola izilungiselelo zolimi kanye nezokufaka."</string>
     <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string>
-    <string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string>
-    <string name="send_feedback" msgid="1780431884109392046">"Thumela impendulo"</string>
-    <string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string>
+    <string name="language_selection_title" msgid="3666971864764478269">"Izilimi"</string>
+    <string name="help_and_feedback" msgid="5328219371839879161">"Usizo nempendulo"</string>
+    <string name="select_language" msgid="5709487854987078367">"Izilimi"</string>
     <string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string>
+    <string name="hint_add_to_dictionary_without_word" msgid="3040385779511255101">"Thinta lapha ukuze ulondoloze"</string>
     <string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string>
     <string name="keyboard_layout" msgid="8451164783510487501">"Indikimba yekhibhodi"</string>
+    <string name="switch_accounts" msgid="3321216593719006162">"Shintshanisa ama-akhawunti"</string>
+    <string name="no_accounts_selected" msgid="2073821619103904330">"Awekho ama-akhawunti akhethiwe"</string>
+    <string name="account_selected" msgid="2846876462199625974">"Okwamanje isebenzisa i-<xliff:g id="EMAIL_ADDRESS">%1$s</xliff:g>"</string>
+    <string name="account_select_ok" msgid="9141195141763227797">"KULUNGILE"</string>
+    <string name="account_select_cancel" msgid="5181012062618504340">"Khansela"</string>
+    <string name="account_select_sign_out" msgid="3299651159390187933">"Phuma ngemvume"</string>
+    <string name="account_select_title" msgid="6279711684772922649">"Khetha i-akhawunti ezosetshenziswa"</string>
     <string name="subtype_en_GB" msgid="88170601942311355">"i-English(UK)"</string>
     <string name="subtype_en_US" msgid="6160452336634534239">"i-English (US)"</string>
     <string name="subtype_es_US" msgid="5583145191430180200">"I-Spanish (US)"</string>
+    <string name="subtype_hi_ZZ" msgid="8860448146262798623">"I-Hinglish"</string>
+    <string name="subtype_sr_ZZ" msgid="9059219552986034343">"Isi-Serbian (Latin)"</string>
     <string name="subtype_with_layout_en_GB" msgid="1931018968641592304">"I-English (UK) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_en_US" msgid="8809311287529805422">"I-English (US) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
     <string name="subtype_with_layout_es_US" msgid="510930471167541338">"Isi-Spanish (US) ( <xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g> )"</string>
+    <string name="subtype_with_layout_hi_ZZ" msgid="6827402953860547044">"I-Hinglish (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
+    <string name="subtype_with_layout_sr_ZZ" msgid="2859024772719772407">"Isi-Serbian (<xliff:g id="KEYBOARD_LAYOUT">%s</xliff:g>)"</string>
     <string name="subtype_generic_traditional" msgid="8584594350973800586">"Isi-<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Tradition)"</string>
-    <string name="subtype_generic_cyrillic" msgid="7486451947618138947">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Isi-Cyrillic)"</string>
-    <string name="subtype_generic_latin" msgid="9128716486310604145">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Isi-Latin)"</string>
+    <string name="subtype_generic_compact" msgid="3353673321203202922">"<xliff:g id="LANGUAGE_NAME">%s</xliff:g> (Okuqoqene ndawonye)"</string>
     <string name="subtype_no_language" msgid="7137390094240139495">"Alikho ulimi (Alfabhethi)"</string>
     <string name="subtype_no_language_qwerty" msgid="244337630616742604">"Alfabhethi (QWERTY)"</string>
     <string name="subtype_no_language_qwertz" msgid="443066912507547976">"Alfabhethi (QWERTZ)"</string>
@@ -108,16 +121,7 @@
     <string name="subtype_no_language_colemak" msgid="5837418400010302623">"Alfabhethi (Colemak)"</string>
     <string name="subtype_no_language_pcqwerty" msgid="5354918232046200018">"Alfabhethi (PC)"</string>
     <string name="subtype_emoji" msgid="7483586578074549196">"I-Emoji"</string>
-    <!-- no translation found for keyboard_theme (4909551808526178852) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_white (8506588144096428751) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_holo_blue (192400518003397418) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_dark (2701178578784760596) -->
-    <skip />
-    <!-- no translation found for keyboard_theme_material_light (3479400901818790331) -->
-    <skip />
+    <string name="keyboard_theme" msgid="4909551808526178852">"Itimu yekhibhodi"</string>
     <string name="custom_input_styles_title" msgid="8429952441821251512">"Izitayela zokufaka ngokwezifiso"</string>
     <string name="add_style" msgid="6163126614514489951">"Engeza isitayela"</string>
     <string name="add" msgid="8299699805688017798">"Engeza"</string>
@@ -129,14 +133,9 @@
     <string name="enable" msgid="5031294444630523247">"Nika amandla"</string>
     <string name="not_now" msgid="6172462888202790482">"Hhayi manje"</string>
     <string name="custom_input_style_already_exists" msgid="8008728952215449707">"Isitayela sokufaka esifanayo sesivele sikhona: <xliff:g id="INPUT_STYLE_NAME">%s</xliff:g>"</string>
-    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ukulibazisa ukucindezela isikhashana ukhiye"</string>
     <string name="prefs_keypress_vibration_duration_settings" msgid="7918341459947439226">"Ubude besikhathi sokudlidliza ukucindezela ukhiye"</string>
     <string name="prefs_keypress_sound_volume_settings" msgid="6027007337036891623">"Ivolumu yomsindo wokucindezela ukhiye"</string>
-    <string name="prefs_read_external_dictionary" msgid="2588931418575013067">"Funda ifayela elangaphandle lesichazamazwi"</string>
-    <string name="read_external_dictionary_no_files_message" msgid="4947420942224623792">"Awekho amafayela wesichazamazwi kufolda yokulandiwe"</string>
-    <string name="read_external_dictionary_multiple_files_title" msgid="7637749044265808628">"Khetha ifayela lesichazamazwi ukuze ulifake"</string>
-    <string name="read_external_dictionary_confirm_install_message" msgid="4782116251651288054">"Fakela ngempela leli fayela i-<xliff:g id="LANGUAGE_NAME">%s</xliff:g>?"</string>
-    <string name="error" msgid="8940763624668513648">"Kube nephutha"</string>
+    <string name="prefs_key_longpress_timeout_settings" msgid="6102240298932897873">"Ukulibazisa ukucindezela isikhashana ukhiye"</string>
     <string name="button_default" msgid="3988017840431881491">"Okuzenzakalelayo"</string>
     <string name="setup_welcome_title" msgid="6112821709832031715">"Siyakwamukela ku-<xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="setup_welcome_additional_description" msgid="8150252008545768953">"nokuthayipha ngokuthinta"</string>
@@ -154,8 +153,6 @@
     <string name="setup_step3_instruction" msgid="8025981829605426000">"Manje usungathayipha ngokufaka zonke izinhlelo zokusebenza eziyizintandokazi zakho nge-<xliff:g id="APPLICATION_NAME">%s</xliff:g>."</string>
     <string name="setup_step3_action" msgid="600879797256942259">"Lungiselela izilimi ezingeziwe"</string>
     <string name="setup_finish_action" msgid="276559243409465389">"Iqedile"</string>
-    <string name="show_setup_wizard_icon" msgid="5008028590593710830">"Bonisa isithonjana sohlelo lokusebenza"</string>
-    <string name="show_setup_wizard_icon_summary" msgid="4119998322536880213">"Bonisa isithonjana sohlelo lokusebenza kusiqalisi"</string>
     <string name="app_name" msgid="6320102637491234792">"Umhlinzeki wesichazamazwi"</string>
     <string name="dictionary_provider_name" msgid="3027315045397363079">"Umhlinzeki wesichazamazwi"</string>
     <string name="dictionary_service_name" msgid="6237472350693511448">"Isevisi yesichazamazwi"</string>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index f1253b4..d9e42f1 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -20,6 +20,8 @@
 
 <resources>
     <declare-styleable name="KeyboardTheme">
+        <!-- InputView style -->
+        <attr name="inputViewStyle" format="reference" />
         <!-- Keyboard style -->
         <attr name="keyboardStyle" format="reference" />
         <!-- KeyboardView style -->
@@ -41,15 +43,18 @@
     </declare-styleable>
 
     <declare-styleable name="KeyboardView">
-        <!-- Background image for the key. This image needs to be a {@link StateListDrawable},
-             with the following possible states: normal, pressed, checkable, checkable+pressed,
-             checkable+checked, checkable+checked+pressed. -->
+        <!-- Background image for the key. This image needs to be a
+            {@link android.graphics.drawable.StateListDrawable}, with the following possible states:
+             normal, pressed, checkable, checkable+pressed, checkable+checked,
+             checkable+checked+pressed. -->
         <attr name="keyBackground" format="reference" />
         <!-- Background image for the functional key. This image needs to be a
-             {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+             {@link android.graphics.drawable.StateListDrawable}, with the following possible
+             states: normal, pressed. -->
         <attr name="functionalKeyBackground" format="reference" />
         <!-- Background image for the spacebar.  This image needs to be a
-             {@link StateListDrawable}, with the following possible states: normal, pressed. -->
+             {@link android.graphics.drawable.StateListDrawable}, with the following possible
+             states: normal, pressed. -->
         <attr name="spacebarBackground" format="reference" />
         <attr name="spacebarIconWidthRatio" format="float" />
         <!-- Right padding of hint letter to the edge of the key.-->
@@ -198,7 +203,8 @@
 
     <declare-styleable name="SuggestionStripView">
         <attr name="suggestionStripOptions" format="integer">
-            <!-- This should be aligned with SuggestionStripLayoutHelper.AUTO_CORRECT_* and etc. -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.latin.suggestions.SuggestionStripLayoutHelper.AUTO_CORRECT_BOLD} etc. -->
             <flag name="autoCorrectBold" value="0x01" />
             <flag name="autoCorrectUnderline" value="0x02" />
             <flag name="validTypedWordBold" value="0x04" />
@@ -216,7 +222,8 @@
 
     <declare-styleable name="Keyboard">
         <attr name="themeId" format="enum">
-            <!-- This should be aligned with KeyboardTheme.THEME_ID_*. -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
             <enum name="ICS" value="0" />
             <enum name="KLP" value="2" />
             <enum name="LXXLight" value="3" />
@@ -238,8 +245,8 @@
         <attr name="verticalGap" format="fraction" />
         <!-- More keys keyboard layout template -->
         <attr name="moreKeysTemplate" format="reference" />
-        <!-- Icon set for key top and key preview.
-             These should be aligned with KeyboardIconsSet.NAMES_AND_ATTR_IDS[] -->
+        <!-- Icon set for key top and key preview. These should be aligned with
+             {@link com.android.inputmethod.keyboard.internal.KeyboardIconsSet#NAMES_AND_ATTR_IDS} -->
         <attr name="iconShiftKey" format="reference" />
         <attr name="iconDeleteKey" format="reference" />
         <attr name="iconSettingsKey" format="reference" />
@@ -285,7 +292,8 @@
         <!-- Maximum column of more keys keyboard -->
         <attr name="maxMoreKeysColumn" format="integer" />
         <attr name="backgroundType" format="enum">
-            <!-- This should be aligned with Key.BACKGROUND_TYPE_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#BACKGROUND_TYPE_NORMAL} etc. -->
             <enum name="empty" value="0" />
             <enum name="normal" value="1" />
             <enum name="functional" value="2" />
@@ -296,7 +304,8 @@
         </attr>
         <!-- The key action flags. -->
         <attr name="keyActionFlags" format="integer">
-            <!-- This should be aligned with Key.ACTION_FLAGS_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#ACTION_FLAGS_IS_REPEATABLE} etc. -->
             <flag name="isRepeatable" value="0x01" />
             <flag name="noKeyPreview" value="0x02" />
             <flag name="altCodeWhileTyping" value="0x04" />
@@ -310,7 +319,8 @@
         <attr name="keyHintLabelVerticalAdjustment" format="fraction" />
         <!-- The key label flags. -->
         <attr name="keyLabelFlags" format="integer">
-            <!-- This should be aligned with Key.LABEL_FLAGS__* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.keyboard.Key#LABEL_FLAGS_FONT_NORMAL} etc. -->
             <flag name="alignHintLabelToBottom" value="0x02" />
             <flag name="alignIconToBottom" value="0x04" />
             <flag name="alignLabelOffCenter" value="0x08" />
@@ -355,7 +365,8 @@
         <!-- Width of the key, in the proportion of keyboard width.
              If the value is fillRight, the actual key width will be determined to fill out the
              area up to the right edge of the keyboard. -->
-        <!-- This should be aligned with KeyboardBuilder.Row.KEYWIDTH_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.internal.KeyboardRow#KEYWIDTH_FILL_RIGHT}. -->
         <attr name="keyWidth" format="fraction|enum">
             <enum name="fillRight" value="-1" />
         </attr>
@@ -366,7 +377,7 @@
 
         <!-- Key top visual attributes -->
         <attr name="keyTypeface" format="enum">
-            <!-- This should be aligned with Typeface.NORMAL etc. -->
+            <!-- This should be aligned with {@link android.graphics.Typeface#NORMAL} etc. -->
             <enum name="normal" value="0" />
             <enum name="bold" value="1" />
             <enum name="italic" value="2" />
@@ -389,11 +400,11 @@
         <attr name="keyShiftedLetterHintRatio" format="fraction" />
         <!-- The label's horizontal offset to the center of the key. Negative is to left and
              positive is to right. The value is in proportion of the width of
-             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+             {@link com.android.inputmethod.latin.utils.TypefaceUtils#KEY_LABEL_REFERENCE_CHAR}. -->
         <attr name="keyLabelOffCenterRatio" format="fraction" />
         <!-- The hint label's horizontal offset to the center of the key. Negative is to left and
              positive is to right. The value is in proportion of the width of
-             TypefaceUtils.KEY_LABEL_REFERENCE_CHAR. -->
+             {@link com.android.inputmethod.latin.utils.TypefaceUtils#KEY_LABEL_REFERENCE_CHAR}. -->
         <attr name="keyHintLabelOffCenterRatio" format="fraction" />
         <!-- Color to use for the label in a key. -->
         <attr name="keyTextColor" format="color" />
@@ -423,7 +434,8 @@
 
     <declare-styleable name="Keyboard_Case">
         <attr name="keyboardLayoutSet" format="string" />
-        <!-- This should be aligned with KeyboardLayoutSet_Element's elementName. -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#ELEMENT_ALPHABET} etc. -->
         <attr name="keyboardLayoutSetElement" format="enum|string">
             <enum name="alphabet" value="0" />
             <enum name="alphabetManualShifted" value="1" />
@@ -443,14 +455,16 @@
             <enum name="emojiCategory5" value="15" />
             <enum name="emojiCategory6" value="16" />
         </attr>
-        <!-- This should be aligned with Keyboard.themeId and KeyboardTheme.THEME_ID_* -->
+        <!-- This should be aligned with Keyboard.themeId and
+             {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
         <attr name="keyboardTheme" format="enum|string">
             <enum name="ICS" value="0" />
             <enum name="KLP" value="2" />
             <enum name="LXXLight" value="3" />
             <enum name="LXXDark" value="4" />
         </attr>
-        <!-- This should be aligned with KeyboardId.MODE_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#MODE_TEXT} etc. -->
         <attr name="mode" format="enum|string">
             <enum name="text" value="0" />
             <enum name="url" value="1" />
@@ -467,7 +481,8 @@
         <attr name="languageSwitchKeyEnabled" format="boolean" />
         <attr name="isMultiLine" format="boolean" />
         <attr name="imeAction" format="enum">
-            <!-- This should be aligned with EditorInfo.IME_ACTION_* -->
+            <!-- This should be aligned with
+                 {@link android.view.inputmethod.EditorInfo#IME_ACTION_GO} etc. -->
             <enum name="actionUnspecified" value="0" />
             <enum name="actionNone" value="1" />
             <enum name="actionGo" value="2" />
@@ -476,13 +491,16 @@
             <enum name="actionNext" value="5" />
             <enum name="actionDone" value="6" />
             <enum name="actionPrevious" value="7" />
-            <!--  This should be aligned with KeyboardId.IME_ACTION_* -->
+            <!-- This should be aligned with
+                 {@link com.android.inputmethod.latin.utils.InputTypeUtils#IME_ACTION_CUSTOM_LABEL}. -->
             <enum name="actionCustomLabel" value="0x100" />
         </attr>
         <attr name="isIconDefined" format="string" />
         <attr name="localeCode" format="string" />
         <attr name="languageCode" format="string" />
         <attr name="countryCode" format="string" />
+        <!-- Enable split keyboard layout. Disabled by default. -->
+        <attr name="isSplitLayout" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="Keyboard_KeyStyle">
@@ -491,7 +509,8 @@
     </declare-styleable>
 
     <declare-styleable name="KeyboardLayoutSet_Element">
-        <!-- This should be aligned with KeyboardId.ELEMENT_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.keyboard.KeyboardId#ELEMENT_ALPHABET} etc. -->
         <attr name="elementName" format="enum">
             <enum name="alphabet" value="0" />
             <enum name="alphabetManualShifted" value="1" />
@@ -514,10 +533,15 @@
         <attr name="elementKeyboard" format="reference"/>
         <!-- Enable proximity characters correction. Disabled by default. -->
         <attr name="enableProximityCharsCorrection" format="boolean" />
+        <!-- Indicates if the keyboard layout supports being split or not. false by default -->
+        <attr name="supportsSplitLayout" format="boolean" />
+        <!-- Allow redundant more keys when they are in the base layout. true by default. -->
+        <attr name="allowRedundantMoreKeys" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="KeyboardLayoutSet_Feature">
-        <!-- This should be aligned with ScriptUtils.SCRIPT_* -->
+        <!-- This should be aligned with
+             {@link com.android.inputmethod.latin.utils.ScriptUtils#SCRIPT_ARABIC} etc. -->
         <attr name="supportedScript" format="enum">
             <enum name="arabic" value="0" />
             <enum name="armenian" value="1" />
@@ -532,7 +556,7 @@
             <enum name="lao" value="10" />
             <enum name="latin" value="11" />
             <enum name="malayalam" value="12" />
-            <enum name="myanmar" value="13" />
+            <!-- Myanmar is disabled. <enum name="myanmar" value="13" /> -->
             <enum name="sinhala" value="14" />
             <enum name="tamil" value="15" />
             <enum name="telugu" value="16" />
diff --git a/java/res/values/config-auto-correction-thresholds.xml b/java/res/values/config-auto-correction-thresholds.xml
index 7d94a42..fc701c7 100644
--- a/java/res/values/config-auto-correction-thresholds.xml
+++ b/java/res/values/config-auto-correction-thresholds.xml
@@ -34,6 +34,12 @@
         <item>floatNegativeInfinity</item>
     </string-array>
 
+    <!-- Chosen to be slightly less than the "aggressive" threshold. This is the threshold for
+         a mildly plausible suggestion given the input; if no "plausible" suggestion is present
+         for a language, it's a strong indicator the user is not typing in this language, so we
+         may be more forgiving of whitelist entries in another language. -->
+    <string name="plausibility_threshold" translatable="false">0.065</string>
+
     <!-- The index of the auto correction threshold values array. -->
     <string name="auto_correction_threshold_mode_index_off" translatable="false">0</string>
     <string name="auto_correction_threshold_mode_index_modest" translatable="false">1</string>
diff --git a/java/res/values/config-common.xml b/java/res/values/config-common.xml
index 36fd30a..fb20f7c 100644
--- a/java/res/values/config-common.xml
+++ b/java/res/values/config-common.xml
@@ -20,8 +20,8 @@
 
 <resources>
     <bool name="config_block_potentially_offensive">true</bool>
-    <!-- Default value for next word prediction: after entering a word and a space only, should we look
-         at input history to suggest a hopefully helpful suggestions for the next word? -->
+    <!-- Default value for next word prediction: after entering a word and a space only, should we
+         look at input history to suggest a hopefully helpful suggestions for the next word? -->
     <bool name="config_default_next_word_prediction">true</bool>
 
     <integer name="config_delay_in_milliseconds_to_update_shift_state">100</integer>
diff --git a/java/res/values/config-dictionary-pack.xml b/java/res/values/config-dictionary-pack.xml
index d076af4..bf52de8 100644
--- a/java/res/values/config-dictionary-pack.xml
+++ b/java/res/values/config-dictionary-pack.xml
@@ -25,6 +25,6 @@
     <bool name="allow_over_roaming">false</bool>
     <bool name="dict_downloads_visible_in_download_UI">false</bool>
     <bool name="metadata_downloads_visible_in_download_UI">false</bool>
-    <bool name="display_notification_for_auto_update">false</bool>
-    <bool name="display_notification_for_user_requested_update">false</bool>
+    <bool name="display_notification_for_auto_update">true</bool>
+    <bool name="display_notification_for_user_requested_update">true</bool>
 </resources>
diff --git a/java/res/values/donottranslate-config-spacing-and-punctuations.xml b/java/res/values/donottranslate-config-spacing-and-punctuations.xml
index 2faf578..06144d0 100644
--- a/java/res/values/donottranslate-config-spacing-and-punctuations.xml
+++ b/java/res/values/donottranslate-config-spacing-and-punctuations.xml
@@ -33,9 +33,14 @@
     <string name="symbols_word_separators">"&#x0009;&#x0020;&#x000A;&#x00A0;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
     <!-- Word connectors -->
     <string name="symbols_word_connectors">\'-</string>
-    <!-- The sentence separator code point, for capitalization -->
+    <!-- The sentence separator code point, for capitalization and auto-insertion -->
     <!-- U+002E: "." FULL STOP   ; 2Eh = 46d -->
     <integer name="sentence_separator">46</integer>
+    <!-- The abbreviation marker code point -->
+    <!-- U+002E: "." FULL STOP   ; 2Eh = 46d -->
+    <integer name="abbreviation_marker">46</integer>
+    <!-- Symbols that terminate sentences and require capitalization on the next char -->
+    <string name="symbols_sentence_terminators">.?!</string>
     <!-- Whether this language uses spaces between words -->
     <bool name="current_language_has_spaces">true</bool>
 </resources>
diff --git a/java/res/values/donottranslate-debug-settings.xml b/java/res/values/donottranslate-debug-settings.xml
index 35e6efa..9df73ae 100644
--- a/java/res/values/donottranslate-debug-settings.xml
+++ b/java/res/values/donottranslate-debug-settings.xml
@@ -22,14 +22,11 @@
     <string name="english_ime_debug_settings">Android Keyboard Debug settings</string>
     <string name="prefs_debug_mode">Debug Mode</string>
     <string name="prefs_force_non_distinct_multitouch">Force non-distinct multitouch</string>
-    <string name="prefs_force_physical_keyboard_special_key">Force physical keyboard special key</string>
-    <string name="prefs_show_ui_to_accept_typed_word">Show UI to accept typed word</string>
+    <string name="prefs_should_show_lxx_suggestion_ui">Show LXX suggestion UI</string>
     <!-- Option to enable sliding key input indicator. The user can see a rubber band-like effect during sliding key input. [CHAR LIMIT=30]-->
     <string name="sliding_key_input_preview">Show slide indicator</string>
     <!-- Option summary to enable sliding key input indicator. The user can see a rubber band-like effect during sliding key input. [CHAR LIMIT=66]-->
     <string name="sliding_key_input_preview_summary">Display visual cue while sliding from Shift or Symbol keys</string>
-    <!-- Title of the settings for key long press delay [CHAR LIMIT=35] -->
-    <string name="prefs_key_longpress_timeout_settings">Key long press delay</string>
     <!-- Title of the settings for customize key popup animation parameters [CHAR LIMIT=35] -->
     <string name="prefs_customize_key_preview_animation">Customize key preview animation</string>
     <!-- Title of the settings for key popup show up animation duration (in milliseconds) [CHAR LIMIT=35] -->
@@ -44,16 +41,10 @@
     <string name="prefs_key_popup_dismiss_end_x_scale_settings">Key popup dismiss end X scale</string>
     <!-- Title of the settings for key popup dismiss animation end Y-scale (in percentile) [CHAR LIMIT=35] -->
     <string name="prefs_key_popup_dismiss_end_y_scale_settings">Key popup dismiss end Y scale</string>
-    <!-- Title of the settings for reading an external dictionary file -->
-    <string name="prefs_read_external_dictionary">Read external dictionary file</string>
-    <!-- Message to show when there are no files to install as an external dictionary [CHAR LIMIT=100] -->
-    <string name="read_external_dictionary_no_files_message">No dictionary files in the Downloads folder</string>
-    <!-- Title of the dialog that selects a file to install as an external dictionary [CHAR LIMIT=50] -->
-    <string name="read_external_dictionary_multiple_files_title">Select a dictionary file to install</string>
-    <!-- Title of the confirmation dialog to install a file as an external dictionary [CHAR LIMIT=50] -->
-    <string name="read_external_dictionary_confirm_install_message">Really install this file for <xliff:g id="LANGUAGE_NAME" example="English">%s</xliff:g>?</string>
-    <!-- Title for an error dialog that contains the details of the error in the body [CHAR LIMIT=80] -->
-    <string name="read_external_dictionary_error">There was an error</string>
+    <!-- Title of the settings to enable keyboard resizing -->
+    <string name="prefs_resize_keyboard">Enable keyboard resizing</string>
+    <!-- Title of the settings for setting keyboard height -->
+    <string name="prefs_keyboard_height_scale">Keyboard height scale</string>
     <!-- Title of the settings group for dumpping dictionary files that have been created on the device [CHAR LIMIT=35] -->
     <string name="prefs_dump_dynamic_dicts">Dump dictionary</string>
 </resources>
diff --git a/java/res/values/donottranslate-text-decorator.xml b/java/res/values/donottranslate-text-decorator.xml
deleted file mode 100644
index 2693645..0000000
--- a/java/res/values/donottranslate-text-decorator.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, 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>
-    <!-- The extra margin in dp around the hit area of the commit/add-to-dictionary indicator -->
-    <integer name="text_decorator_hit_area_margin_in_dp">
-        4
-    </integer>
-
-    <!-- Background color to be used to highlight the target text when the add-to-dictionary
-         indicator is visible. -->
-    <color name="text_decorator_add_to_dictionary_indicator_text_highlight_color">
-        #D1E7B7
-    </color>
-
-    <!-- Foreground color of the commit indicator. -->
-    <color name="text_decorator_add_to_dictionary_indicator_background_color">
-        #4EB848
-    </color>
-
-    <!-- Foreground color of the add-to-dictionary indicator. -->
-    <color name="text_decorator_add_to_dictionary_indicator_foreground_color">
-        #FFFFFF
-    </color>
-
-    <!-- Viewport size of "text_decorator_add_to_dictionary_indicator_path". -->
-    <integer name="text_decorator_add_to_dictionary_indicator_path_size">
-        480
-    </integer>
-
-    <!-- Coordinates of the closed path to be used to render the add-to-dictionary indicator.
-         The format is: X[0], Y[0], X[1], Y[1], ..., X[N-1], Y[N-1] -->
-    <integer-array name="text_decorator_add_to_dictionary_indicator_path">
-        <item>380</item>
-        <item>260</item>
-        <item>260</item>
-        <item>260</item>
-        <item>260</item>
-        <item>380</item>
-        <item>220</item>
-        <item>380</item>
-        <item>220</item>
-        <item>260</item>
-        <item>100</item>
-        <item>260</item>
-        <item>100</item>
-        <item>220</item>
-        <item>220</item>
-        <item>220</item>
-        <item>220</item>
-        <item>100</item>
-        <item>260</item>
-        <item>100</item>
-        <item>260</item>
-        <item>220</item>
-        <item>380</item>
-        <item>220</item>
-    </integer-array>
-</resources>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index c54b995..08d8bb2 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -19,7 +19,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- For backward compatibility.
-         See {@link SettingsValues#needsToShowVoiceInputKey(SharedPreferences,Resources)} -->
+         @see com.android.inputmethod.latin.settings.SettingsValues#needsToShowVoiceInputKey(android.content.SharedPreferences,android.content.res.Resources) -->
     <string name="voice_mode_main">0</string>
 
     <!-- Subtype locale display name exceptions.
@@ -30,8 +30,18 @@
         <item>en_US</item>
         <item>en_GB</item>
         <item>es_US</item>
+        <item>hi_ZZ</item>
+        <item>sr_ZZ</item>
     </string-array>
 
+    <!-- Subtype locale whose name should be displayed in Locale.ROOT. -->
+    <string-array name="subtype_locale_displayed_in_root_locale">
+        <item>hi_ZZ</item>
+        <item>sr_ZZ</item>
+    </string-array>
+    <string name="subtype_in_root_locale_hi_ZZ">Hinglish</string>
+    <string name="subtype_in_root_locale_sr_ZZ">Srpski</string>
+
     <!-- Generic subtype label -->
     <string name="subtype_generic">%s</string>
 
diff --git a/java/res/values/keyboard-themes.xml b/java/res/values/keyboard-themes.xml
index 9d772c4..26b2582 100644
--- a/java/res/values/keyboard-themes.xml
+++ b/java/res/values/keyboard-themes.xml
@@ -25,11 +25,12 @@
         <item>@string/keyboard_theme_holo_white</item>
         <item>@string/keyboard_theme_holo_blue</item>
     </string-array>
-    <!-- An element must be a keyboard theme id of {@link KeyboardTheme#THEME_ID_*}. -->
-    <string-array name="keyboard_theme_ids" translatable="false">
+    <!-- An element must be a keyboard theme id of
+         {@link com.android.inputmethod.keyboard.KeyboardTheme#THEME_ID_ICS} etc. -->
+    <integer-array name="keyboard_theme_ids" translatable="false">
         <item>3</item>
         <item>4</item>
         <item>2</item>
         <item>0</item>
-    </string-array>
+    </integer-array>
 </resources>
diff --git a/java/res/values/setup-wizard.xml b/java/res/values/setup-wizard.xml
index 8464709..90c3eca 100644
--- a/java/res/values/setup-wizard.xml
+++ b/java/res/values/setup-wizard.xml
@@ -18,5 +18,4 @@
 */
 -->
 <resources>
-    <bool name="config_setup_wizard_available">false</bool>
 </resources>
diff --git a/java/res/values/spinner-style.xml b/java/res/values/spinner-style.xml
new file mode 100644
index 0000000..c0f32ab
--- /dev/null
+++ b/java/res/values/spinner-style.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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">
+    <!-- Until KitKat (API 19), {@link android.widget.Spinner} of dialog mode in a Dialog can't
+         handle orientation change correctly. Using dropdown mode avoids the issue.
+         This file is overridden by values-v19/spinner-style.xml on KitKat and up. -->
+    <style name="additionalSubtypeSpinnerStyle">
+        <item name="android:spinnerMode">dropdown</item>
+    </style>
+</resources>
diff --git a/java/res/values/strings-talkback-descriptions.xml b/java/res/values/strings-talkback-descriptions.xml
index 80c7bdb..9644271 100644
--- a/java/res/values/strings-talkback-descriptions.xml
+++ b/java/res/values/strings-talkback-descriptions.xml
@@ -31,6 +31,9 @@
     <!-- Spoken description used during obscured (e.g. password) entry to let the user know that auto-correction will be performed when a key is pressed. -->
     <string name="spoken_auto_correct_obscured"><xliff:g id="KEY_NAME" example="Space">%1$s</xliff:g> performs auto-correction</string>
 
+    <!-- Spoken description of a suggestion when nothing is specified and the field is blank. -->
+    <string name="spoken_empty_suggestion">No suggestion</string>
+
     <!-- Spoken description for unknown keyboard keys. -->
     <string name="spoken_description_unknown">Unknown character</string>
     <!-- Spoken description for the "Shift" keyboard key when "Shift" is off. -->
@@ -139,6 +142,18 @@
     <string name="spoken_symbol_unknown">Unknown symbol</string>
     <!-- Spoken description for unknown emoji code point. -->
     <string name="spoken_emoji_unknown">Unknown emoji</string>
+    <!-- Spoken description for emoticons ":-!". -->
+    <string name="spoken_emoticon_3A_2D_21_20">Bored face</string>
+    <!-- Spoken description for emoticons ":-$". -->
+    <string name="spoken_emoticon_3A_2D_24_20">Embarrassed face</string>
+    <!-- Spoken description for emoticons "B-)". -->
+    <string name="spoken_emoticon_42_2D_29_20">Face wearing sunglasses</string>
+    <!-- Spoken description for emoticons ":O". -->
+    <string name="spoken_emoticon_3A_4F_20">Surprised face</string>
+    <!-- Spoken description for emoticons ":-*". -->
+    <string name="spoken_emoticon_3A_2D_2A_20">Kissing face</string>
+    <!-- Spoken description for emoticons ":-[". -->
+    <string name="spoken_emoticon_3A_2D_5B_20">Frowning face</string>
 
     <!-- Spoken descriptions when opening a more keys keyboard that has alternative characters. -->
     <string name="spoken_open_more_keys_keyboard">Alternative characters are available</string>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2f8b380..5655a55 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -38,10 +38,10 @@
 
     <!-- Settings screen title for preferences [CHAR LIMIT=33]-->
     <string name="settings_screen_preferences">Preferences</string>
+    <!-- Settings screen title for accounts and privacy preferences [CHAR LIMIT=33]-->
+    <string name="settings_screen_accounts">Accounts &amp; Privacy</string>
     <!-- Settings screen title for appearance & layouts preferences [CHAR LIMIT=33] -->
-    <string name="settings_screen_appearance">Appearance &amp; layouts</string>
-    <!-- Settings screen title for multilingual options [CHAR_LIMIT=33] -->
-    <string name="settings_screen_multilingual">Multilingual options</string>
+    <string name="settings_screen_appearance">Appearance &amp; Layouts</string>
     <!-- Settings screen title for gesture typing preferences [CHAR_LIMIT=33] -->
     <string name="settings_screen_gesture">Gesture Typing</string>
     <!-- Settings screen title for text correction options [CHAR_LIMIT=33] -->
@@ -51,6 +51,38 @@
     <!-- Settings screen title for keyboard theme settings [CHAR LIMIT=33] -->
     <string name="settings_screen_theme">Theme</string>
 
+    <!--  Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
+    <string name="enable_split_keyboard">Enable split keyboard</string>
+
+    <!-- Option title for enabling cloud sync feature [CHAR LIMIT=33]-->
+    <string name="cloud_sync_title">Google Keyboard Sync</string>
+    <!-- Option summary when cloud sync feature is enabled  [CHAR LIMIT=65] -->
+    <string name="cloud_sync_summary">Sync is turned on</string>
+    <!-- Option summary when cloud sync feature is disabled  [CHAR LIMIT=65] -->
+    <string name="cloud_sync_summary_disabled">Sync your personal dictionary across devices</string>
+    <!-- Option title for starting the sync cycle now. [CHAR LIMIT=33]-->
+    <string name="sync_now_title">Sync now</string>
+    <!-- Option title for letting user delete synced google keyboard data from Google servers.  [CHAR LIMIT=35] -->
+    <string name="clear_sync_data_title">Delete cloud data</string>
+    <!-- Option summary for letting user delete synced google keyboard data from Google servers. [CHAR LIMIT=65] -->
+    <string name="clear_sync_data_summary">Deletes your synced data from Google</string>
+    <!-- Text for confirmation dialog box asking user to confirm deletion of cloud data. [CHAR LIMIT=65] -->
+    <string name="clear_sync_data_confirmation">Your synced data will be deleted from the cloud. Are you sure?</string>
+    <!-- Option to confirm deleting of user data from cloud [CHAR LIMIT=20] -->
+    <string name="clear_sync_data_ok">Delete</string>
+    <!-- Option to cancel the deletion of user data from cloud [CHAR LIMIT=20] -->
+    <string name="cloud_sync_cancel">Cancel</string>
+    <!-- Option to agree to terms and conditions for enabling cloud sync feature. -->
+    <string name="cloud_sync_opt_in_text">Your personal dictionary will be synced and backed up to
+        Google servers. The statistical information of word frequency may be collected to help
+        improve our products. The collection and usage of all the information will be compliant with
+        <a href="https://www.google.com/policies/privacy">Google\'s Privacy Policy</a>.
+    </string>
+    <!-- Text to tell the user to add a Google account to the device to enable the cloud sync feature. [CHAR LIMIT=65]-->
+    <string name="add_account_to_enable_sync">
+        Please add a Google account to this device to enable this feature
+    </string>
+
     <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
     <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
     <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] -->
@@ -174,6 +206,23 @@
     <!-- Title of the item to change the keyboard theme [CHAR LIMIT=20]-->
     <string name="keyboard_layout">Keyboard theme</string>
 
+    <!-- Title of the preference item for switching accounts [CHAR LIMIT=30] -->
+    <string name="switch_accounts">Switch accounts</string>
+    <!-- Summary of the preference item for switching accounts when no accounts
+         are selected [CHAR LIMIT=65] -->
+    <string name="no_accounts_selected">No accounts selected</string>
+    <!-- Summary of the preference item for switching accounts when an account
+         is selected [CHAR LIMIT=65] -->
+    <string name="account_selected">Currently using <xliff:g id="EMAIL_ADDRESS" example="someone@example.com">%1$s</xliff:g></string>
+    <!-- Positive text for selecting an account -->
+    <string name="account_select_ok">OK</string>
+    <!-- Negative text for selecting an account -->
+    <string name="account_select_cancel">Cancel</string>
+    <!-- Text for signing out of an account -->
+    <string name="account_select_sign_out">Sign out</string>
+    <!-- Title of the account picker dialog for selecting an account [CHAR LIMIT=40] -->
+    <string name="account_select_title">Select an account to use</string>
+
     <!-- Description for English (UK) keyboard subtype [CHAR LIMIT=25]
          (UK) should be an abbreviation of United Kingdom to fit in the CHAR LIMIT. -->
     <string name="subtype_en_GB">English (UK)</string>
@@ -183,6 +232,11 @@
     <!-- Description for Spanish (US) keyboard subtype [CHAR LIMIT=25]
          (US) should be an abbreviation of United States to fit in the CHAR LIMIT. -->
     <string name="subtype_es_US">Spanish (US)</string>
+    <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype [CHAR LIMIT=25] -->
+    <string name="subtype_hi_ZZ">Hinglish</string>
+    <!-- Description for Serbian (Latin) keyboard subtype [CHAR LIMIT=25]
+         (Latin) can be an abbreviation to fit in the CHAR LIMIT. -->
+    <string name="subtype_sr_ZZ">Serbian (Latin)</string>
     <!-- Description for English (UK) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
          (UK) should be an abbreviation of United Kingdom to fit in the CHAR LIMIT.
          This should be identical to subtype_en_GB aside from the trailing (%s). -->
@@ -195,19 +249,18 @@
          (US) should be an abbreviation of United Statesn to fit in the CHAR LIMIT.
          This should be identical to subtype_es_US aside from the trailing (%s). -->
     <string name="subtype_with_layout_es_US">Spanish (US) (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
+    <!-- Description for Hinglish (https://en.wikipedia.org/wiki/Hinglish) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+         This should be identical to subtype_hi_ZZ aside from the trailing (%s). -->
+    <string name="subtype_with_layout_hi_ZZ">Hinglish (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
+    <!-- Description for Serbian (Latin) keyboard subtype with explicit keyboard layout [CHAR LIMIT=25]
+         This should be identical to subtype_sr_ZZ aside from the trailing (%s). -->
+    <string name="subtype_with_layout_sr_ZZ">Serbian (<xliff:g id="KEYBOARD_LAYOUT" example="QWERTY">%s</xliff:g>)</string>
     <!-- Description for "LANGUAGE_NAME" (Traditional) keyboard subtype [CHAR LIMIT=25]
          (Traditional) can be an abbreviation to fit in the CHAR LIMIT. -->
     <string name="subtype_generic_traditional"><xliff:g id="LANGUAGE_NAME" example="Nepali">%s</xliff:g> (Traditional)</string>
     <!-- Description for "LANGUAGE_NAME" (Compact) keyboard subtype [CHAR LIMIT=25]
-         (Compact) can be an abbreviation to fit in the CHAR LIMIT.
-         TODO: Remove translatable=false once we are settled down with the naming. -->
-    <string name="subtype_generic_compact" translatable="false"><xliff:g id="LANGUAGE_NAME" example="Hindi">%s</xliff:g> (Compact)</string>
-    <!-- Description for "LANGUAGE_NAME" (Cyrillic) keyboard subtype [CHAR LIMIT=25]
-         (Cyrillic) can be an abbreviation to fit in the CHAR LIMIT. -->
-    <string name="subtype_generic_cyrillic"><xliff:g id="LANGUAGE_NAME" example="Serbian">%s</xliff:g> (Cyrillic)</string>
-    <!-- Description for "LANGUAGE_NAME" (Latin) keyboard subtype [CHAR LIMIT=25]
-         (Latin) can be an abbreviation to fit in the CHAR LIMIT. -->
-    <string name="subtype_generic_latin"><xliff:g id="LANGUAGE_NAME" example="Serbian">%s</xliff:g> (Latin)</string>
+         (Compact) can be an abbreviation to fit in the CHAR LIMIT. -->
+    <string name="subtype_generic_compact"><xliff:g id="LANGUAGE_NAME" example="Hindi">%s</xliff:g> (Compact)</string>
     <!-- This string is displayed in a language list that allows to choose a language for
 suggestions in a software keyboard. This setting won't give suggestions in any particular
 language, hence "No language".
@@ -326,6 +379,14 @@
     <string name="prefs_keypress_vibration_duration_settings">Keypress vibration duration</string>
     <!-- Title of the settings for keypress sound volume [CHAR LIMIT=35] -->
     <string name="prefs_keypress_sound_volume_settings">Keypress sound volume</string>
+    <!-- Title of the settings for key long press delay [CHAR LIMIT=35] -->
+    <string name="prefs_key_longpress_timeout_settings">Key long press delay</string>
+    <!-- TODO: Let's finalize title of the settings and remove translatable="false" -->
+    <!-- Title of the settings for enabling Emoji palette triggered by the Alt key on physical keyboards [CHAR LIMIT=35] -->
+    <string name="prefs_enable_emoji_alt_physical_key" translatable="false">Emoji for physical keyboard</string>
+    <!-- TODO: Let's finalize title of the settings and remove translatable="false" -->
+    <!-- Description of the settings for enabling Emoji palette triggered by the Alt key on physical keyboards [CHAR LIMIT=64] -->
+    <string name="prefs_enable_emoji_alt_physical_key_summary" translatable="false">Physical Alt key shows the emoji palette</string>
 
     <!-- Title of the button to revert to the default value of the device in the settings dialog [CHAR LIMIT=15] -->
     <string name="button_default">Default</string>
@@ -368,10 +429,6 @@
     <string name="setup_step3_action">Configure additional languages</string>
     <!-- The label of the button that finishes the setup wizard. [CHAR_LIMIT=64] -->
     <string name="setup_finish_action">Finished</string>
-    <!-- Option to show setup wizard icon. [CHAR LIMIT=30]-->
-    <string name="show_setup_wizard_icon">Show app icon</string>
-    <!-- Description for the option to show setup wizard application icon of this IME in the laucher. [CHAR_LIMIT=65] -->
-    <string name="show_setup_wizard_icon_summary">Display application icon in the launcher</string>
 
     <!-- The dictionary provider application name. Visible in Settings/Applications/Manage applications. -->
     <string name="app_name">Dictionary Provider</string>
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 110f6b7..2f768de 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="KeyboardIcons" />
+    <style name="InputView" />
     <!-- Default theme values -->
     <style name="Keyboard">
         <item name="rowHeight">25%p</item>
@@ -104,8 +105,10 @@
     <style
         name="MainKeyboardView"
         parent="KeyboardView" />
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style name="EmojiPalettesView" />
     <style name="MoreKeysKeyboard" />
     <style name="MoreKeysKeyboardView" />
diff --git a/java/res/values/themes-holo.xml b/java/res/values/themes-holo.xml
index 9f1bd2f..efac656 100644
--- a/java/res/values/themes-holo.xml
+++ b/java/res/values/themes-holo.xml
@@ -19,6 +19,10 @@
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style
+        name="InputView.Holo"
+        parent="InputView"
+    />
     <!-- Holo KeyboardView theme (ICS and KLP) -->
     <style
         name="KeyboardView.Holo"
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index bfbac0a..26ebd2f 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="KeyboardTheme.ICS" parent="KeyboardIcons.Holo">
+        <item name="inputViewStyle">@style/InputView.Holo</item>
         <item name="keyboardStyle">@style/Keyboard.ICS</item>
         <item name="keyboardViewStyle">@style/KeyboardView.ICS</item>
         <item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item>
@@ -72,8 +73,10 @@
         <item name="languageOnSpacebarTextShadowRadius">1.0</item>
         <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.ICS"
         parent="MainKeyboardView.ICS"
diff --git a/java/res/values/themes-klp.xml b/java/res/values/themes-klp.xml
index 36b1fc1..c8e11a9 100644
--- a/java/res/values/themes-klp.xml
+++ b/java/res/values/themes-klp.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="KeyboardTheme.KLP" parent="KeyboardIcons.Holo">
+        <item name="inputViewStyle">@style/InputView.Holo</item>
         <item name="keyboardStyle">@style/Keyboard.KLP</item>
         <item name="keyboardViewStyle">@style/KeyboardView.KLP</item>
         <item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item>
@@ -72,8 +73,10 @@
         <item name="languageOnSpacebarTextShadowRadius">1.0</item>
         <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.KLP"
         parent="MainKeyboardView.KLP"
diff --git a/java/res/values/themes-lxx-dark.xml b/java/res/values/themes-lxx-dark.xml
index 67f94f3..0535064 100644
--- a/java/res/values/themes-lxx-dark.xml
+++ b/java/res/values/themes-lxx-dark.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="KeyboardTheme.LXX_Dark" parent="KeyboardIcons.LXX_Dark">
+        <item name="inputViewStyle">@style/InputView.LXX</item>
         <item name="keyboardStyle">@style/Keyboard.LXX_Dark</item>
         <item name="keyboardViewStyle">@style/KeyboardView.LXX_Dark</item>
         <item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Dark</item>
@@ -72,8 +73,10 @@
         <!-- A negative value to disable text shadow layer. -->
         <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.LXX_Dark"
         parent="MainKeyboardView.LXX_Dark"
diff --git a/java/res/values/themes-lxx-light.xml b/java/res/values/themes-lxx-light.xml
index be817f4..80e88b8 100644
--- a/java/res/values/themes-lxx-light.xml
+++ b/java/res/values/themes-lxx-light.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <style name="KeyboardTheme.LXX_Light" parent="KeyboardIcons.LXX_Light">
+        <item name="inputViewStyle">@style/InputView.LXX</item>
         <item name="keyboardStyle">@style/Keyboard.LXX_Light</item>
         <item name="keyboardViewStyle">@style/KeyboardView.LXX_Light</item>
         <item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Light</item>
@@ -72,8 +73,10 @@
         <!-- A negative value to disable text shadow layer. -->
         <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
     </style>
-    <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
+    <!-- Though {@link com.android.inputmethod.keyboard.emoji.EmojiPalettesView} doesn't extend
+         {@link com.android.inputmethod.keyboard.KeyboardView}, some views inside it, for instance
+         delete button, need themed {@link com.android.inputmethod.keyboard.KeyboardView}
+         attributes. -->
     <style
         name="EmojiPalettesView.LXX_Light"
         parent="MainKeyboardView.LXX_Light"
diff --git a/java/res/values/themes-lxx.xml b/java/res/values/themes-lxx.xml
index c721888..463306b 100644
--- a/java/res/values/themes-lxx.xml
+++ b/java/res/values/themes-lxx.xml
@@ -19,6 +19,10 @@
 -->
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style
+        name="InputView.LXX"
+        parent="InputView"
+    />
     <!-- LXX KeyboardView theme (LXX_Light and LXX_Dark) -->
     <style
         name="KeyboardView.LXX"
diff --git a/java/res/xml-sw600dp-land/key_space_3kw.xml b/java/res/xml-sw600dp-land/key_space_3kw.xml
new file mode 100644
index 0000000..47c4e48
--- /dev/null
+++ b/java/res/xml-sw600dp-land/key_space_3kw.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <!-- TODO: Consolidate the layout specification between protrait and landscape.
+         Ideally just the keyWidth should be different -->
+    <switch>
+        <!-- fa: Perisan
+             kn: Kannada
+             ne: Nepali
+             te: Telugu -->
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="7.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageCode="fa|kn|ne|te"
+            latin:languageSwitchKeyEnabled="false"
+        >
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="14.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="14.0%p" />
+        </case>
+        <!-- languageSwitchKeyEnabled="false" -->
+        <default>
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="21.0%p" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp-land/row_qwerty4.xml b/java/res/xml-sw600dp-land/row_qwerty4.xml
new file mode 100644
index 0000000..0fdb5c6
--- /dev/null
+++ b/java/res/xml-sw600dp-land/row_qwerty4.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <switch>
+        <!-- Split the 4th row for split layouts -->
+        <case
+            latin:isSplitLayout="true"
+        >
+            <Row
+                latin:keyWidth="7.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyboardLayout="@xml/key_space_3kw"
+                    latin:backgroundType="normal" />
+                <Spacer
+                    latin:keyWidth="28.0%p" />
+                <Key
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="21.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </case>
+        <default>
+            <Row
+                latin:keyWidth="9.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyXPos="19.0%p"
+                    latin:keyboardLayout="@xml/key_space_7kw"
+                    latin:backgroundType="normal" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp-land/rows_qwerty.xml b/java/res/xml-sw600dp-land/rows_qwerty.xml
new file mode 100644
index 0000000..b580dcf
--- /dev/null
+++ b/java/res/xml-sw600dp-land/rows_qwerty.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <include
+        latin:keyboardLayout="@xml/key_styles_common" />
+    <!-- First row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the first row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_left5"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="20.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_right5"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the first row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Second row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the second row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_left5"
+                    latin:keyXPos="4.0%p"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="23.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_right4"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the second row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2"
+                    latin:keyXPos="4.5%p"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Third row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the third row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_left4"
+                    latin:keyWidth="7.0%p" />
+                <Spacer
+                    latin:keyWidth="17.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_right3"
+                    latin:keyWidth="7.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="7.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the third row -->
+            <default>
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3"
+                    latin:keyWidth="9.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
+    </Row>
+    <!-- Fourth row -->
+    <include
+        latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/key_period.xml b/java/res/xml-sw600dp/key_period.xml
index df1daf7..3045cbc 100644
--- a/java/res/xml-sw600dp/key_period.xml
+++ b/java/res/xml-sw600dp/key_period.xml
@@ -25,17 +25,6 @@
     <!-- Kept as a separate file for cleaner overriding by an overlay.  -->
     <switch>
         <case
-            latin:languageCode="hi"
-            latin:keyboardLayoutSet="hindi_compact"
-        >
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key
-                latin:keySpec="\u0964"
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,&quot;,+,\\%,&amp;"
-                latin:backgroundType="functional" />
-        </case>
-        <case
             latin:keyboardLayoutSet="dvorak"
         >
             <Key
diff --git a/java/res/xml-sw600dp/key_space_3kw.xml b/java/res/xml-sw600dp/key_space_3kw.xml
new file mode 100644
index 0000000..8cc3a38
--- /dev/null
+++ b/java/res/xml-sw600dp/key_space_3kw.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <switch>
+        <case
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="8.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
+            latin:languageSwitchKeyEnabled="false"
+        >
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="16.0%p" />
+            <Key
+                latin:keyStyle="zwnjKeyStyle" />
+        </case>
+        <case
+            latin:languageSwitchKeyEnabled="true"
+        >
+            <Key
+                latin:keyStyle="languageSwitchKeyStyle" />
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="16.0%p" />
+        </case>
+        <!-- languageSwitchKeyEnabled="false" -->
+        <default>
+            <Key
+                latin:keyStyle="spaceKeyStyle"
+                latin:keyWidth="24.0%p" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml-sw600dp/key_space_7kw.xml b/java/res/xml-sw600dp/key_space_7kw.xml
index 3311f81..61e0765 100644
--- a/java/res/xml-sw600dp/key_space_7kw.xml
+++ b/java/res/xml-sw600dp/key_space_7kw.xml
@@ -22,12 +22,8 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <switch>
-        <!-- fa: Perisan
-             kn: Kannada
-             ne: Nepali
-             te: Telugu -->
         <case
-            latin:languageCode="fa|kn|ne|te"
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
             latin:languageSwitchKeyEnabled="true"
         >
             <Key
@@ -39,7 +35,7 @@
                 latin:keyStyle="zwnjKeyStyle" />
         </case>
         <case
-            latin:languageCode="fa|kn|ne|te"
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
             latin:languageSwitchKeyEnabled="false"
         >
             <Key
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index 006cda3..ea8f292 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -35,10 +35,6 @@
                 latin:keyLabelFlags="hasShiftedLetterHint" />
         </default>
     </switch>
-    <!-- Base key style for the key which may have settings key as more keys. -->
-    <key-style
-        latin:styleName="baseSettingsMoreKeysStyle"
-        latin:parentStyle="hasShiftedLetterHintStyle" />
     <include
         latin:keyboardLayout="@xml/key_styles_settings" />
     <!-- Functional key styles -->
diff --git a/java/res/xml-sw600dp/row_qwerty4.xml b/java/res/xml-sw600dp/row_qwerty4.xml
index ed7150d..bcfd2cb 100644
--- a/java/res/xml-sw600dp/row_qwerty4.xml
+++ b/java/res/xml-sw600dp/row_qwerty4.xml
@@ -21,23 +21,54 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:backgroundType="functional"
-    >
-        <Key
-            latin:keyStyle="toSymbolKeyStyle"
-            latin:keyWidth="10.0%p" />
-        <include
-            latin:keyboardLayout="@xml/key_comma" />
-        <!-- Space key. -->
-        <include
-            latin:keyXPos="19.0%p"
-            latin:keyboardLayout="@xml/key_space_7kw"
-            latin:backgroundType="normal" />
-        <include
-            latin:keyboardLayout="@xml/key_period" />
-        <include
-            latin:keyboardLayout="@xml/key_emoji" />
-    </Row>
+    <switch>
+        <!-- Split the 4th row for split layouts -->
+        <case
+            latin:isSplitLayout="true"
+        >
+            <Row
+                latin:keyWidth="8.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyboardLayout="@xml/key_space_3kw"
+                    latin:backgroundType="normal" />
+                <Spacer
+                    latin:keyWidth="20.0%p" />
+                <Key
+                    latin:keyStyle="spaceKeyStyle"
+                    latin:keyWidth="24.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </case>
+        <default>
+            <Row
+                latin:keyWidth="9.0%p"
+                latin:backgroundType="functional"
+            >
+                <Key
+                    latin:keyStyle="toSymbolKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/key_comma" />
+                <!-- Space key. -->
+                <include
+                    latin:keyXPos="19.0%p"
+                    latin:keyboardLayout="@xml/key_space_7kw"
+                    latin:backgroundType="normal" />
+                <include
+                    latin:keyboardLayout="@xml/key_period" />
+                <include
+                    latin:keyboardLayout="@xml/key_emoji" />
+            </Row>
+        </default>
+    </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/rows_bengali_akkhor.xml b/java/res/xml-sw600dp/rows_bengali_akkhor.xml
new file mode 100644
index 0000000..3e81a14
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_bengali_akkhor.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor1" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor2" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.182%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_myanmar.xml b/java/res/xml-sw600dp/rows_myanmar.xml
deleted file mode 100644
index 20d9d8a..0000000
--- a/java/res/xml-sw600dp/rows_myanmar.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <include latin:keyboardLayout="@xml/key_styles_common" />
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar1" />
-        <Key
-            latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillRight" />
-    </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar2" />
-    </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar3" />
-        <Key
-            latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillRight" />
-    </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <Key
-            latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="10.0%p" />
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar4" />
-        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
-    </Row>
-    <include latin:keyboardLayout="@xml/row_qwerty4" />
-</merge>
diff --git a/java/res/xml-sw600dp/rows_nepali_romanized.xml b/java/res/xml-sw600dp/rows_nepali_romanized.xml
index fe73fbd..41cd2f9 100644
--- a/java/res/xml-sw600dp/rows_nepali_romanized.xml
+++ b/java/res/xml-sw600dp/rows_nepali_romanized.xml
@@ -39,7 +39,7 @@
             latin:keyWidth="fillRight" />
     </Row>
     <Row
-        latin:keyWidth="8.182%p"
+        latin:keyWidth="8.0%p"
         latin:keyLabelFlags="fontNormal"
     >
         <Key
@@ -47,6 +47,9 @@
             latin:keyWidth="10.0%p" />
         <include latin:keyboardLayout="@xml/rowkeys_nepali_romanized3" />
         <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="fillRight" />
     </Row>
     <include latin:keyboardLayout="@xml/row_qwerty4" />
 </merge>
diff --git a/java/res/xml-sw600dp/rows_nepali_traditional.xml b/java/res/xml-sw600dp/rows_nepali_traditional.xml
index e56271f..d23ca24 100644
--- a/java/res/xml-sw600dp/rows_nepali_traditional.xml
+++ b/java/res/xml-sw600dp/rows_nepali_traditional.xml
@@ -45,8 +45,8 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="10.0%p" />
-        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3_left6" />
-        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3_right5" />
-    </Row>
+        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+        </Row>
     <include latin:keyboardLayout="@xml/row_qwerty4" />
 </merge>
diff --git a/java/res/xml-sw600dp/rows_number_normal.xml b/java/res/xml-sw600dp/rows_number_normal.xml
index 7a4700d..e6fdf73 100644
--- a/java/res/xml-sw600dp/rows_number_normal.xml
+++ b/java/res/xml-sw600dp/rows_number_normal.xml
@@ -24,17 +24,17 @@
     <Row>
         <Key
             latin:keySpec="-"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="+"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="."
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
@@ -53,13 +53,15 @@
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
+        <!-- U+FF0A: "*" FULLWIDTH ASTERISK -->
         <Key
-            latin:keyStyle="numStarKeyStyle"
+            latin:keySpec="&#xFF0A;|*"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="/"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <switch>
@@ -70,14 +72,14 @@
                     latin:keySpec=","
                     latin:keyLabelFlags="hasPopupHint"
                     latin:moreKeys="!text/morekeys_am_pm"
-                    latin:keyStyle="numKeyStyle"
+                    latin:keyStyle="numSymbolKeyStyle"
                     latin:keyWidth="10%p"
                     latin:backgroundType="functional" />
             </case>
             <default>
                 <Key
                     latin:keySpec=","
-                    latin:keyStyle="numKeyStyle"
+                    latin:keyStyle="numSymbolKeyStyle"
                     latin:keyWidth="10%p"
                     latin:backgroundType="functional" />
             </default>
@@ -100,12 +102,12 @@
     <Row>
         <Key
             latin:keySpec="("
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec=")"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <switch>
@@ -114,14 +116,14 @@
             >
                 <Key
                     latin:keySpec=":"
-                    latin:keyStyle="numKeyStyle"
+                    latin:keyStyle="numSymbolKeyStyle"
                     latin:keyWidth="10%p"
                     latin:backgroundType="functional" />
             </case>
             <default>
                 <Key
                     latin:keySpec="="
-                    latin:keyStyle="numKeyStyle"
+                    latin:keyStyle="numSymbolKeyStyle"
                     latin:keyWidth="10%p"
                     latin:backgroundType="functional" />
             </default>
@@ -143,8 +145,10 @@
         <Key
             latin:keyStyle="tabletNumSpaceKeyStyle"
             latin:keyWidth="30%p" />
+        <!-- U+FF0A: "*" FULLWIDTH ASTERISK -->
         <Key
-            latin:keyStyle="numStarKeyStyle"
+            latin:keySpec="&#xFF0A;|*"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyXPos="31%p" />
         <Key
             latin:keySpec="0"
diff --git a/java/res/xml-sw600dp/rows_number_password.xml b/java/res/xml-sw600dp/rows_number_password.xml
index 6c3855a..37e6338 100644
--- a/java/res/xml-sw600dp/rows_number_password.xml
+++ b/java/res/xml-sw600dp/rows_number_password.xml
@@ -70,7 +70,8 @@
         <Key
             latin:keyStyle="deleteKeyStyle" />
         <Key
-            latin:keyStyle="num0KeyStyle" />
+            latin:keyStyle="num0KeyStyle"
+            latin:keyHintLabel="+" />
         <Key
             latin:keyStyle="enterKeyStyle" />
         <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
diff --git a/java/res/xml-sw600dp/rows_phone.xml b/java/res/xml-sw600dp/rows_phone.xml
index 612397a..fc86a76 100644
--- a/java/res/xml-sw600dp/rows_phone.xml
+++ b/java/res/xml-sw600dp/rows_phone.xml
@@ -28,16 +28,18 @@
     <Row>
         <Key
             latin:keySpec="-"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="+"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
-            latin:keyStyle="numPauseKeyStyle"
+            latin:keySpec="!string/label_pause_key|,"
+            latin:keyLabelFlags="followKeyLabelRatio|autoXScale"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
@@ -55,16 +57,18 @@
     <Row>
         <Key
             latin:keySpec=","
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="."
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
-            latin:keyStyle="numWaitKeyStyle"
+            latin:keySpec="!string/label_wait_key|;"
+            latin:keyLabelFlags="followKeyLabelRatio|autoXScale"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
@@ -82,17 +86,17 @@
     <Row>
         <Key
             latin:keySpec="("
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec=")"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
             latin:keySpec="N"
-            latin:keyStyle="numKeyStyle"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyWidth="10%p"
             latin:backgroundType="functional" />
         <Key
@@ -109,13 +113,16 @@
         <Key
             latin:keyStyle="tabletNumSpaceKeyStyle"
             latin:keyWidth="30%p" />
+        <!-- U+FF0A: "*" FULLWIDTH ASTERISK -->
         <Key
-            latin:keyStyle="numStarKeyStyle"
+            latin:keySpec="&#xFF0A;|*"
+            latin:keyStyle="numSymbolKeyStyle"
             latin:keyXPos="31%p" />
         <Key
-            latin:keyStyle="num0KeyStyle" />
+            latin:keyStyle="num0KeyStyle"
+            latin:keyHintLabel="+" />
         <Key
             latin:keySpec="\#"
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
     </Row>
 </merge>
diff --git a/java/res/xml-sw600dp/rows_qwerty.xml b/java/res/xml-sw600dp/rows_qwerty.xml
index 58ba1d7..51df4b0 100644
--- a/java/res/xml-sw600dp/rows_qwerty.xml
+++ b/java/res/xml-sw600dp/rows_qwerty.xml
@@ -23,39 +23,114 @@
 >
     <include
         latin:keyboardLayout="@xml/key_styles_common" />
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty1" />
-        <Key
-            latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- TODO: Consolidate the layout specification between protrait and landscape.
+         Ideally just the keyWidth should be different and the spacer should adjust to fill
+         the available space. -->
+    <!-- First row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the first row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_left5"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1_right5"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the first row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty1"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="deleteKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty2"
-            latin:keyXPos="4.5%p" />
-        <Key
-            latin:keyStyle="enterKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- Second row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the second row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_left5"
+                    latin:keyXPos="4.0%p"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="14.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2_right4"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the second row -->
+            <default>
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty2"
+                    latin:keyXPos="4.5%p"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="enterKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
-    <Row
-        latin:keyWidth="9.0%p"
-    >
-        <Key
-            latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="10.0%p" />
-        <include
-            latin:keyboardLayout="@xml/rowkeys_qwerty3" />
-        <include
-            latin:keyboardLayout="@xml/keys_exclamation_question" />
-        <Key
-            latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="fillRight" />
+    <!-- Third row -->
+    <Row>
+        <switch>
+            <!-- Split keyboard layout for the third row -->
+            <case
+                latin:isSplitLayout="true"
+            >
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_left4"
+                    latin:keyWidth="8.0%p" />
+                <Spacer
+                    latin:keyWidth="8.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3_right3"
+                    latin:keyWidth="8.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="8.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+            </case>
+            <!-- Regular layout for the third row -->
+            <default>
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="10.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/rowkeys_qwerty3"
+                    latin:keyWidth="9.0%p" />
+                <include
+                    latin:keyboardLayout="@xml/keys_exclamation_question"
+                    latin:keyWidth="9.0%p" />
+                <Key
+                    latin:keyStyle="shiftKeyStyle"
+                    latin:keyWidth="fillRight" />
+            </default>
+        </switch>
     </Row>
+    <!-- Fourth row -->
     <include
         latin:keyboardLayout="@xml/row_qwerty4" />
 </merge>
diff --git a/java/res/xml-sw600dp/rows_serbian_qwertz.xml b/java/res/xml-sw600dp/rows_serbian_qwertz.xml
new file mode 100644
index 0000000..a3fb625
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_serbian_qwertz.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz1" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz2" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml-sw600dp/rows_uzbek.xml b/java/res/xml-sw600dp/rows_uzbek.xml
new file mode 100644
index 0000000..3cd9940
--- /dev/null
+++ b/java/res/xml-sw600dp/rows_uzbek.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek1" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek2" />
+        <Key
+            latin:keyStyle="enterKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <Row latin:keyWidth="8.182%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.0%p" />
+        <Spacer latin:keyWidth="3.181%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+        <include latin:keyboardLayout="@xml/keys_exclamation_question" />
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="fillRight"
+            latin:keyXPos="-10.0%p" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/kbd_bengali_akkhor.xml b/java/res/xml/kbd_bengali_akkhor.xml
new file mode 100644
index 0000000..6c81d53
--- /dev/null
+++ b/java/res/xml/kbd_bengali_akkhor.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rows_bengali_akkhor" />
+</Keyboard>
diff --git a/java/res/xml/kbd_myanmar.xml b/java/res/xml/kbd_myanmar.xml
deleted file mode 100644
index af997b1..0000000
--- a/java/res/xml/kbd_myanmar.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<Keyboard
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
-    latin:rowHeight="20%p"
-    latin:verticalGap="@fraction/config_key_vertical_gap_5row"
-    latin:keyLetterSize="@fraction/config_key_letter_ratio_5row"
-    latin:keyShiftedLetterHintRatio="@fraction/config_key_shifted_letter_hint_ratio_5row"
-    latin:touchPositionCorrectionData="@array/touch_position_correction_data_default"
->
-    <include
-        latin:keyboardLayout="@xml/rows_myanmar" />
-</Keyboard>
diff --git a/java/res/xml/kbd_serbian_qwertz.xml b/java/res/xml/kbd_serbian_qwertz.xml
new file mode 100644
index 0000000..4f763b8
--- /dev/null
+++ b/java/res/xml/kbd_serbian_qwertz.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rows_serbian_qwertz" />
+</Keyboard>
\ No newline at end of file
diff --git a/java/res/xml/kbd_uzbek.xml b/java/res/xml/kbd_uzbek.xml
new file mode 100644
index 0000000..84486a7
--- /dev/null
+++ b/java/res/xml/kbd_uzbek.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<Keyboard xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rows_uzbek" />
+</Keyboard>
\ No newline at end of file
diff --git a/java/res/xml/key_period.xml b/java/res/xml/key_period.xml
index fc27c02..5b59cff 100644
--- a/java/res/xml/key_period.xml
+++ b/java/res/xml/key_period.xml
@@ -23,32 +23,6 @@
 >
     <switch>
         <case
-            latin:languageCode="hi"
-            latin:keyboardLayoutSet="hindi_compact"
-        >
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key
-                latin:keySpec="\u0964"
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,&quot;,+,\\%,&amp;"
-                latin:backgroundType="functional" />
-        </case>
-        <case
-            latin:languageCode="ne"
-            latin:keyboardLayoutSet="nepali_traditional"
-        >
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include
-                latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" />
-            <Key
-                latin:keyStyle="baseKeyDevanagariSignVirama"
-                latin:keyLabelFlags="hasPopupHint"
-                latin:moreKeys="!text/morekeys_punctuation"
-                latin:backgroundType="functional" />
-        </case>
-        <case
             latin:keyboardLayoutSet="dvorak"
         >
             <Key
diff --git a/java/res/xml/key_space_5kw.xml b/java/res/xml/key_space_5kw.xml
index b1fe0bb..692c245 100644
--- a/java/res/xml/key_space_5kw.xml
+++ b/java/res/xml/key_space_5kw.xml
@@ -22,12 +22,8 @@
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
     <switch>
-        <!-- fa: Perisan
-             kn: Kannada
-             ne: Nepali
-             te: Telugu -->
         <case
-            latin:languageCode="fa|kn|ne|te"
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
             latin:languageSwitchKeyEnabled="true"
         >
             <Key
@@ -39,7 +35,7 @@
                 latin:keyStyle="zwnjKeyStyle" />
         </case>
         <case
-            latin:languageCode="fa|kn|ne|te"
+            latin:keyboardLayoutSet="bengali_akkhor|farsi|kannada|nepali_romanized|nepali_traditional|telugu"
             latin:languageSwitchKeyEnabled="false"
         >
             <Key
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index b36ddf2..d85438d 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -35,9 +35,6 @@
                 latin:keyLabelFlags="hasShiftedLetterHint" />
         </default>
     </switch>
-    <!-- Base key style for the key which may have settings key as more keys. -->
-    <key-style
-        latin:styleName="baseSettingsMoreKeysStyle" />
     <include
         latin:keyboardLayout="@xml/key_styles_settings" />
     <!-- Functional key styles -->
diff --git a/java/res/xml/key_styles_currency.xml b/java/res/xml/key_styles_currency.xml
index cfe9a90..de5e6f2 100644
--- a/java/res/xml/key_styles_currency.xml
+++ b/java/res/xml/key_styles_currency.xml
@@ -80,6 +80,7 @@
         </case>
         <!-- fa: Persian (Rial and Afgahni)
              hi: Hindi (Indian Rupee)
+             hi_ZZ: Hinglish (Indian Rupee)
              iw: Hebrew (New Sheqel)
              lo: Lao (Kip)
              mn: Mongolian (Tugrik)
@@ -97,8 +98,9 @@
             <include latin:keyboardLayout="@xml/key_styles_currency_generic" />
         </case>
         <!-- si_LK: Sinhala (Sri Lanka) (Sri Lanka Rupee)
-             ta_LK: Tamil (Sri Lanka) (Sri Lanka Rupee) -->
-        <case latin:countryCode="LK">
+             ta_LK: Tamil (Sri Lanka) (Sri Lanka Rupee)
+             bn_BD: Bengali (Bangladesh) (Taka) -->
+        <case latin:countryCode="LK|BD">
             <include latin:keyboardLayout="@xml/key_styles_currency_generic" />
         </case>
         <!-- bn_IN: Bengali (India) (Indian Rupee)
diff --git a/java/res/xml/key_styles_number.xml b/java/res/xml/key_styles_number.xml
index 97ae6c6..911c276 100644
--- a/java/res/xml/key_styles_number.xml
+++ b/java/res/xml/key_styles_number.xml
@@ -33,9 +33,7 @@
         latin:keyLabelFlags="fontNormal|followKeyLetterRatio|followFunctionalTextColor"
         latin:parentStyle="numKeyBaseStyle" />
     <key-style
-        latin:styleName="numFunctionalKeyStyle"
-        latin:keyLabelFlags="followKeyLargeLetterRatio"
-        latin:backgroundType="functional"
+        latin:styleName="numSymbolKeyStyle"
         latin:parentStyle="numKeyBaseStyle" />
     <key-style
         latin:styleName="numberKeyStyle"
@@ -89,11 +87,6 @@
         latin:keySpec="9"
         latin:keyHintLabel="WXYZ"
         latin:parentStyle="numberKeyStyle" />
-    <!-- U+FF0A: "*" FULLWIDTH ASTERISK -->
-    <key-style
-        latin:styleName="numStarKeyStyle"
-        latin:keySpec="&#xFF0A;|*"
-        latin:parentStyle="numKeyStyle" />
     <!-- Only for non-tablet device -->
     <key-style
         latin:styleName="numPhoneToSymbolKeyStyle"
@@ -104,16 +97,6 @@
         latin:keySpec="!text/keylabel_to_phone_numeric|!code/key_switch_alpha_symbol"
         latin:parentStyle="numModeKeyStyle" />
     <key-style
-        latin:styleName="numPauseKeyStyle"
-        latin:keySpec="!text/label_pause_key|,"
-        latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
-        latin:parentStyle="numKeyBaseStyle" />
-    <key-style
-        latin:styleName="numWaitKeyStyle"
-        latin:keySpec="!text/label_wait_key|;"
-        latin:keyLabelFlags="followKeyHintLabelRatio|autoXScale"
-        latin:parentStyle="numKeyBaseStyle" />
-    <key-style
         latin:styleName="numTabKeyStyle"
         latin:keyActionFlags="noKeyPreview"
         latin:parentStyle="tabKeyStyle" />
diff --git a/java/res/xml/key_styles_settings.xml b/java/res/xml/key_styles_settings.xml
index a504bed..43ee601 100644
--- a/java/res/xml/key_styles_settings.xml
+++ b/java/res/xml/key_styles_settings.xml
@@ -21,16 +21,14 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <!-- Base key style for the key which may have settings key as more keys. -->
-    <!-- Kept as a separate file for cleaner overriding by an overlay.  -->
+    <!-- Key style for the key which may have settings key as more keys. -->
     <switch>
         <case
             latin:clobberSettingsKey="true"
         >
             <key-style
                 latin:styleName="settingsMoreKeysStyle"
-                latin:backgroundType="functional"
-                latin:parentStyle="baseSettingsMoreKeysStyle" />
+                latin:backgroundType="functional" />
         </case>
         <!-- clobberSettingsKey="false" -->
         <default>
@@ -38,8 +36,7 @@
                 latin:styleName="settingsMoreKeysStyle"
                 latin:keyLabelFlags="hasPopupHint"
                 latin:additionalMoreKeys="!text/keyspec_settings"
-                latin:backgroundType="functional"
-                latin:parentStyle="baseSettingsMoreKeysStyle" />
+                latin:backgroundType="functional" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml/keyboard_layout_set_bengali_akkhor.xml b/java/res/xml/keyboard_layout_set_bengali_akkhor.xml
new file mode 100644
index 0000000..267064d
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_bengali_akkhor.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+
+<KeyboardLayoutSet xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <Feature latin:supportedScript="bengali" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabet"
+        latin:enableProximityCharsCorrection="true" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetAutomaticShifted"
+        latin:enableProximityCharsCorrection="true" />
+    <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
+         because the letters on these layouts aren't the ones in different case of the above
+         unshifted layouts.-->
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetManualShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetShiftLocked" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_bengali_akkhor"
+        latin:elementName="alphabetShiftLockShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols"
+        latin:elementName="symbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols_shift"
+        latin:elementName="symbolsShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone"
+        latin:elementName="phone" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone_symbols"
+        latin:elementName="phoneSymbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_number"
+        latin:elementName="number" />
+</KeyboardLayoutSet>
diff --git a/java/res/xml/keyboard_layout_set_myanmar.xml b/java/res/xml/keyboard_layout_set_myanmar.xml
deleted file mode 100644
index 5af8c06..0000000
--- a/java/res/xml/keyboard_layout_set_myanmar.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, 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.
-*/
--->
-
-<KeyboardLayoutSet
-    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <Feature
-        latin:supportedScript="myanmar" />
-    <Element
-        latin:elementName="alphabet"
-        latin:elementKeyboard="@xml/kbd_myanmar"
-        latin:enableProximityCharsCorrection="true" />
-    <Element
-        latin:elementName="alphabetAutomaticShifted"
-        latin:elementKeyboard="@xml/kbd_myanmar"
-        latin:enableProximityCharsCorrection="true" />
-    <!-- On these shifted alphabet layouts the proximity characters correction should be disabled
-         because the letters on these layouts aren't the ones in different case of the above
-         unshifted layouts. -->
-    <Element
-        latin:elementName="alphabetManualShifted"
-        latin:elementKeyboard="@xml/kbd_myanmar" />
-    <Element
-        latin:elementName="alphabetShiftLocked"
-        latin:elementKeyboard="@xml/kbd_myanmar" />
-    <Element
-        latin:elementName="alphabetShiftLockShifted"
-        latin:elementKeyboard="@xml/kbd_myanmar" />
-    <Element
-        latin:elementName="symbols"
-        latin:elementKeyboard="@xml/kbd_symbols" />
-    <Element
-        latin:elementName="symbolsShifted"
-        latin:elementKeyboard="@xml/kbd_symbols_shift" />
-    <Element
-        latin:elementName="phone"
-        latin:elementKeyboard="@xml/kbd_phone" />
-    <Element
-        latin:elementName="phoneSymbols"
-        latin:elementKeyboard="@xml/kbd_phone_symbols" />
-    <Element
-        latin:elementName="number"
-        latin:elementKeyboard="@xml/kbd_number" />
-</KeyboardLayoutSet>
diff --git a/java/res/xml/keyboard_layout_set_nordic.xml b/java/res/xml/keyboard_layout_set_nordic.xml
index 1f00f44..eb3d45b 100644
--- a/java/res/xml/keyboard_layout_set_nordic.xml
+++ b/java/res/xml/keyboard_layout_set_nordic.xml
@@ -23,7 +23,8 @@
     <Element
         latin:elementName="alphabet"
         latin:elementKeyboard="@xml/kbd_nordic"
-        latin:enableProximityCharsCorrection="true" />
+        latin:enableProximityCharsCorrection="true"
+        latin:allowRedundantMoreKeys="false" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/keyboard_layout_set_qwerty.xml b/java/res/xml/keyboard_layout_set_qwerty.xml
index 8215170..7c9a140 100644
--- a/java/res/xml/keyboard_layout_set_qwerty.xml
+++ b/java/res/xml/keyboard_layout_set_qwerty.xml
@@ -23,7 +23,8 @@
     <Element
         latin:elementName="alphabet"
         latin:elementKeyboard="@xml/kbd_qwerty"
-        latin:enableProximityCharsCorrection="true" />
+        latin:enableProximityCharsCorrection="true"
+        latin:supportsSplitLayout="true" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/keyboard_layout_set_serbian_qwertz.xml b/java/res/xml/keyboard_layout_set_serbian_qwertz.xml
new file mode 100644
index 0000000..2c7e28b
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_serbian_qwertz.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+
+<KeyboardLayoutSet xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <Element
+        latin:allowRedundantMoreKeys="false"
+        latin:elementKeyboard="@xml/kbd_serbian_qwertz"
+        latin:elementName="alphabet"
+        latin:enableProximityCharsCorrection="true" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols"
+        latin:elementName="symbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols_shift"
+        latin:elementName="symbolsShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone"
+        latin:elementName="phone" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone_symbols"
+        latin:elementName="phoneSymbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_number"
+        latin:elementName="number" />
+</KeyboardLayoutSet>
\ No newline at end of file
diff --git a/java/res/xml/keyboard_layout_set_swiss.xml b/java/res/xml/keyboard_layout_set_swiss.xml
index e17a5ab..f925b83 100644
--- a/java/res/xml/keyboard_layout_set_swiss.xml
+++ b/java/res/xml/keyboard_layout_set_swiss.xml
@@ -23,7 +23,8 @@
     <Element
         latin:elementName="alphabet"
         latin:elementKeyboard="@xml/kbd_swiss"
-        latin:enableProximityCharsCorrection="true" />
+        latin:enableProximityCharsCorrection="true"
+        latin:allowRedundantMoreKeys="true" />
     <Element
         latin:elementName="symbols"
         latin:elementKeyboard="@xml/kbd_symbols" />
diff --git a/java/res/xml/keyboard_layout_set_uzbek.xml b/java/res/xml/keyboard_layout_set_uzbek.xml
new file mode 100644
index 0000000..8251b01
--- /dev/null
+++ b/java/res/xml/keyboard_layout_set_uzbek.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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.
+*/
+-->
+
+<KeyboardLayoutSet xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <Element
+        latin:elementName="alphabet"
+        latin:elementKeyboard="@xml/kbd_uzbek"
+        latin:enableProximityCharsCorrection="true"
+        latin:allowRedundantMoreKeys="true" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols"
+        latin:elementName="symbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_symbols_shift"
+        latin:elementName="symbolsShifted" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone"
+        latin:elementName="phone" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_phone_symbols"
+        latin:elementName="phoneSymbols" />
+    <Element
+        latin:elementKeyboard="@xml/kbd_number"
+        latin:elementName="number" />
+</KeyboardLayoutSet>
\ No newline at end of file
diff --git a/java/res/xml/keystyle_devanagari_sign_virama.xml b/java/res/xml/keystyle_devanagari_sign_virama.xml
index ff778d9..7863ca4 100644
--- a/java/res/xml/keystyle_devanagari_sign_virama.xml
+++ b/java/res/xml/keystyle_devanagari_sign_virama.xml
@@ -35,7 +35,7 @@
                  U+090D: "ऍ" DEVANAGARI LETTER CANDRA E -->
             <key-style
                 latin:styleName="moreKeysDevanagariSignVirama"
-                latin:moreKeys="&#x25CC;&#x0945;,&#x090D;" />
+                latin:moreKeys="&#x25CC;&#x0945;|&#x0945;,&#x090D;" />
         </case>
         <case latin:keyboardLayoutSet="marathi">
             <!-- U+0905: "अ" DEVANAGARI LETTER A -->
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 4f8efa8..0b0c93e 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -28,6 +28,7 @@
     be_BY: Belarusian (Belarus)/east_slavic
     bg: Bulgarian/bulgarian
     bg: Bulgarian/bulgarian_bds
+    bn_BD: Bengali (Bangladesh)/bengali_akkhor
     bn_IN: Bengali (India)/bengali
     ca: Catalan/spanish
     cs: Czech/qwertz
@@ -52,6 +53,7 @@
     gl_ES: Galician (Spain)/spanish
     hi: Hindi/hindi
     hi: Hindi/hindi_compact
+    hi_ZZ: Hinglish/qwerty  # This is a preliminary keyboard layout.
     hr: Croatian/qwertz
     hu: Hungarian/qwertz
     hy_AM: Armenian (Armenia) Phonetic/armenian_phonetic
@@ -73,7 +75,6 @@
     mn_MN: Mongolian (Mongolia)/mongolian
     mr_IN: Marathi (India)/marathi
     ms_MY: Malay (Malaysia)/qwerty
-    (my_MM: Myanmar (Myanmar)/myanmar) # This is a preliminary keyboard layout.
     nb: Norwegian Bokmål/nordic
     ne_NP: Nepali (Nepal) Romanized/nepali_romanized
     ne_NP: Nepali (Nepal) Traditional/nepali_traditional
@@ -84,21 +85,22 @@
     pt_PT: Portuguese (Portugal)/qwerty
     ro: Romanian/qwerty
     ru: Russian/east_slavic
-    (si_LK: Sinhala (Sri Lanka)/sinhala) # This is a preliminary keyboard layout.
+    si_LK: Sinhala (Sri Lanka)/sinhala # This is a preliminary keyboard layout.
     sk: Slovak/qwerty
     sl: Slovenian/qwerty
     sr: Serbian/south_slavic
-    (sr-Latn: Serbian/qwerty) # not yet implemented.
+    sr_ZZ: Serbian (Latin)/serbian_qwertz # This is a preliminary keyboard layout.
     sv: Swedish/nordic
     sw: Swahili/qwerty
     ta_IN: Tamil (India)/tamil
-    (ta_LK: Tamil (Sri Lanka)/tamil) # Disabled in conjunction with si_LK.
+    ta_LK: Tamil (Sri Lanka)/tamil # Disabled in conjunction with si_LK.
     ta_SG: Tamil (Singapore)/tamil
     te_IN: Telugu (India)/telugu
     th: Thai/thai
     tl: Tagalog/spanish
     tr: Turkish/qwerty
     uk: Ukrainian/east_slavic
+    uz_UZ: Uzbek (Uzbekistan)/uzbek # This is a preliminary keyboard layout.
     vi: Vietnamese/qwerty
     zu: Zulu/qwerty
     zz: QWERTY/qwerty
@@ -180,6 +182,14 @@
     />
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
+            android:subtypeId="0xa2144b0c"
+            android:imeSubtypeLocale="bn_BD"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=bengali_akkhor,EmojiCapable"
+            android:isAsciiCapable="false"
+    />
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_generic"
             android:subtypeId="0xbff5986c"
             android:imeSubtypeLocale="bn_IN"
             android:imeSubtypeMode="keyboard"
@@ -354,6 +364,18 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi_compact,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Hinglish keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
+    <!--  Disabled because there is no LM yet, and this layout does not offer anything different.
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_hi_ZZ"
+            android:subtypeId="0x352eb37c"
+            android:imeSubtypeLocale="hi_ZZ"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="AsciiCapable,KeyboardLayoutSet=qwerty,EmojiCapable"
+            android:isAsciiCapable="true"
+    />
+    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x35b7526a"
@@ -524,18 +546,6 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable"
             android:isAsciiCapable="true"
     />
-    <!-- TODO: This Myanmar keyboard is a preliminary layout.
-               This isn't based on the final specification. -->
-    <!--
-    <subtype android:icon="@drawable/ic_ime_switcher_dark"
-            android:label="@string/subtype_generic"
-            android:subtypeId="0xea266ea4"
-            android:imeSubtypeLocale="my_MM"
-            android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=myanmar,EmojiCapable,CombiningRules=MyanmarReordering"
-            android:isAsciiCapable="false"
-    />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x3f12ee14"
@@ -618,7 +628,7 @@
     />
     <!-- TODO: This Sinhala keyboard is a preliminary layout.
                This isn't based on the final specification. -->
-    <!--
+    <!-- si_LK is currently disabled due to lack of combination rules.
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x5c6b3bde"
@@ -652,24 +662,16 @@
             android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    <!-- TODO: Uncomment once we can handle IETF language tag with script name specified.
+    <!-- TODO: This Serbian Latin keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
-            android:label="@string/subtype_serbian_cyrillic"
-            android:subtypeId="0xXXXXXXXX"
-            android:imeSubtypeLocale="sr"
+            android:label="@string/subtype_sr_ZZ"
+            android:subtypeId="0xf4a5569c"
+            android:imeSubtypeLocale="sr_ZZ"
             android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="SupportTouchPositionCorrection,EmojiCapable"
-            android:isAsciiCapable="false"
-    />
-    <subtype android:icon="@drawable/ic_ime_switcher_dark"
-            android:label="@string/subtype_serbian_latin"
-            android:subtypeId="0xXXXXXXXX"
-            android:imeSubtypeLocale="sr-Latn"
-            android:imeSubtypeMode="keyboard"
-            android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EmojiCapable"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=serbian_qwertz,AsciiCapable,EmojiCapable"
             android:isAsciiCapable="true"
     />
-    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x48b4ff43"
@@ -694,8 +696,8 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=tamil,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    <!-- TODO: Enable ta_LK subtype when si_LK subtype is ready -->
-    <!--
+    <!-- TODO: Enabling/Disabling ta_LK subtype must be aligned with si_LK subtype. -->
+    <!-- ta_LK disabled alongside si_LK subtype due to lack of combination rules.
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x6ca12d84"
@@ -704,7 +706,7 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=tamil,EmojiCapable"
             android:isAsciiCapable="false"
     />
-    -->
+    !-->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x785abbd9"
@@ -753,6 +755,16 @@
             android:imeSubtypeExtraValue="KeyboardLayoutSet=east_slavic,EmojiCapable"
             android:isAsciiCapable="false"
     />
+    <!-- TODO: This Uzbek keyboard is a preliminary layout.
+               This isn't based on the final specification. -->
+    <subtype android:icon="@drawable/ic_ime_switcher_dark"
+            android:label="@string/subtype_generic"
+            android:subtypeId="0xad5cf7f6"
+            android:imeSubtypeLocale="uz_UZ"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=uzbek,AsciiCapable,EmojiCapable"
+            android:isAsciiCapable="true"
+    />
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x93972eee"
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index c14cd64..f01909f 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -23,14 +23,14 @@
         android:title="@string/settings_screen_preferences"
         android:key="screen_preferences" />
     <PreferenceScreen
+        android:fragment="com.android.inputmethod.latin.settings.AccountsSettingsFragment"
+        android:title="@string/settings_screen_accounts"
+        android:key="screen_accounts" />
+    <PreferenceScreen
         android:fragment="com.android.inputmethod.latin.settings.AppearanceSettingsFragment"
         android:title="@string/settings_screen_appearance"
         android:key="screen_appearance" />
     <PreferenceScreen
-        android:fragment="com.android.inputmethod.latin.settings.MultiLingualSettingsFragment"
-        android:title="@string/settings_screen_multilingual"
-        android:key="screen_multilingual" />
-    <PreferenceScreen
         android:fragment="com.android.inputmethod.latin.settings.GestureSettingsFragment"
         android:title="@string/settings_screen_gesture"
         android:key="screen_gesture" />
diff --git a/java/res/xml/prefs_screen_accounts.xml b/java/res/xml/prefs_screen_accounts.xml
new file mode 100644
index 0000000..f2ade91
--- /dev/null
+++ b/java/res/xml/prefs_screen_accounts.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+    android:title="@string/settings_screen_accounts">
+
+    <!-- This preference is a dummy view of the underlying preference.
+         This isn't persisted and the summary/title is refreshed by the fragment
+         after inspecting the underlying account preference. -->
+    <Preference
+        android:key="account_switcher"
+        android:persistent="false"
+        android:title="@string/switch_accounts"
+        android:summary="@string/no_accounts_selected" />
+
+    <!-- Summary will be set programmatically to reflect the account status -->
+    <CheckBoxPreference
+        android:key="pref_enable_cloud_sync"
+        android:title="@string/cloud_sync_title"
+        android:defaultValue="false"
+        android:persistent="true"
+        android:disableDependentsState="false" />
+
+    <!-- This preference (acts like a button) enables the user to initiate an one time sync. -->
+    <Preference android:key="pref_sync_now"
+        android:persistent="false"
+        android:title="@string/sync_now_title"
+        android:dependency="pref_enable_cloud_sync" />
+
+    <!-- This preference (acts like a button) enables the user to clear data from the cloud. -->
+    <Preference android:key="pref_clear_sync_data"
+        android:persistent="false"
+        android:title="@string/clear_sync_data_title"
+        android:summary="@string/clear_sync_data_summary"
+        android:dependency="pref_enable_cloud_sync" />
+
+    <!-- Title will be set programmatically to embed application name -->
+    <CheckBoxPreference
+        android:key="pref_enable_metrics_logging"
+        android:summary="@string/enable_metrics_logging_summary"
+        android:defaultValue="true"
+        android:persistent="true" />
+</PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_advanced.xml b/java/res/xml/prefs_screen_advanced.xml
index 5aefcc8..6038f99 100644
--- a/java/res/xml/prefs_screen_advanced.xml
+++ b/java/res/xml/prefs_screen_advanced.xml
@@ -31,16 +31,16 @@
         android:key="pref_keypress_sound_volume"
         android:title="@string/prefs_keypress_sound_volume_settings"
         latin:maxValue="100" /> <!-- percent -->
-    <!-- The settings for showing setup wizard application icon shouldn't be persistent and
-         the default value is added programmatically. -->
+    <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+        android:key="pref_key_longpress_timeout"
+        android:title="@string/prefs_key_longpress_timeout_settings"
+        latin:minValue="@integer/config_min_longpress_timeout"
+        latin:maxValue="@integer/config_max_longpress_timeout"
+        latin:stepValue="@integer/config_longpress_timeout_step" />
     <CheckBoxPreference
-        android:key="pref_show_setup_wizard_icon"
-        android:title="@string/show_setup_wizard_icon"
-        android:summary="@string/show_setup_wizard_icon_summary" />
-    <!-- title will be set programmatically to embed application name -->
-    <CheckBoxPreference
-        android:key="pref_enable_metrics_logging"
-        android:summary="@string/enable_metrics_logging_summary"
+        android:key="pref_enable_emoji_alt_physical_key"
+        android:title="@string/prefs_enable_emoji_alt_physical_key"
+        android:summary="@string/prefs_enable_emoji_alt_physical_key_summary"
         android:defaultValue="true"
         android:persistent="true" />
     <PreferenceScreen
diff --git a/java/res/xml/prefs_screen_appearance.xml b/java/res/xml/prefs_screen_appearance.xml
index 7719c05..036b665 100644
--- a/java/res/xml/prefs_screen_appearance.xml
+++ b/java/res/xml/prefs_screen_appearance.xml
@@ -26,4 +26,9 @@
         android:fragment="com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment"
         android:key="custom_input_styles"
         android:title="@string/custom_input_styles_title" />
+    <CheckBoxPreference
+        android:key="pref_split_keyboard"
+        android:title="@string/enable_split_keyboard"
+        android:persistent="true"
+        android:defaultValue="false" />
 </PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_correction.xml b/java/res/xml/prefs_screen_correction.xml
index dd5ba54..a943dc1 100644
--- a/java/res/xml/prefs_screen_correction.xml
+++ b/java/res/xml/prefs_screen_correction.xml
@@ -41,13 +41,11 @@
         android:summary="@string/prefs_block_potentially_offensive_summary"
         android:defaultValue="@bool/config_block_potentially_offensive"
         android:persistent="true" />
-    <ListPreference
-        android:key="auto_correction_threshold"
+    <CheckBoxPreference
+        android:key="pref_key_auto_correction"
         android:title="@string/auto_correction"
         android:summary="@string/auto_correction_summary"
-        android:entryValues="@array/auto_correction_threshold_mode_indexes"
-        android:entries="@array/auto_correction_threshold_modes"
-        android:defaultValue="@string/auto_correction_threshold_mode_index_modest"
+        android:defaultValue="true"
         android:persistent="true" />
     <CheckBoxPreference
         android:key="show_suggestions"
diff --git a/java/res/xml/prefs_screen_debug.xml b/java/res/xml/prefs_screen_debug.xml
index c477402..1ae2d0e 100644
--- a/java/res/xml/prefs_screen_debug.xml
+++ b/java/res/xml/prefs_screen_debug.xml
@@ -31,13 +31,8 @@
         android:defaultValue="false"
         android:persistent="true" />
     <CheckBoxPreference
-        android:key="force_physical_keyboard_special_key"
-        android:title="@string/prefs_force_physical_keyboard_special_key"
-        android:defaultValue="false"
-        android:persistent="true" />
-    <CheckBoxPreference
-        android:key="pref_show_ui_to_accept_typed_word"
-        android:title="@string/prefs_show_ui_to_accept_typed_word"
+        android:key="pref_should_show_lxx_suggestion_ui"
+        android:title="@string/prefs_should_show_lxx_suggestion_ui"
         android:defaultValue="true"
         android:persistent="true" />
     <CheckBoxPreference
@@ -46,12 +41,6 @@
         android:summary="@string/sliding_key_input_preview_summary"
         android:defaultValue="true"
         android:persistent="true" />
-    <com.android.inputmethod.latin.settings.SeekBarDialogPreference
-        android:key="pref_key_longpress_timeout"
-        android:title="@string/prefs_key_longpress_timeout_settings"
-        latin:minValue="@integer/config_min_longpress_timeout"
-        latin:maxValue="@integer/config_max_longpress_timeout"
-        latin:stepValue="@integer/config_longpress_timeout_step" />
     <CheckBoxPreference
         android:key="pref_has_custom_key_preview_animation_params"
         android:title="@string/prefs_customize_key_preview_animation"
@@ -87,9 +76,17 @@
         android:key="pref_key_preview_dismiss_duration"
         android:title="@string/prefs_key_popup_dismiss_duration_settings"
         latin:maxValue="100" /> <!-- milliseconds -->
-    <PreferenceScreen
-        android:key="read_external_dictionary"
-        android:title="@string/prefs_read_external_dictionary" />
+    <CheckBoxPreference
+        android:key="pref_resize_keyboard"
+        android:title="@string/prefs_resize_keyboard"
+        android:defaultValue="false"
+        android:persistent="true" />
+    <com.android.inputmethod.latin.settings.SeekBarDialogPreference
+        android:dependency="pref_resize_keyboard"
+        android:key="pref_keyboard_height_scale"
+        android:title="@string/prefs_keyboard_height_scale"
+        latin:minValue="50"
+        latin:maxValue="120" /> <!-- percentage -->
     <PreferenceCategory
         android:key="pref_key_dump_dictionaries"
         android:title="@string/prefs_dump_dynamic_dicts">
diff --git a/java/res/xml/prefs_screen_gesture.xml b/java/res/xml/prefs_screen_gesture.xml
index c87316d..38c7eda 100644
--- a/java/res/xml/prefs_screen_gesture.xml
+++ b/java/res/xml/prefs_screen_gesture.xml
@@ -37,11 +37,4 @@
         android:title="@string/gesture_preview_trail"
         android:defaultValue="true"
         android:persistent="true" />
-    <CheckBoxPreference
-        android:key="pref_gesture_space_aware"
-        android:dependency="gesture_input"
-        android:title="@string/gesture_space_aware"
-        android:summary="@string/gesture_space_aware_summary"
-        android:defaultValue="true"
-        android:persistent="true" />
 </PreferenceScreen>
diff --git a/java/res/xml/prefs_screen_multilingual.xml b/java/res/xml/prefs_screen_multilingual.xml
deleted file mode 100644
index 07a4b70..0000000
--- a/java/res/xml/prefs_screen_multilingual.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/settings_screen_multilingual"
-    android:key="screen_multilingual">
-    <CheckBoxPreference
-        android:key="pref_show_language_switch_key"
-        android:title="@string/show_language_switch_key"
-        android:summary="@string/show_language_switch_key_summary"
-        android:defaultValue="true"
-        android:persistent="true" />
-    <CheckBoxPreference
-        android:key="pref_include_other_imes_in_language_switch_list"
-        android:dependency="pref_show_language_switch_key"
-        android:title="@string/include_other_imes_in_language_switch_list"
-        android:summary="@string/include_other_imes_in_language_switch_list_summary"
-        android:defaultValue="false"
-        android:persistent="true" />
-</PreferenceScreen>
diff --git a/java/res/xml/rowkeys_bengali_akkhor1.xml b/java/res/xml/rowkeys_bengali_akkhor1.xml
new file mode 100644
index 0000000..bc612be
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor1.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+09A2: "ঢ" BENGALI LETTER DDHA -->
+            <Key latin:keySpec="&#x09A2;" />
+            <!-- U+09A0: "ঠ" BENGALI LETTER TTHA -->
+            <Key latin:keySpec="&#x09A0;" />
+            <!-- U+09C8: "ৈ" BENGALI VOWEL SIGN AI
+                 U+0990: "ঐ" BENGALI LETTER AI -->
+            <Key
+                latin:keySpec="&#x09C8;"
+                latin:moreKeys="&#x0990;" />
+            <!-- U+09DC: "ড়" BENGALI LETTER RRA
+                 U+09BC: "়" BENGALI SIGN NUKTA -->
+            <Key
+                latin:keySpec="&#x09DC;"
+                latin:moreKeys="&#x09BC;" />
+            <!-- U+099F: "ট" BENGALI LETTER TTA
+                 U+09F3: "৳" BENGALI RUPEE SIGN
+                 U+099F/U+09CD/U+099F: "ট্ট" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+099F/U+09CD/U+09AC: "ট্ব" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+099F/U+09CD/U+09AE: "ট্ম" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                latin:keySpec="&#x099F;"
+                latin:moreKeys="&#x09F3;,&#x099F;&#x09CD;&#x099F;,&#x099F;&#x09CD;&#x09AC;,&#x099F;&#x09CD;&#x09AE;" />
+            <!-- U+099E: "ঞ" BENGALI LETTER NYA
+                 U+099E/U+09CD/U+099A: "ঞ্চ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+099E/U+09CD/U+099B: "ঞ্ছ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                 U+099E/U+09CD/U+099C: "ঞ্জ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER JA -->
+            <Key
+                latin:keySpec="&#x099E;"
+                latin:moreKeys="&#x099E;&#x09CD;&#x099A;,&#x099E;&#x09CD;&#x099B;,&#x099E;&#x09CD;&#x099C;" />
+            <!-- U+09C2: "ূ" BENGALI VOWEL SIGN UU
+                 U+098A: "ঊ" BENGALI LETTER UU -->
+            <Key
+                latin:keySpec="&#x09C2;"
+                latin:moreKeys="&#x098A;" />
+            <!-- U+09C0: "ী" BENGALI VOWEL SIGN II
+                 U+0988: "ঈ" BENGALI LETTER II -->
+            <Key
+                latin:keySpec="&#x09C0;"
+                latin:moreKeys="&#x0988;" />
+            <!-- U+09CC: "ৌ" BENGALI VOWEL SIGN AU
+                 U+099A: "ঔ" BENGALI LETTER CA
+                 U+09D7: "ৗ" BENGALI AU LENGTH MARK -->
+            <Key
+                latin:keySpec="&#x09CC;"
+                latin:moreKeys="&#x099A;,&#x09D7;" />
+            <!-- U+09AB: "ফ" BENGALI LETTER PHA
+                 U+09AB/U+09CD/U+099F: "ফ্ট" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09AB/U+09CD/U+09AF: "ফ্য" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AB/U+09CD/U+09B0: "ফ্র" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AB/U+09CD/U+09B2: "ফ্ল" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09AB;"
+                latin:moreKeys="&#x09AB;&#x09CD;&#x099F;,&#x09AB;&#x09CD;&#x09AF;,&#x09AB;&#x09CD;&#x09B0;,&#x09AB;&#x09CD;&#x09B2;" />
+            <!-- U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                 U+098C: "ঌ" BENGALI LETTER VOCALIC L
+                 U+09E1: "ৡ" BENGALI LETTER VOCALIC LL
+                 U+09F4: "৴" BENGALI CURRENCY NUMERATOR ONE
+                 U+09F5: "৵" BENGALI CURRENCY NUMERATOR TWO
+                 U+09F6: "৶" BENGALI CURRENCY NUMERATOR THREE
+                 U+09E2: " ৢ" BENGALI VOWEL SIGN VOCALIC L
+                 U+09E3: " ৣ" BENGALI VOWEL SIGN VOCALIC LL -->
+            <Key
+                latin:keySpec="&#x098B;"
+                latin:moreKeys="&#x098C;,&#x09E1;,&#x09F4;,&#x09F5;,&#x09F6;,&#x09E2;,&#x09E3;" />
+        </case>
+        <default>
+            <!-- U+09A7: "ধ" BENGALI LETTER DHA
+                 U+09E7: "১" BENGALI DIGIT ONE
+                 U+09A7/U+09CD/U+09AC: "ধ্ব্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A7/U+09CD/U+09AF: "ধ্য্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A7/U+09CD/U+09B0: "ধ্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A7;"
+                latin:keyHintLabel="&#x09E7;"
+                latin:additionalMoreKeys="&#x09E7;"
+                latin:moreKeys="&#x09A7;&#x09CD;&#x09AC;,&#x09A7;&#x09CD;&#x09AF;,&#x09A7;&#x09CD;&#x09B0;" />
+            <!-- U+09A5: "থ" BENGALI LETTER THA
+                 U+09E8: "২" BENGALI DIGIT TWO
+                 U+09A5/U+09CD/U+09AF: "থ্য" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A5/U+09CD/U+09B0: "থ্র" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A5;"
+                latin:keyHintLabel="&#x09E8;"
+                latin:additionalMoreKeys="&#x09E8;"
+                latin:moreKeys="&#x09A5;&#x09CD;&#x09AF;,&#x09A5;&#x09CD;&#x09B0;" />
+            <!-- U+09C7: "ে" BENGALI VOWEL SIGN E
+                 U+09E9: "৩" BENGALI DIGIT THREE
+                 U+098F: "এ" BENGALI LETTER E -->
+            <Key
+                latin:keySpec="&#x09C7;"
+                latin:keyHintLabel="&#x09E9;"
+                latin:additionalMoreKeys="&#x09E9;"
+                latin:moreKeys="&#x098F;" />
+            <!-- U+09B0: "র" BENGALI LETTER RA
+                 U+09EA: "৪" BENGALI DIGIT FOUR -->
+            <Key
+                latin:keySpec="&#x09B0;"
+                latin:keyHintLabel="&#x09EA;"
+                latin:additionalMoreKeys="&#x09EA;" />
+            <!-- U+09A4: "ত" BENGALI LETTER TA
+                 U+09EB: "৫" BENGALI DIGIT FIVE
+                 U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                 U+09A4/U+09CD/U+09A4: "ত্ত" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09A4/U+09CD/U+09A8: "ত্ন" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09A4/U+09CD/U+09AC: "ত্ব" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A4/U+09CD/U+09AE: "ত্ম" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                latin:keySpec="&#x09A4;"
+                latin:keyHintLabel="&#x09EB;"
+                latin:additionalMoreKeys="&#x09EB;"
+                latin:moreKeys="&#x09CE;,&#x09A4;&#x09CD;&#x09A4;,&#x09A4;&#x09CD;&#x09A8;,&#x09A4;&#x09CD;&#x09AC;,&#x09A4;&#x09CD;&#x09AE;" />
+            <!-- U+09DF: "য়" BENGALI LETTER YYA
+                 U+09EC: "৬" BENGALI DIGIT SIX -->
+            <Key
+                latin:keySpec="&#x09DF;"
+                latin:keyHintLabel="&#x09EC;"
+                latin:additionalMoreKeys="&#x09EC;" />
+            <!-- U+09C1: "ু" BENGALI VOWEL SIGN U
+                 U+09ED: "৭" BENGALI DIGIT SEVEN
+                 U+0989: "উ" BENGALI LETTER U -->
+            <Key
+                latin:keySpec="&#x09C1;"
+                latin:keyHintLabel="&#x09ED;"
+                latin:additionalMoreKeys="&#x09ED;"
+                latin:moreKeys="&#x0989;" />
+            <!-- U+09BF: "ি" BENGALI VOWEL SIGN I
+                 U+09EE: "৮" BENGALI DIGIT EIGHT
+                 U+0987: "ই BENGALI LETTER I -->
+            <Key
+                latin:keySpec="&#x09BF;"
+                latin:keyHintLabel="&#x09EE;"
+                latin:additionalMoreKeys="&#x09EE;"
+                latin:moreKeys="&#x0987;" />
+            <!-- U+09CB: "ো" BENGALI VOWEL SIGN O
+                 U+09EF: "৯" BENGALI DIGIT NINE
+                 U+0993: "ও" BENGALI LETTER O -->
+            <Key
+                latin:keySpec="&#x09CB;"
+                latin:keyHintLabel="&#x09EF;"
+                latin:additionalMoreKeys="&#x09EF;"
+                latin:moreKeys="&#x0993;" />
+            <!-- U+09AA: "প" BENGALI LETTER PA
+                 U+09E6: "০" BENGALI DIGIT ZERO
+                 U+09AA/U+09CD/U+09A4: "প্ত" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09AA/U+09CD/U+09A8: "প্ন" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09AA/U+09CD/U+09AA: "প্প" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09AA/U+09CD/U+09AF: "প্য" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AA/U+09CD/U+09B0: "প্র" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AA/U+09CD/U+09B2: "প্ল" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+09AA/U+09CD/U+09B8: "প্স" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER SA -->
+            <Key
+                latin:keySpec="&#x09AA;"
+                latin:keyHintLabel="&#x09E6;"
+                latin:additionalMoreKeys="&#x09E6;"
+                latin:moreKeys="&#x09AA;&#x09CD;&#x09A4;,&#x09AA;&#x09CD;&#x09A8;,&#x09AA;&#x09CD;&#x09AA;,&#x09AA;&#x09CD;&#x09AF;,&#x09AA;&#x09CD;&#x09B0;,&#x09AA;&#x09CD;&#x09B2;,&#x09AA;&#x09CD;&#x09B8;" />
+            <!-- U+0986: "আ" BENGALI LETTER AA -->
+            <Key latin:keySpec="&#x0986;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_bengali_akkhor2.xml b/java/res/xml/rowkeys_bengali_akkhor2.xml
new file mode 100644
index 0000000..1dbab55
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor2.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+0985: "অ" BENGALI LETTER A -->
+            <Key latin:keySpec="&#x0985;" />
+            <!-- U+09B6: "শ" BENGALI LETTER SHA
+                 U+09B6/U+09CD/U+099A: "শ্চ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+09B6/U+09CD/U+099B: "শ্ছ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                 U+09B6/U+09CD/U+09A4: "শ্ত" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B6/U+09CD/U+09A8: "শ্ন" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09B6/U+09CD/U+09AC: "শ্ব" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B6/U+09CD/U+09AE: "শ্ম" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B6/U+09CD/U+09B0: "শ্র" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09B6/U+09CD/U+09B2: "শ্ল" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B6;"
+                latin:moreKeys="&#x09B6;&#x09CD;&#x099A;,&#x09B6;&#x09CD;&#x099B;,&#x09B6;&#x09CD;&#x09A4;,&#x09B6;&#x09CD;&#x09A8;,&#x09B6;&#x09CD;&#x09AC;,&#x09B6;&#x09CD;&#x09AE;,&#x09B6;&#x09CD;&#x09B0;,&#x09B6;&#x09CD;&#x09B2;" />
+            <!-- U+09A1: "ড" BENGALI LETTER DDA
+                 U+09A1/U+09CD/U+09A1: "ড্ড" BENGALI LETTER DDA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA-->
+            <Key
+                latin:keySpec="&#x09A1;"
+                latin:moreKeys="&#x09A1;&#x09CD;&#x09A1;" />
+            <!-- U+09DD: "ঢ়" BENGALI LETTER RHA -->
+            <Key latin:keySpec="&#x09DD;" />
+            <!-- U+0998: "ঘ" BENGALI LETTER GHA -->
+            <Key latin:keySpec="&#x0998;" />
+            <!-- U+09B9: "হ" BENGALI LETTER HA
+                 U+09BD: "ঽ" BENGALI SIGN AVAGRAHA
+                 U+09B9/U+09CD/U+09A3: "হ্ণ" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                 U+09B9/U+09CD/U+09A8: "হ্ন" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09B9/U+09CD/U+09AC: "হ্ব" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B9/U+09CD/U+09AE: "হ্ম" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B9/U+09CD/U+09B0: "হ্র" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09B9/U+09CD/U+09B2: "হ্ল" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B9;"
+                latin:moreKeys="&#x09BD;,&#x09B9;&#x09CD;&#x09A3;,&#x09B9;&#x09CD;&#x09A8;,&#x09B9;&#x09CD;&#x09AC;,&#x09B9;&#x09CD;&#x09AE;,&#x09B9;&#x09CD;&#x09B0;,&#x09B9;&#x09CD;&#x09B2;" />
+            <!-- U+099D: "ঝ" BENGALI LETTER JHA -->
+            <Key latin:keySpec="&#x099D;" />
+            <!-- U+0996: "খ" BENGALI LETTER KHA -->
+            <Key latin:keySpec="&#x0996;" />
+            <!-- U+09CE: "ৎ" BENGALI LETTER KHANDA TA -->
+            <Key latin:keySpec="&#x09CE;" />
+            <!-- U+0988: "ঈ" BENGALI LETTER II -->
+            <Key latin:keySpec="&#x0988;" />
+            <!-- U+098A: "ঊ" BENGALI LETTER UU -->
+            <Key latin:keySpec="&#x098A;" />
+        </case>
+        <default>
+            <!-- U+09BE: "া BENGALI VOWEL SIGN AA
+                 U+0986: "আ" BENGALI LETTER AA -->
+            <Key
+                latin:keySpec="&#x09BE;"
+                latin:moreKeys="&#x0986;" />
+            <!-- U+09B8: "স" BENGALI LETTER SA
+                 U+09B8/U+09CD/U+09AC: "স্ব" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B8/U+09CD/U+09A4: "স্ত" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B8/U+09CD/U+099F: "স্ট" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B8/U+09CD/U+0995: "স্ক" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B8/U+09CD/U+09AA: "স্প" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER PA -->
+            <Key
+                latin:keySpec="&#x09B8;"
+                latin:moreKeys="&#x09B8;&#x09CD;&#x09AC;,&#x09B8;&#x09CD;&#x09A4;,&#x09B8;&#x09CD;&#x099F;,&#x09B8;&#x09CD;&#x0995;,&#x09B8;&#x09CD;&#x09AA;" />
+            <!-- U+09A6: "দ" BENGALI LETTER DA
+                 U+09A6/U+09CD/U+09A6: "দ্দ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09A6/U+09CD/U+09A7: "দ্ধ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09A6/U+09CD/U+09AC: "দ্ব" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A6/U+09CD/U+09AD: "দ্ভ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                 U+09A6/U+09CD/U+09AE: "দ্ম" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09A6/U+09CD/U+09AF: "দ্য" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09A6/U+09CD/U+09B0: "দ্র" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x09A6;"
+                latin:moreKeys="&#x09A6;&#x09CD;&#x09A6;,&#x09A6;&#x09CD;&#x09A7;,&#x09A6;&#x09CD;&#x09AC;,&#x09A6;&#x09CD;&#x09AD;,&#x09A6;&#x09CD;&#x09AE;,&#x09A6;&#x09CD;&#x09AF;,&#x09A6;&#x09CD;&#x09B0;" />
+            <!-- U+09C3: "ৃ" BENGALI VOWEL SIGN VOCALIC R
+                 U+098B: "ঋ" BENGALI LETTER VOCALIC R -->
+            <Key
+                latin:keySpec="&#x09C3;"
+                latin:moreKeys="&#x098B;" />
+            <!-- U+0997: "গ" BENGALI LETTER GA
+                 U+0997/U+09CD/U+09A7: "গ্ধ" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+0997/U+09CD/U+09B0: "গ্র" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+0997/U+09CD/U+09B2: "গ্ল" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+0997/U+09CD/U+09A8: "গ্ন" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER NA -->
+            <Key
+                latin:keySpec="&#x0997;"
+                latin:moreKeys="&#x0997;&#x09CD;&#x09A7;,&#x0997;&#x09CD;&#x09B0;,&#x0997;&#x09CD;&#x09B2;,&#x0997;&#x09CD;&#x09A8;" />
+            <!-- U+09CD: "্" BENGALI SIGN VIRAMA -->
+            <Key latin:keySpec="&#x09CD;" />
+            <!-- U+099C: "জ" BENGALI LETTER JA
+                 U+099C/U+09CD/U+099E: "জ্ঞ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER NYA
+                 U+099C/U+09CD/U+099C: "জ্জ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                 U+099C/U+09CD/U+09AF: "জ্ব" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+099C/U+09CD/U+09AC: "জ্য" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+099C/U+09CD/U+09B0: "জ্র" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER RA -->
+            <Key
+                latin:keySpec="&#x099C;"
+                latin:moreKeys="&#x099C;&#x09CD;&#x099E;,&#x099C;&#x09CD;&#x099C;,&#x099C;&#x09CD;&#x09AF;,&#x099C;&#x09CD;&#x09AC;,&#x099C;&#x09CD;&#x09B0;" />
+            <!-- U+0995: "ক" BENGALI LETTER KA
+                 U+0995/U+09CD/U+09B7: "ক্ষ" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SSA
+                 U+0995/U+09CD/U+0995: "ক্ক" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+0995/U+09CD/U+099F: "ক্ট" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+0995/U+09CD/U+09A4: "ক্ত" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+0995/U+09CD/U+09B0: "ক্র" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+0995/U+09CD/U+09B8: "ক্স" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                 U+0995/U+09CD/U+09B2: "ক্ল" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x0995;"
+                latin:moreKeys="&#x0995;&#x09CD;&#x09B7;,&#x0995;&#x09CD;&#x0995;,&#x0995;&#x09CD;&#x099F;,&#x0995;&#x09CD;&#x09A4;,&#x0995;&#x09CD;&#x09B0;,&#x0995;&#x09CD;&#x09B8;,&#x0995;&#x09CD;&#x09B2;" />
+            <!-- U+09B2: "ল" BENGALI LETTER LA
+                 U+09B2/U+09CD/U+0995: "ল্ক" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B2/U+09CD/U+0997: "ল্গ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER GA
+                 U+09B2/U+09CD/U+099F: "ল্ট" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B2/U+09CD/U+09A1: "ল্ড" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09B2/U+09CD/U+09A4: "ল্ত" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09B2/U+09CD/U+09A6: "ল্দ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09B2/U+09CD/U+09A7: "ল্ধ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09B2/U+09CD/U+09AA: "ল্প" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09B2/U+09CD/U+09AB: "ল্ফ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                 U+09B2/U+09CD/U+09AC: "ল্ব" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09B2/U+09CD/U+09AE: "ল্ম" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09B2/U+09CD/U+09B2: "ল্ল" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                latin:keySpec="&#x09B2;"
+                latin:moreKeys="&#x09B2;&#x09CD;&#x0995;,&#x09B2;&#x09CD;&#x0997;,&#x09B2;&#x09CD;&#x099F;,&#x09B2;&#x09CD;&#x09A1;,&#x09B2;&#x09CD;&#x09A4;,&#x09B2;&#x09CD;&#x09A6;,&#x09B2;&#x09CD;&#x09A7;,&#x09B2;&#x09CD;&#x09AA;,&#x09B2;&#x09CD;&#x09AB;,&#x09B2;&#x09CD;&#x09AC;,&#x09B2;&#x09CD;&#x09AE;,&#x09B2;&#x09CD;&#x09B2;" />
+            <!-- U+0987: "ই" BENGALI LETTER I -->
+            <Key latin:keySpec="&#x0987;" />
+            <!-- U+0989: "উ" BENGALI LETTER U -->
+            <Key latin:keySpec="&#x0989;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_bengali_akkhor3.xml b/java/res/xml/rowkeys_bengali_akkhor3.xml
new file mode 100644
index 0000000..eb9e836
--- /dev/null
+++ b/java/res/xml/rowkeys_bengali_akkhor3.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+0964: "।" DEVANAGARI DANDA
+                 U+0965: "॥" DEVANAGARI DOUBLE DANDA -->
+            <Key
+                 latin:keySpec="&#x0964;"
+                 latin:moreKeys="&#x0965;" />
+            <!-- U+0999: "ঙ BENGALI LETTER NGA
+                 U+0999/U+09CD/U+0995: "ঙ্ক"
+                 U+0999/U+09CD/U+0996: "ঙ্খ"
+                 U+0999/U+09CD/U+0997: "ঙ্গ" -->
+            <Key latin:keySpec="&#x0999;"
+                 latin:moreKeys="&#x0999;&#x09CD;&#x0995;,&#x0999;&#x09CD;&#x0996;,&#x0999;&#x09CD;&#x0997;" />
+            <!-- U+099B: "ছ" BENGALI LETTER CHA -->
+            <Key latin:keySpec="&#x099B;" />
+            <!-- U+0983: "ঃ" BENGALI SIGN VISARGA -->
+            <Key latin:keySpec="&#x0983;" />
+            <!-- U+0981: "ঁ" BENGALI SIGN CANDRABINDU -->
+            <Key latin:keySpec="&#x0981;" />
+            <!-- U+09A3: "ণ" BENGALI LETTER NNA
+                 U+09A3/U+09CD/U+099F: "ণ্ট" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09A3/U+09CD/U+09A1: "ণ্ড" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09A3/U+09CD/U+09A3: "ণ্ণ" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA -->
+            <Key latin:keySpec="&#x09A3;"
+                 latin:moreKeys="&#x09A3;&#x09CD;&#x099F;,&#x09A3;&#x09CD;&#x09A1;,&#x09A3;&#x09CD;&#x09A3;" />
+            <!-- U+0982: "ং" BENGALI SIGN ANUSVARA -->
+            <Key latin:keySpec="&#x0982;" />
+            <!-- U+0990: "ঐ" BENGALI LETTER AI -->
+            <Key latin:keySpec="&#x0990;" />
+            <!-- U+0994: "ঔ" BENGALI LETTER AU -->
+            <Key latin:keySpec="&#x0994;" />
+        </case>
+        <default>
+            <!-- U+09AF: "য" BENGALI LETTER YA
+                 U+09CD/U+09AF: "্য" BENGALI SIGN VIRAMA/BENGALI LETTER YA -->
+            <Key
+                 latin:keySpec="&#x09AF;"
+                 latin:moreKeys="&#x09CD;&#x09AF;" />
+            <!-- U+09B7: "ষ" BENGALI LETTER SSA
+                 U+09B7/U+09CD/U+0995: "ষ্ক" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                 U+09B7/U+09CD/U+099F: "ষ্ট" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09B7/U+09CD/U+09A0: "ষ্ঠ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTHA
+                 U+09B7/U+09CD/U+09A3: "ষ্ণ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                 U+09B7/U+09CD/U+09AA: "ষ্প" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09B7/U+09CD/U+09AB: "ষ্ফ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                 U+09B7/U+09CD/U+09AE: "ষ্ম" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER MA -->
+            <Key
+                 latin:keySpec="&#x09B7;"
+                 latin:moreKeys="&#x09B7;&#x09CD;&#x0995;,&#x09B7;&#x09CD;&#x099F;,&#x09B7;&#x09CD;&#x09A0;,&#x09B7;&#x09CD;&#x09A3;,&#x09B7;&#x09CD;&#x09AA;,&#x09B7;&#x09CD;&#x09AB;,&#x09B7;&#x09CD;&#x09AE;" />
+            <!-- U+099A: "চ" BENGALI LETTER CA
+                 U+099A/U+09CD/U+099A: "চ্চ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                 U+099A/U+09CD/U+099B: "চ্ছ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA -->
+            <Key
+                 latin:keySpec="&#x099A;"
+                 latin:moreKeys="&#x099A;&#x09CD;&#x099A;,&#x099A;&#x09CD;&#x099B;" />
+            <!-- U+09AD: "ভ" BENGALI LETTER BHA
+                 U+09AD/U+09CD/U+09AF: "ভ্" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                 U+09AD/U+09CD/U+09B0: "ভ্র" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AD/U+09CD/U+09B2: "ভ্ল" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                 latin:keySpec="&#x09AD;"
+                 latin:moreKeys="&#x09AD;&#x09CD;&#x09AF;,&#x09AD;&#x09CD;&#x09B0;,&#x09AD;&#x09CD;&#x09B2;" />
+            <!-- U+09AC: "ব" BENGALI LETTER BA
+                 U+09CD/U+09AC: "্ব" BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AC/U+09CD/U+09B0: "ব্র" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AC/U+09CD/U+099C: "ব্জ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                 U+09AC/U+09CD/U+09A6: "ব্দ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09AC/U+09CD/U+09A7: "ব্ধ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09AC/U+09CD/U+09AC: "ব্ব" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AC/U+09CD/U+09B2: "ব্ল" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                 U+09F1: "ৱ" BENGALI LETTER RA WITH MIDDLE DIAGONAL
+                 U+09F0: "ৰ" BENGALI LETTER RA WITH LOWER DIAGONAL -->
+            <Key
+                 latin:keySpec="&#x09AC;"
+                 latin:moreKeys="&#x09CD;&#x09AC;,&#x09AC;&#x09CD;&#x09B0;,&#x09AC;&#x09CD;&#x099C;,&#x09AC;&#x09CD;&#x09A6;,&#x09AC;&#x09CD;&#x09A7;,&#x09AC;&#x09CD;&#x09AC;,&#x09AC;&#x09CD;&#x09B2;,&#x09F1;,&#x09F0;" />
+            <!-- U+09A8: "ন" BENGALI LETTER NA
+                 U+09A8/U+09CD/U+09A4: "ন্ত" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                 U+09A8/U+09CD/U+09A5: "ন্থ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER THA
+                 U+09A8/U+09CD/U+099F: "ন্ট" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                 U+09A8/U+09CD/U+09A6: "ন্দ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                 U+09A8/U+09CD/U+09A7: "ন্ধ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                 U+09A8/U+09CD/U+09A1: "ন্ড" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                 U+09A8/U+09CD/U+09A8: "ন্ন" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09A8/U+09CD/U+09AC: "ন্ব" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09A8/U+09CD/U+09AE: "ন্ম" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09A8/U+09CD/U+09B8: "ন্স" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER SA -->
+            <Key
+                 latin:keySpec="&#x09A8;"
+                 latin:moreKeys="&#x09A8;&#x09CD;&#x09A4;,&#x09A8;&#x09CD;&#x09A5;,&#x09A8;&#x09CD;&#x099F;,&#x09A8;&#x09CD;&#x09A6;,&#x09A8;&#x09CD;&#x09A7;,&#x09A8;&#x09CD;&#x09A1;,&#x09A8;&#x09CD;&#x09A8;,&#x09A8;&#x09CD;&#x09AC;,&#x09A8;&#x09CD;&#x09AE;,&#x09A8;&#x09CD;&#x09B8;" />
+            <!-- U+09AE: "ম" BENGALI LETTER MA
+                 U+09AE/U+09CD/U+09A8: "ম্ন" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                 U+09AE/U+09CD/U+09AA: "ম্প" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                 U+09AE/U+09CD/U+09AC: "ম্ব" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                 U+09AE/U+09CD/U+09AD: "ম্ভ" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                 U+09AE/U+09CD/U+09AE: "ম্ম" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                 U+09AE/U+09CD/U+09B0: "ম্র" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                 U+09AE/U+09CD/U+09B2: "ম্ল" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER LA -->
+            <Key
+                 latin:keySpec="&#x09AE;"
+                 latin:moreKeys=",&#x09AE;&#x09CD;&#x09A8;,&#x09AE;&#x09CD;&#x09AA;,&#x09AE;&#x09CD;&#x09AC;,&#x09AE;&#x09CD;&#x09AD;,&#x09AE;&#x09CD;&#x09AE;,&#x09AE;&#x09CD;&#x09B0;,&#x09AE;&#x09CD;&#x09B2;" />
+            <!-- U+098F: "এ" BENGALI LETTER E -->
+            <Key latin:keySpec="&#x098F;" />
+            <!-- U+0993: "ও" BENGALI LETTER O -->
+            <Key latin:keySpec="&#x0993;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_myanmar1.xml b/java/res/xml/rowkeys_myanmar1.xml
deleted file mode 100644
index 1170074..0000000
--- a/java/res/xml/rowkeys_myanmar1.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- U+1027: "ဧ" MYANMAR LETTER E -->
-            <Key latin:keySpec="&#x1027;" />
-            <!-- U+104F: "၏" MYANMAR SYMBOL GENITIVE -->
-            <Key latin:keySpec="&#x104F;" />
-            <!-- U+1024: "ဤ" MYANMAR LETTER II -->
-            <Key latin:keySpec="&#x1024;" />
-            <!-- U+1023: "ဣ" MYANMAR LETTER I -->
-            <Key latin:keySpec="&#x1023;" />
-            <!-- U+104E: "၎" MYANMAR SYMBOL AFOREMENTIONED -->
-            <Key latin:keySpec="&#x104E;" />
-            <!-- U+1000/U+103B/U+1015/U+103A: "ကျပ်"
-                 MYANMAR LETTER KA/MYANMAR CONSONANT SIGN MEDIAL YA/MYANMAR LETTER PA/MYANMAR SIGN ASAT -->
-            <Key
-                latin:keySpec="&#x1000;&#x103B;&#x1015;&#x103A;"
-                latin:keyLabelFlags="followKeyLetterRatio|autoScale" />
-            <!-- U+1029: "ဩ" MYANMAR LETTER O -->
-            <Key
-                latin:keySpec="&#x1029;"
-                latin:keyLabelFlags="autoScale" />
-            <!-- U+102A: "ဪ" MYANMAR LETTER AU -->
-            <Key
-                latin:keySpec="&#x102A;"
-                latin:keyLabelFlags="autoScale" />
-            <!-- U+104D: "၍" MYANMAR SYMBOL COMPLETED -->
-            <Key latin:keySpec="&#x104D;" />
-            <!-- U+104C: "၌" MYANMAR SYMBOL LOCATIVE -->
-            <Key latin:keySpec="&#x104C;" />
-        </case>
-        <default>
-            <!-- U+1041: "၁" MYANMAR DIGIT ONE -->
-            <Key
-                latin:keySpec="&#x1041;"
-                latin:keyHintLabel="1"
-                latin:additionalMoreKeys="1" />
-            <!-- U+1042: "၂" MYANMAR DIGIT TWO -->
-            <Key
-                latin:keySpec="&#x1042;"
-                latin:keyHintLabel="2"
-                latin:additionalMoreKeys="2" />
-            <!-- U+1043: "၃" MYANMAR DIGIT THREE -->
-            <Key
-                latin:keySpec="&#x1043;"
-                latin:keyHintLabel="3"
-                latin:additionalMoreKeys="3" />
-            <!-- U+1044: "၄" MYANMAR DIGIT FOUR -->
-            <Key
-                latin:keySpec="&#x1044;"
-                latin:keyHintLabel="4"
-                latin:additionalMoreKeys="4" />
-            <!-- U+1045: "၅" MYANMAR DIGIT FIVE -->
-            <Key
-                latin:keySpec="&#x1045;"
-                latin:keyHintLabel="5"
-                latin:additionalMoreKeys="5" />
-            <!-- U+1046: "၆" MYANMAR DIGIT SIX -->
-            <Key
-                latin:keySpec="&#x1046;"
-                latin:keyHintLabel="6"
-                latin:additionalMoreKeys="6" />
-            <!-- U+1047: "၇" MYANMAR DIGIT SEVEN -->
-            <Key
-                latin:keySpec="&#x1047;"
-                latin:keyHintLabel="7"
-                latin:additionalMoreKeys="7" />
-            <!-- U+1048: "၈" MYANMAR DIGIT EIGHT -->
-            <Key
-                latin:keySpec="&#x1048;"
-                latin:keyHintLabel="8"
-                latin:additionalMoreKeys="8" />
-            <!-- U+1049: "၉" MYANMAR DIGIT NINE -->
-            <Key
-                latin:keySpec="&#x1049;"
-                latin:keyHintLabel="9"
-                latin:additionalMoreKeys="9" />
-            <!-- U+1040: "၀" MYANMAR DIGIT ZERO -->
-            <Key
-                latin:keySpec="&#x1040;"
-                latin:keyHintLabel="0"
-                latin:additionalMoreKeys="0" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_myanmar2.xml b/java/res/xml/rowkeys_myanmar2.xml
deleted file mode 100644
index ae71ecb..0000000
--- a/java/res/xml/rowkeys_myanmar2.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- U+1017: "ဗ" MYANMAR LETTER BA
-                 U+1039/U+1017: "္ဗ" MYANMAR SIGN VIRAMA/MYANMAR LETTER BA -->
-            <Key
-                latin:keySpec="&#x1017;"
-                latin:moreKeys="&#x1039;&#x1017;" />
-            <!-- U+1012: "ဒ" MYANMAR LETTER DA
-                 U+1039/U+1012: "္ဒ" MYANMAR SIGN VIRAMA/MYANMAR LETTER DA -->
-            <Key
-                latin:keySpec="&#x1012;"
-                latin:moreKeys="&#x1039;&#x1012;" />
-            <!-- U+1013: "ဓ" MYANMAR LETTER DHA
-                 U+1039/U+1013: "္ဓ" MYANMAR SIGN VIRAMA/MYANMAR LETTER DHA -->
-            <Key
-                latin:keySpec="&#x1013;"
-                latin:moreKeys="&#x1039;&#x1013;" />
-            <!-- U+1003: "ဃ" MYANMAR LETTER GHA -->
-            <Key latin:keySpec="&#x1003;" />
-            <!-- U+100E: "ဎ" MYANMAR LETTER DDHA -->
-            <Key latin:keySpec="&#x100E;" />
-            <!-- U+103F: "ဿ" MYANMAR LETTER GREAT SA -->
-            <Key latin:keySpec="&#x103F;" />
-            <!-- U+100F: "ဏ" MYANMAR LETTER NNA -->
-            <Key latin:keySpec="&#x100F;" />
-            <!-- U+1008: "ဈ" MYANMAR LETTER JHA
-                 U+1039/U+1008: "္ဈ" MYANMAR SIGN VIRAMA/MYANMAR LETTER JHA -->
-            <Key
-                latin:keySpec="&#x1008;"
-                latin:moreKeys="&#x1039;&#x1008;" />
-            <!-- U+1007: "ဇ" MYANMAR LETTER JA
-                 U+1039/U+1007: "္ဇ" MYANMAR SIGN VIRAMA/MYANMAR LETTER JA -->
-            <Key
-                latin:keySpec="&#x1007;"
-                latin:moreKeys="&#x1039;&#x1007;" />
-            <!-- U+1002: "ဂ" MYANMAR LETTER GA
-                 U+1039/U+1002: "္ဂ" MYANMAR SIGN VIRAMA/MYANMAR LETTER GA -->
-            <Key
-                latin:keySpec="&#x1002;"
-                latin:moreKeys="&#x1039;&#x1002;" />
-        </case>
-        <default>
-            <!-- U+1006: "ဆ" MYANMAR LETTER CHA
-                 U+1039/U+1006: "္ဆ" MYANMAR SIGN VIRAMA/MYANMAR LETTER CHA -->
-            <Key
-                latin:keySpec="&#x1006;"
-                latin:moreKeys="&#x1039;&#x1006;" />
-            <!-- U+1010: "တ" MYANMAR LETTER TA
-                 U+1039/U+1010: "္တ" MYANMAR SIGN VIRAMA/MYANMAR LETTER TA -->
-            <Key
-                latin:keySpec="&#x1010;"
-                latin:moreKeys="&#x1039;&#x1010;" />
-            <!-- U+1014: "န" MYANMAR LETTER NA
-                 U+1039/U+1014: "္န" MYANMAR SIGN VIRAMA/MYANMAR LETTER NA -->
-            <Key
-                latin:keySpec="&#x1014;"
-                latin:moreKeys="&#x1039;&#x1014;" />
-            <!-- U+1019: "မ" MYANMAR LETTER MA
-                 U+1039/U+1019: "္မ" MYANMAR SIGN VIRAMA/MYANMAR LETTER MA -->
-            <Key
-                latin:keySpec="&#x1019;"
-                latin:moreKeys="&#x1039;&#x1019;" />
-            <!-- U+1021: "အ" MYANMAR LETTER A -->
-            <Key latin:keySpec="&#x1021;" />
-            <!-- U+1015: "ပ" MYANMAR LETTER PA -->
-            <Key latin:keySpec="&#x1015;" />
-            <!-- U+1000: "က" MYANMAR LETTER KA
-                 U+1039/U+1000: "္က" MYANMAR SIGN VIRAMA/MYANMAR LETTER KA -->
-            <Key
-                latin:keySpec="&#x1000;"
-                latin:moreKeys="&#x1039;&#x1000;" />
-            <!-- U+1004: "င" MYANMAR LETTER NGA -->
-            <Key latin:keySpec="&#x1004;" />
-            <!-- U+101E: "သ" MYANMAR LETTER SA -->
-            <Key latin:keySpec="&#x101E;" />
-            <!-- U+1005: "စ" MYANMAR LETTER CA
-                 U+1039/U+1005: "္စ" MYANMAR SIGN VIRAMA/MYANMAR LETTER CA -->
-            <Key
-                latin:keySpec="&#x1005;"
-                latin:moreKeys="&#x1039;&#x1005;" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_myanmar3.xml b/java/res/xml/rowkeys_myanmar3.xml
deleted file mode 100644
index 4dafe09..0000000
--- a/java/res/xml/rowkeys_myanmar3.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- U+101A: "ယ" MYANMAR LETTER YA -->
-            <Key latin:keySpec="&#x101A;" />
-            <!-- U+1039: "္" MYANMAR SIGN VIRAMA -->
-            <Key latin:keySpec="&#x1039;" />
-            <!-- U+1004/U+103A/U+1039: "င်္င" MYANMAR LETTER NGA/MYANMAR SIGN ASAT/MYANMAR SIGN VIRAMA -->
-            <Key
-                latin:keySpec="&#x1004;&#x103A;&#x1039;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-            <!-- U+103E: "ှ" MYANMAR CONSONANT SIGN MEDIAL HA -->
-            <Key latin:keySpec="&#x103E;" />
-            <!-- U+102E: "ီ" MYANMAR VOWEL SIGN II -->
-            <Key latin:keySpec="&#x102E;" />
-            <!-- U+1030: "ူ" MYANMAR VOWEL SIGN UU -->
-            <Key latin:keySpec="&#x1030;" />
-            <!-- U+102B: "ါ" MYANMAR VOWEL SIGN TALL AA -->
-            <Key latin:keySpec="&#x102B;" />
-            <!-- U+1032: "ဲ" MYANMAR VOWEL SIGN AI -->
-            <Key latin:keySpec="&#x1032;" />
-            <!-- U+1036: "ံ" MYANMAR SIGN ANUSVARA -->
-            <Key latin:keySpec="&#x1036;" />
-            <!-- U+101F: "ဟ" MYANMAR LETTER HA -->
-            <Key latin:keySpec="&#x101F;" />
-        </case>
-        <default>
-            <!-- U+1031: "ေ" MYANMAR VOWEL SIGN E -->
-            <Key latin:keySpec="&#x1031;" />
-            <!-- U+103B: "ျ" MYANMAR CONSONANT SIGN MEDIAL YA -->
-            <Key latin:keySpec="&#x103B;" />
-            <!-- U+103C: "ြ" MYANMAR CONSONANT SIGN MEDIAL RA -->
-            <Key latin:keySpec="&#x103C;" />
-            <!-- U+103D: "ွ" MYANMAR CONSONANT SIGN MEDIAL WA
-                 U+103E: "ှ" MYANMAR CONSONANT SIGN MEDIAL HA
-                 U+103D/U+103E: "ွှ" MYANMAR CONSONANT SIGN MEDIAL WA/MYANMAR CONSONANT SIGN MEDIAL HA -->
-            <Key
-                latin:keySpec="&#x103D;"
-                latin:moreKeys="&#x103E;,&#x103D;&#x103E;" />
-            <!-- U+102D: "ိ" MYANMAR VOWEL SIGN I
-                 U+102E: "ီ" MYANMAR VOWEL SIGN II -->
-            <Key
-                latin:keySpec="&#x102D;"
-                latin:moreKeys="&#x102E;" />
-            <!-- U+102F: "ု" MYANMAR VOWEL SIGN U
-                 U+1030: "ူ" MYANMAR VOWEL SIGN UU -->
-            <Key
-                latin:keySpec="&#x102F;"
-                latin:moreKeys="&#x1030;" />
-            <!-- U+102C: "ာ" MYANMAR VOWEL SIGN AA
-                 U+102B: "ါ" MYANMAR VOWEL SIGN TALL AA -->
-            <Key
-                latin:keySpec="&#x102C;"
-                latin:moreKeys="&#x102B;" />
-            <!-- U+103A: "်" MYANMAR SIGN ASAT
-                 U+1032: "ဲ" MYANMAR VOWEL SIGN AI -->
-            <Key
-                latin:keySpec="&#x103A;"
-                latin:moreKeys="&#x1032;" />
-            <!-- U+1037: "့" MYANMAR SIGN DOT BELOW
-                 U+1036: "ံ" MYANMAR SIGN ANUSVARA -->
-            <Key
-                latin:keySpec="&#x1037;"
-                latin:moreKeys="&#x1036;" />
-            <!-- U+1038: "း" MYANMAR SIGN VISARGA -->
-            <Key latin:keySpec="&#x1038;" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_myanmar4.xml b/java/res/xml/rowkeys_myanmar4.xml
deleted file mode 100644
index a1befcf..0000000
--- a/java/res/xml/rowkeys_myanmar4.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- U+1025: "ဥ" MYANMAR LETTER U -->
-            <Key latin:keySpec="&#x1025;" />
-            <!-- U+1026: "ဦ" MYANMAR LETTER UU -->
-            <Key latin:keySpec="&#x1026;" />
-            <!-- U+100C: "ဌ" MYANMAR LETTER TTHA -->
-            <Key latin:keySpec="&#x100C;" />
-            <!-- U+100B: "ဋ" MYANMAR LETTER TTA -->
-            <Key latin:keySpec="&#x100B;" />
-            <!-- U+100D: "ဍ" MYANMAR LETTER DDA -->
-            <Key latin:keySpec="&#x100D;" />
-            <!-- U+1020: "ဠ" MYANMAR LETTER LLA -->
-            <Key latin:keySpec="&#x1020;" />
-            <!-- U+100B/U+1039/U+100C: "ဋ္ဌ" MYANMAR LETTER TTA/MYANMAR SIGN VIRAMA/MYANMAR LETTER TTHA -->
-            <Key
-                latin:keySpec="&#x100B;&#x1039;&#x100C;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-            <!-- U+100F/U+1039/U+100D: "ဏ္ဍ" MYANMAR LETTER NNA/MYANMAR SIGN VIRAMA/MYANMAR LETTER DDA
-                 U+100F/U+1039/U+100C: "ဏ္ဌ" MYANMAR LETTER NNA/MYANMAR SIGN VIRAMA/MYANMAR LETTER TTHA -->
-            <Key
-                latin:keySpec="&#x100F;&#x1039;&#x100D;"
-                latin:moreKeys="&#x100F;&#x1039;&#x100C;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-        </case>
-        <default>
-            <!-- U+1016: "ဖ" MYANMAR LETTER PHA -->
-            <Key latin:keySpec="&#x1016;" />
-            <!-- U+1011: "ထ" MYANMAR LETTER THA
-                 U+1039/U+1011: "္ထ" MYANMAR SIGN VIRAMA/MYANMAR LETTER THA -->
-            <Key
-                latin:keySpec="&#x1011;"
-                latin:moreKeys="&#x1039;&#x1011;" />
-            <!-- U+1001: "ခ" MYANMAR LETTER KHA
-                 U+1039/U+1001: "္ခ" MYANMAR SIGN VIRAMA/MYANMAR LETTER KHA -->
-            <Key
-                latin:keySpec="&#x1001;"
-                latin:moreKeys="&#x1039;&#x1001;" />
-            <!-- U+101C: "လ" MYANMAR LETTER LA
-                 U+1039/U+101C: "္လ" MYANMAR SIGN VIRAMA/MYANMAR LETTER LA -->
-            <Key
-                latin:keySpec="&#x101C;"
-                latin:moreKeys="&#x1039;&#x101C;" />
-            <!-- U+1018: "ဘ" MYANMAR LETTER BHA
-                 U+1039/U+1018: "္ဘ" MYANMAR SIGN VIRAMA/MYANMAR LETTER BHA -->
-            <Key
-                latin:keySpec="&#x1018;"
-                latin:moreKeys="&#x1039;&#x1018;" />
-            <!-- U+100A: "ည" MYANMAR LETTER NNYA
-                 U+1009: "ဉ" MYANMAR LETTER NYA -->
-            <Key
-                latin:keySpec="&#x100A;"
-                latin:moreKeys="&#x1009;" />
-            <!-- U+101B: "ရ" MYANMAR LETTER RA -->
-            <Key latin:keySpec="&#x101B;" />
-            <!-- U+101D: "ဝ" MYANMAR LETTER WA -->
-            <Key latin:keySpec="&#x101D;" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_nepali_romanized3.xml b/java/res/xml/rowkeys_nepali_romanized3.xml
index 24f5908..c6a1e28 100644
--- a/java/res/xml/rowkeys_nepali_romanized3.xml
+++ b/java/res/xml/rowkeys_nepali_romanized3.xml
@@ -43,11 +43,6 @@
             <Key latin:keyStyle="baseKeyDevanagariSignAnusvara" />
             <!-- U+0919: "ङ" DEVANAGARI LETTER NGA -->
             <Key latin:keySpec="&#x0919;" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" />
-            <Key latin:keyStyle="baseKeyDevanagariSignVirama" />
         </case>
         <default>
             <!-- U+0937: "ष" DEVANAGARI LETTER SSA -->
@@ -64,16 +59,14 @@
             <Key latin:keySpec="&#x0928;" />
             <!-- U+092E: "म" DEVANAGARI LETTER MA -->
             <Key latin:keySpec="&#x092E;" />
-            <!-- U+0964: "।" DEVANAGARI DANDA
-                 U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
-            <Key
-                latin:keySpec="&#x0964;"
-                latin:moreKeys="&#x093D;" />
             <!-- Because the font rendering system prior to API version 16 can't automatically
                  render dotted circle for incomplete combining letter of some scripts, different
                  set of Key definitions are needed based on the API version. -->
             <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" />
-            <Key latin:keyStyle="baseKeyDevanagariSignVirama" />
+            <!-- U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
+            <Key
+                latin:keyStyle="baseKeyDevanagariSignVirama"
+                latin:moreKeys="&#x093D;" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml/rowkeys_nepali_traditional3.xml b/java/res/xml/rowkeys_nepali_traditional3.xml
new file mode 100644
index 0000000..c43c593
--- /dev/null
+++ b/java/res/xml/rowkeys_nepali_traditional3.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
+    <switch>
+        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
+            <!-- U+0915/U+094D: "क्" DEVANAGARI LETTER KA/DEVANAGARI SIGN VIRAMA -->
+            <Key
+                latin:keySpec="&#x0915;&#x094D;"
+                latin:keyLabelFlags="followKeyLetterRatio" />
+            <!-- U+0939/U+094D/U+092E: "ह्म" DEVANAGARI LETTER HA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER MA -->
+            <Key
+                latin:keySpec="&#x0939;&#x094D;&#x092E;"
+                latin:keyLabelFlags="followKeyLetterRatio" />
+            <!-- U+090B: "ऋ" DEVANAGARI LETTER VOCALIC R -->
+            <Key latin:keySpec="&#x090B;" />
+            <!-- U+0950: "ॐ" DEVANAGARI OM -->
+            <Key latin:keySpec="&#x0950;" />
+            <!-- Because the font rendering system prior to API version 16 can't automatically
+                 render dotted circle for incomplete combining letter of some scripts, different
+                 set of Key definitions are needed based on the API version. -->
+            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_au" />
+            <Key latin:keyStyle="baseKeyDevanagariVowelSignAu" />
+            <!-- U+0926/U+094D/U+092F: "द्य" DEVANAGARI LETTER DA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER YA -->
+            <Key
+                latin:keySpec="&#x0926;&#x094D;&#x092F;"
+                latin:keyLabelFlags="followKeyLetterRatio" />
+            <!-- Because the font rendering system prior to API version 16 can't automatically
+                 render dotted circle for incomplete combining letter of some scripts, different
+                 set of Key definitions are needed based on the API version. -->
+            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_anusvara" />
+            <Key latin:keyStyle="baseKeyDevanagariSignAnusvara" />
+            <!-- U+0919: "ङ" DEVANAGARI LETTER NGA -->
+            <Key latin:keySpec="&#x0919;" />
+            <!-- Because the font rendering system prior to API version 16 can't automatically
+                 render dotted circle for incomplete combining letter of some scripts, different
+                 set of Key definitions are needed based on the API version. -->
+            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_ai" />
+            <Key latin:keyStyle="baseKeyDevanagariVowelSignAi" />
+        </case>
+        <default>
+            <!-- U+0936: "श" DEVANAGARI LETTER SHA -->
+            <Key latin:keySpec="&#x0936;" />
+            <!-- U+0939: "ह" DEVANAGARI LETTER HA -->
+            <Key latin:keySpec="&#x0939;" />
+            <!-- U+0905: "अ" DEVANAGARI LETTER A -->
+            <Key latin:keySpec="&#x0905;" />
+            <!-- U+0916: "ख" DEVANAGARI LETTER KHA -->
+            <Key latin:keySpec="&#x0916;" />
+            <!-- U+0926: "द" DEVANAGARI LETTER DA -->
+            <Key latin:keySpec="&#x0926;" />
+            <!-- U+0932: "ल" DEVANAGARI LETTER LA -->
+            <Key latin:keySpec="&#x0932;" />
+            <!-- Because the font rendering system prior to API version 16 can't automatically
+                 render dotted circle for incomplete combining letter of some scripts, different
+                 set of Key definitions are needed based on the API version. -->
+            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_e" />
+            <Key latin:keyStyle="baseKeyDevanagariVowelSignE" />
+            <!-- Because the font rendering system prior to API version 16 can't automatically
+                 render dotted circle for incomplete combining letter of some scripts, different
+                 set of Key definitions are needed based on the API version. -->
+            <include
+                latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" />
+            <Key latin:keyStyle="baseKeyDevanagariSignVirama" />
+            <!-- U+0930: "र" DEVANAGARI LETTER RA
+                 U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U -->
+            <Key
+                latin:keySpec="&#x0930;"
+                latin:moreKeys="&#x0930;&#x0941;" />
+        </default>
+    </switch>
+</merge>
diff --git a/java/res/xml/rowkeys_nepali_traditional3_left6.xml b/java/res/xml/rowkeys_nepali_traditional3_left6.xml
deleted file mode 100644
index ade2787..0000000
--- a/java/res/xml/rowkeys_nepali_traditional3_left6.xml
+++ /dev/null
@@ -1,61 +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.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- U+0915/U+094D: "क्" DEVANAGARI LETTER KA/DEVANAGARI SIGN VIRAMA -->
-            <Key
-                latin:keySpec="&#x0915;&#x094D;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-            <!-- U+0939/U+094D/U+092E: "ह्म" DEVANAGARI LETTER HA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER MA -->
-            <Key
-                latin:keySpec="&#x0939;&#x094D;&#x092E;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-            <!-- U+090B: "ऋ" DEVANAGARI LETTER VOCALIC R -->
-            <Key latin:keySpec="&#x090B;" />
-            <!-- U+0950: "ॐ" DEVANAGARI OM -->
-            <Key latin:keySpec="&#x0950;" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_au" />
-            <Key latin:keyStyle="baseKeyDevanagariVowelSignAu" />
-            <!-- U+0926/U+094D/U+092F: "द्य" DEVANAGARI LETTER DA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER YA -->
-            <Key
-                latin:keySpec="&#x0926;&#x094D;&#x092F;"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-        </case>
-        <default>
-            <!-- U+0936: "श" DEVANAGARI LETTER SHA -->
-            <Key latin:keySpec="&#x0936;" />
-            <!-- U+0939: "ह" DEVANAGARI LETTER HA -->
-            <Key latin:keySpec="&#x0939;" />
-            <!-- U+0905: "अ" DEVANAGARI LETTER A -->
-            <Key latin:keySpec="&#x0905;" />
-            <!-- U+0916: "ख" DEVANAGARI LETTER KHA -->
-            <Key latin:keySpec="&#x0916;" />
-            <!-- U+0926: "द" DEVANAGARI LETTER DA -->
-            <Key latin:keySpec="&#x0926;" />
-            <!-- U+0932: "ल" DEVANAGARI LETTER LA -->
-            <Key latin:keySpec="&#x0932;" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_nepali_traditional3_right3.xml b/java/res/xml/rowkeys_nepali_traditional3_right3.xml
deleted file mode 100644
index 4db438d..0000000
--- a/java/res/xml/rowkeys_nepali_traditional3_right3.xml
+++ /dev/null
@@ -1,52 +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.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_anusvara" />
-            <Key latin:keyStyle="baseKeyDevanagariSignAnusvara" />
-            <!-- U+0919: "ङ" DEVANAGARI LETTER NGA -->
-            <Key latin:keySpec="&#x0919;" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_ai" />
-            <Key latin:keyStyle="baseKeyDevanagariVowelSignAi" />
-        </case>
-        <default>
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_e" />
-            <Key latin:keyStyle="baseKeyDevanagariVowelSignE" />
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key latin:keySpec="&#x0964;" />
-            <!-- U+0930: "र" DEVANAGARI LETTER RA
-                 U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U -->
-            <Key
-                latin:keySpec="&#x0930;"
-                latin:moreKeys="&#x0930;&#x0941;" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_nepali_traditional3_right5.xml b/java/res/xml/rowkeys_nepali_traditional3_right5.xml
deleted file mode 100644
index c7c73a4..0000000
--- a/java/res/xml/rowkeys_nepali_traditional3_right5.xml
+++ /dev/null
@@ -1,76 +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.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <switch>
-        <case latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted">
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_anusvara" />
-            <Key latin:keyStyle="baseKeyDevanagariSignAnusvara" />
-            <!-- U+0919: "ङ" DEVANAGARI LETTER NGA -->
-            <Key latin:keySpec="&#x0919;" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_ai" />
-            <Key latin:keyStyle="baseKeyDevanagariVowelSignAi" />
-            <!-- U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U -->
-            <Key
-                latin:keySpec="&#x0930;&#x0941;"
-                latin:moreKeys="!"
-                latin:keyLabelFlags="followKeyLetterRatio" />
-            <Key
-                latin:keySpec="\?"
-                latin:keyLabelFlags="fontDefault" />
-        </case>
-        <default>
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_visarga" />
-            <!-- U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA -->
-            <Key
-                latin:keyStyle="baseKeyDevanagariSignVisarga"
-                latin:moreKeys="&#x093D;" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_vowel_sign_e" />
-            <!-- Override more keys with empty definition -->
-            <key-style latin:styleName="moreKeysDevanagariVowelSignE" />
-            <Key latin:keyStyle="baseKeyDevanagariVowelSignE" />
-            <!-- U+0964: "।" DEVANAGARI DANDA -->
-            <Key latin:keySpec="&#x0964;" />
-            <!-- U+0930: "र" DEVANAGARI LETTER RA -->
-            <Key
-                latin:keySpec="&#x0930;"
-                latin:moreKeys="!" />
-            <!-- Because the font rendering system prior to API version 16 can't automatically
-                 render dotted circle for incomplete combining letter of some scripts, different
-                 set of Key definitions are needed based on the API version. -->
-            <include latin:keyboardLayout="@xml/keystyle_devanagari_sign_virama" />
-            <Key
-                latin:keyStyle="baseKeyDevanagariSignVirama"
-                latin:moreKeys="\?" />
-        </default>
-    </switch>
-</merge>
diff --git a/java/res/xml/rowkeys_qwerty1.xml b/java/res/xml/rowkeys_qwerty1.xml
index 8f3b160..b8e4a4c 100644
--- a/java/res/xml/rowkeys_qwerty1.xml
+++ b/java/res/xml/rowkeys_qwerty1.xml
@@ -21,53 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="!text/keyspec_q"
-        latin:keyHintLabel="1"
-        latin:additionalMoreKeys="1"
-        latin:moreKeys="!text/morekeys_q" />
-    <Key
-        latin:keySpec="!text/keyspec_w"
-        latin:keyHintLabel="2"
-        latin:additionalMoreKeys="2"
-        latin:moreKeys="!text/morekeys_w" />
-    <Key
-        latin:keySpec="e"
-        latin:keyHintLabel="3"
-        latin:additionalMoreKeys="3"
-        latin:moreKeys="!text/morekeys_e" />
-    <Key
-        latin:keySpec="r"
-        latin:keyHintLabel="4"
-        latin:additionalMoreKeys="4"
-        latin:moreKeys="!text/morekeys_r" />
-    <Key
-        latin:keySpec="t"
-        latin:keyHintLabel="5"
-        latin:additionalMoreKeys="5"
-        latin:moreKeys="!text/morekeys_t" />
-    <Key
-        latin:keySpec="!text/keyspec_y"
-        latin:keyHintLabel="6"
-        latin:additionalMoreKeys="6"
-        latin:moreKeys="!text/morekeys_y" />
-    <Key
-        latin:keySpec="u"
-        latin:keyHintLabel="7"
-        latin:additionalMoreKeys="7"
-        latin:moreKeys="!text/morekeys_u" />
-    <Key
-        latin:keySpec="i"
-        latin:keyHintLabel="8"
-        latin:additionalMoreKeys="8"
-        latin:moreKeys="!text/morekeys_i" />
-    <Key
-        latin:keySpec="o"
-        latin:keyHintLabel="9"
-        latin:additionalMoreKeys="9"
-        latin:moreKeys="!text/morekeys_o" />
-    <Key
-        latin:keySpec="p"
-        latin:keyHintLabel="0"
-        latin:additionalMoreKeys="0" />
+    <!-- q,w,e,r,t -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty1_left5" />
+    <!-- y,u,i,o,p -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty1_right5" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty1_left5.xml b/java/res/xml/rowkeys_qwerty1_left5.xml
new file mode 100644
index 0000000..ff9f1b2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty1_left5.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="!text/keyspec_q"
+        latin:keyHintLabel="1"
+        latin:additionalMoreKeys="1"
+        latin:moreKeys="!text/morekeys_q" />
+    <Key
+        latin:keySpec="!text/keyspec_w"
+        latin:keyHintLabel="2"
+        latin:additionalMoreKeys="2"
+        latin:moreKeys="!text/morekeys_w" />
+    <Key
+        latin:keySpec="e"
+        latin:keyHintLabel="3"
+        latin:additionalMoreKeys="3"
+        latin:moreKeys="!text/morekeys_e" />
+    <Key
+        latin:keySpec="r"
+        latin:keyHintLabel="4"
+        latin:additionalMoreKeys="4"
+        latin:moreKeys="!text/morekeys_r" />
+    <Key
+        latin:keySpec="t"
+        latin:keyHintLabel="5"
+        latin:additionalMoreKeys="5"
+        latin:moreKeys="!text/morekeys_t" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty1_right5.xml b/java/res/xml/rowkeys_qwerty1_right5.xml
new file mode 100644
index 0000000..2b3cae2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty1_right5.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="!text/keyspec_y"
+        latin:keyHintLabel="6"
+        latin:additionalMoreKeys="6"
+        latin:moreKeys="!text/morekeys_y" />
+    <Key
+        latin:keySpec="u"
+        latin:keyHintLabel="7"
+        latin:additionalMoreKeys="7"
+        latin:moreKeys="!text/morekeys_u" />
+    <Key
+        latin:keySpec="i"
+        latin:keyHintLabel="8"
+        latin:additionalMoreKeys="8"
+        latin:moreKeys="!text/morekeys_i" />
+    <Key
+        latin:keySpec="o"
+        latin:keyHintLabel="9"
+        latin:additionalMoreKeys="9"
+        latin:moreKeys="!text/morekeys_o" />
+    <Key
+        latin:keySpec="p"
+        latin:keyHintLabel="0"
+        latin:additionalMoreKeys="0" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty2.xml b/java/res/xml/rowkeys_qwerty2.xml
index 4077bea..550db3b 100644
--- a/java/res/xml/rowkeys_qwerty2.xml
+++ b/java/res/xml/rowkeys_qwerty2.xml
@@ -21,30 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="a"
-        latin:moreKeys="!text/morekeys_a" />
-    <Key
-        latin:keySpec="s"
-        latin:moreKeys="!text/morekeys_s" />
-    <Key
-        latin:keySpec="d"
-        latin:moreKeys="!text/morekeys_d" />
-    <Key
-        latin:keySpec="f" />
-    <Key
-        latin:keySpec="g"
-        latin:moreKeys="!text/morekeys_g" />
-    <Key
-        latin:keySpec="h"
-        latin:moreKeys="!text/morekeys_h" />
-    <Key
-        latin:keySpec="j"
-        latin:moreKeys="!text/morekeys_j" />
-    <Key
-        latin:keySpec="k"
-        latin:moreKeys="!text/morekeys_k" />
-    <Key
-        latin:keySpec="l"
-        latin:moreKeys="!text/morekeys_l" />
+    <!-- a,s,d,f,g -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty2_left5" />
+    <!-- h,j,k,l -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty2_right4" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty2_left5.xml b/java/res/xml/rowkeys_qwerty2_left5.xml
new file mode 100644
index 0000000..1803bf2
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty2_left5.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="a"
+        latin:moreKeys="!text/morekeys_a" />
+    <Key
+        latin:keySpec="s"
+        latin:moreKeys="!text/morekeys_s" />
+    <Key
+        latin:keySpec="d"
+        latin:moreKeys="!text/morekeys_d" />
+    <Key
+        latin:keySpec="f" />
+    <Key
+        latin:keySpec="g"
+        latin:moreKeys="!text/morekeys_g" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty2_right4.xml b/java/res/xml/rowkeys_qwerty2_right4.xml
new file mode 100644
index 0000000..99936b7
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty2_right4.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="h"
+        latin:moreKeys="!text/morekeys_h" />
+    <Key
+        latin:keySpec="j"
+        latin:moreKeys="!text/morekeys_j" />
+    <Key
+        latin:keySpec="k"
+        latin:moreKeys="!text/morekeys_k" />
+    <Key
+        latin:keySpec="l"
+        latin:moreKeys="!text/morekeys_l" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty3.xml b/java/res/xml/rowkeys_qwerty3.xml
index 8562003..7a523f1 100644
--- a/java/res/xml/rowkeys_qwerty3.xml
+++ b/java/res/xml/rowkeys_qwerty3.xml
@@ -21,23 +21,10 @@
 <merge
     xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
 >
-    <Key
-        latin:keySpec="z"
-        latin:moreKeys="!text/morekeys_z" />
-    <Key
-        latin:keySpec="!text/keyspec_x"
-        latin:moreKeys="!text/morekeys_x" />
-    <Key
-        latin:keySpec="c"
-        latin:moreKeys="!text/morekeys_c" />
-    <Key
-        latin:keySpec="v"
-        latin:moreKeys="!text/morekeys_v" />
-    <Key
-        latin:keySpec="b" />
-    <Key
-        latin:keySpec="n"
-        latin:moreKeys="!text/morekeys_n" />
-    <Key
-        latin:keySpec="m" />
+    <!-- z,x,c,v -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty3_left4" />
+    <!-- b,n,m -->
+    <include
+        latin:keyboardLayout="@xml/rowkeys_qwerty3_right3" />
 </merge>
diff --git a/java/res/xml/rowkeys_qwerty3_left4.xml b/java/res/xml/rowkeys_qwerty3_left4.xml
new file mode 100644
index 0000000..6043c3b
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty3_left4.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="z"
+        latin:moreKeys="!text/morekeys_z" />
+    <Key
+        latin:keySpec="!text/keyspec_x"
+        latin:moreKeys="!text/morekeys_x" />
+    <Key
+        latin:keySpec="c"
+        latin:moreKeys="!text/morekeys_c" />
+    <Key
+        latin:keySpec="v"
+        latin:moreKeys="!text/morekeys_v" />
+</merge>
diff --git a/java/res/xml/rowkeys_qwerty3_right3.xml b/java/res/xml/rowkeys_qwerty3_right3.xml
new file mode 100644
index 0000000..f699103
--- /dev/null
+++ b/java/res/xml/rowkeys_qwerty3_right3.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge
+    xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
+>
+    <Key
+        latin:keySpec="b" />
+    <Key
+        latin:keySpec="n"
+        latin:moreKeys="!text/morekeys_n" />
+    <Key
+        latin:keySpec="m" />
+</merge>
diff --git a/java/res/xml/rowkeys_serbian_qwertz1.xml b/java/res/xml/rowkeys_serbian_qwertz1.xml
new file mode 100644
index 0000000..1615701
--- /dev/null
+++ b/java/res/xml/rowkeys_serbian_qwertz1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwertz1" />
+    <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON -->
+    <Key latin:keySpec="&#x0161;" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rowkeys_serbian_qwertz2.xml b/java/res/xml/rowkeys_serbian_qwertz2.xml
new file mode 100644
index 0000000..83ec92d
--- /dev/null
+++ b/java/res/xml/rowkeys_serbian_qwertz2.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+    <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
+    <Key latin:keySpec="&#x010D;" />
+    <!-- U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
+    <Key latin:keySpec="&#x0107;" />
+</merge>
diff --git a/java/res/xml/rowkeys_serbian_qwertz3.xml b/java/res/xml/rowkeys_serbian_qwertz3.xml
new file mode 100644
index 0000000..30ba7af
--- /dev/null
+++ b/java/res/xml/rowkeys_serbian_qwertz3.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwertz3" />
+    <!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE -->
+    <Key latin:keySpec="&#x0111;" />
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <Key latin:keySpec="&#x017E;" />
+</merge>
diff --git a/java/res/xml/rowkeys_symbols2.xml b/java/res/xml/rowkeys_symbols2.xml
index 8119158..e55b1b8 100644
--- a/java/res/xml/rowkeys_symbols2.xml
+++ b/java/res/xml/rowkeys_symbols2.xml
@@ -44,7 +44,8 @@
         </default>
     </switch>
     <Key
-        latin:keyStyle="currencyKeyStyle" />
+        latin:keyStyle="currencyKeyStyle"
+        latin:keyLabelFlags="followKeyLetterRatio" />
     <Key
         latin:keySpec="!text/keyspec_symbols_percent"
         latin:moreKeys="!text/morekeys_symbols_percent" />
diff --git a/java/res/xml/rowkeys_telugu2.xml b/java/res/xml/rowkeys_telugu2.xml
index a472fd3..f1ce459 100644
--- a/java/res/xml/rowkeys_telugu2.xml
+++ b/java/res/xml/rowkeys_telugu2.xml
@@ -51,10 +51,10 @@
         latin:moreKeys="&#x0C2B;" />
     <!-- U+0C30: "ర" TELUGU LETTER RA
          U+0C31: "ఱ" TELUGU LETTER RRA
-         U+0C43: "ృ" TELUGU VOWEL SIGN VOCALIC R -->
+         U+0C4D/U+0C30: "్ర" TELUGU SIGN VIRAMA/TELUGU LETTER RA -->
     <Key
         latin:keySpec="&#x0C30;"
-        latin:moreKeys="&#x0C31;,&#x0C43;" />
+        latin:moreKeys="&#x0C31;,&#x0C4D;&#x0C30;" />
     <!-- U+0C15: "క" TELUGU LETTER KA
          U+0C16: "ఖ" TELUGU LETTER KHA -->
     <Key
diff --git a/java/res/xml/rowkeys_telugu3.xml b/java/res/xml/rowkeys_telugu3.xml
index 05755ec..2e3730a 100644
--- a/java/res/xml/rowkeys_telugu3.xml
+++ b/java/res/xml/rowkeys_telugu3.xml
@@ -19,24 +19,28 @@
 -->
 
 <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <!-- U+0C46: "ె" TELUGU VOWEL SIGN E
+    <!-- U+0C4A: "ొ" TELUGU VOWEL SIGN O
          U+0C12: "ఒ" TELUGU LETTER O -->
     <Key
-        latin:keySpec="&#x0C46;"
+        latin:keySpec="&#x0C4A;"
         latin:moreKeys="&#x0C12;" />
-    <!-- U+0C02: "ం" TELUGU SIGN ANUSVARA
+    <!-- U+0C46: "ె" TELUGU VOWEL SIGN E
          U+0C0E: "ఎ" TELUGU LETTER E -->
     <Key
-        latin:keySpec="&#x0C02;"
+        latin:keySpec="&#x0C46;"
         latin:moreKeys="&#x0C0E;" />
-    <!-- U+0C2E: "మ" TELUGU LETTER MA -->
-    <Key latin:keySpec="&#x0C2E;" />
+    <!-- U+0C2E: "మ" TELUGU LETTER MA
+         U+0C02: "ం" TELUGU SIGN ANUSVARA
+         U+0C01: "ఁ" TELUGU SIGN CANDRABINDU -->
+    <Key latin:keySpec="&#x0C2E;"
+         latin:moreKeys="&#x0C02;,&#x0C01;" />
     <!-- U+0C28: "న" TELUGU LETTER NA
          U+0C23: "ణ" TELUGU LETTER NNA
-         U+0C19: "ఙ" TELUGU LETTER NGA -->
+         U+0C19: "ఙ" TELUGU LETTER NGA
+         U+0C1E: "ఞ" TELUGU LETTER NYA -->
     <Key
         latin:keySpec="&#x0C28;"
-        latin:moreKeys="&#x0C23;,&#x0C19;" />
+        latin:moreKeys="&#x0C23;,&#x0C19;,&#x0C1E;" />
     <!-- U+0C35: "వ" TELUGU LETTER VA -->
     <Key latin:keySpec="&#x0C35;" />
     <!-- U+0C32: "ల" TELUGU LETTER LA
@@ -50,10 +54,10 @@
         latin:keySpec="&#x0C38;"
         latin:moreKeys="&#x0C36;" />
     <!-- U+0C0B: "ఋ" TELUGU LETTER VOCALIC R
-         U+0C4D/U+0C30: "్ర" TELUGU SIGN VIRAMA/TELUGU LETTER RA -->
+         U+0C43: "ృ" TELUGU VOWEL SIGN VOCALIC R -->
     <Key
         latin:keySpec="&#x0C0B;"
-        latin:moreKeys="&#x0C4D;&#x0C30;" />
+        latin:moreKeys="&#x0C43;" />
     <!-- U+0C37: "ష" TELUGU LETTER SSA
          U+0C15/U+0C4D/U+0C37: "క్ష" TELUGU LETTER KA/TELUGU SIGN VIRAMA/TELUGU LETTER SSA -->
     <Key
diff --git a/java/res/xml/rowkeys_uzbek1.xml b/java/res/xml/rowkeys_uzbek1.xml
new file mode 100644
index 0000000..967e9a7
--- /dev/null
+++ b/java/res/xml/rowkeys_uzbek1.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwerty1" />
+    <!-- U+006F/U+02BB: "oʻ" LATIN SMALL LETTER O/MODIFIER LETTER TURNED COMMA -->
+    <Key
+        latin:keySpec="o&#x02BB;"
+        latin:keyLabelFlags="followKeyLetterRatio" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rowkeys_uzbek2.xml b/java/res/xml/rowkeys_uzbek2.xml
new file mode 100644
index 0000000..b768a12
--- /dev/null
+++ b/java/res/xml/rowkeys_uzbek2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/rowkeys_qwerty2" />
+    <!-- U+0067/U+02BB: "gʻ" LATIN SMALL LETTER G/MODIFIER LETTER TURNED COMMA -->
+    <Key
+        latin:keySpec="g&#x02BB;"
+        latin:keyLabelFlags="followKeyLetterRatio" />
+    <!-- U+02BC: "ʼ" MODIFIER LETTER APOSTROPHE -->
+    <Key latin:keySpec="&#x02BC;" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rows_bengali_akkhor.xml b/java/res/xml/rows_bengali_akkhor.xml
new file mode 100644
index 0000000..1c7e772
--- /dev/null
+++ b/java/res/xml/rows_bengali_akkhor.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor1" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor2" />
+    </Row>
+    <Row
+        latin:keyLabelFlags="fontNormal"
+        latin:keyWidth="8.711%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.8%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_bengali_akkhor3" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
diff --git a/java/res/xml/rows_myanmar.xml b/java/res/xml/rows_myanmar.xml
deleted file mode 100644
index 54538a9..0000000
--- a/java/res/xml/rows_myanmar.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin">
-    <include latin:keyboardLayout="@xml/key_styles_common" />
-    <Row
-        latin:keyWidth="10.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar1" />
-    </Row>
-    <Row
-        latin:keyWidth="10.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar2" />
-    </Row>
-    <Row
-        latin:keyWidth="10.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar3" />
-    </Row>
-    <Row
-        latin:keyWidth="10.0%p"
-        latin:keyLabelFlags="fontNormal|autoXScale"
-    >
-        <Key latin:keyStyle="shiftKeyStyle" />
-        <include latin:keyboardLayout="@xml/rowkeys_myanmar4" />
-        <Key latin:keyStyle="deleteKeyStyle" />
-    </Row>
-    <include latin:keyboardLayout="@xml/row_qwerty4" />
-</merge>
\ No newline at end of file
diff --git a/java/res/xml/rows_nepali_romanized.xml b/java/res/xml/rows_nepali_romanized.xml
index daca3ee..26737ec 100644
--- a/java/res/xml/rows_nepali_romanized.xml
+++ b/java/res/xml/rows_nepali_romanized.xml
@@ -33,16 +33,18 @@
         <include latin:keyboardLayout="@xml/rowkeys_nepali_romanized2" />
     </Row>
     <Row
-        latin:keyWidth="8.711%p"
+        latin:keyWidth="8.75%p"
         latin:keyLabelFlags="fontNormal"
     >
         <Key
             latin:keyStyle="shiftKeyStyle"
-            latin:keyWidth="10.8%p" />
+            latin:keyWidth="15%p"
+            latin:visualInsetsRight="1%p" />
         <include latin:keyboardLayout="@xml/rowkeys_nepali_romanized3" />
         <Key
             latin:keyStyle="deleteKeyStyle"
-            latin:keyWidth="fillRight" />
+            latin:keyWidth="fillRight"
+            latin:visualInsetsLeft="1%p" />
     </Row>
     <include latin:keyboardLayout="@xml/row_qwerty4" />
 </merge>
diff --git a/java/res/xml/rows_nepali_traditional.xml b/java/res/xml/rows_nepali_traditional.xml
index edcc73a..e2e710c 100644
--- a/java/res/xml/rows_nepali_traditional.xml
+++ b/java/res/xml/rows_nepali_traditional.xml
@@ -40,8 +40,7 @@
         <Key
             latin:keyStyle="shiftKeyStyle"
             latin:keyWidth="10.8%p" />
-        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3_left6" />
-        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3_right3" />
+        <include latin:keyboardLayout="@xml/rowkeys_nepali_traditional3" />
         <Key
             latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="fillRight" />
diff --git a/java/res/xml/rows_number_normal.xml b/java/res/xml/rows_number_normal.xml
index d8d1508..0f92ac6 100644
--- a/java/res/xml/rows_number_normal.xml
+++ b/java/res/xml/rows_number_normal.xml
@@ -35,7 +35,8 @@
             latin:keySpec="-"
             latin:moreKeys="+"
             latin:keyLabelFlags="hasPopupHint"
-            latin:keyStyle="numFunctionalKeyStyle"
+            latin:keyStyle="numKeyStyle"
+            latin:backgroundType="functional"
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
@@ -54,7 +55,8 @@
             >
                 <Key
                     latin:keySpec="."
-                    latin:keyStyle="numFunctionalKeyStyle"
+                    latin:keyStyle="numKeyStyle"
+                    latin:backgroundType="functional"
                     latin:keyWidth="fillRight" />
             </case>
             <case
@@ -62,15 +64,17 @@
             >
                 <Key
                     latin:keySpec="."
-                    latin:keyLabelFlags="hasPopupHint"
                     latin:moreKeys="!text/morekeys_am_pm"
-                    latin:keyStyle="numFunctionalKeyStyle"
+                    latin:keyLabelFlags="hasPopupHint"
+                    latin:keyStyle="numKeyStyle"
+                    latin:backgroundType="functional"
                     latin:keyWidth="fillRight" />
             </case>
             <default>
                 <Key
                     latin:keySpec=","
-                    latin:keyStyle="numFunctionalKeyStyle"
+                    latin:keyStyle="numKeyStyle"
+                    latin:backgroundType="functional"
                     latin:keyWidth="fillRight" />
             </default>
         </switch>
diff --git a/java/res/xml/rows_number_password.xml b/java/res/xml/rows_number_password.xml
index 2e61a08..65736c4 100644
--- a/java/res/xml/rows_number_password.xml
+++ b/java/res/xml/rows_number_password.xml
@@ -70,7 +70,8 @@
         <Key
             latin:keyStyle="deleteKeyStyle" />
         <Key
-            latin:keyStyle="num0KeyStyle" />
+            latin:keyStyle="num0KeyStyle"
+            latin:keyHintLabel="+" />
         <Key
             latin:keyStyle="enterKeyStyle" />
         <!-- Note: This Spacer prevents the above key from being marked as a right edge key. -->
diff --git a/java/res/xml/rows_phone.xml b/java/res/xml/rows_phone.xml
index 03e4541..bb5590d 100644
--- a/java/res/xml/rows_phone.xml
+++ b/java/res/xml/rows_phone.xml
@@ -36,7 +36,8 @@
             latin:keySpec="-"
             latin:moreKeys="+"
             latin:keyLabelFlags="hasPopupHint"
-            latin:keyStyle="numFunctionalKeyStyle"
+            latin:keyStyle="numKeyStyle"
+            latin:backgroundType="functional"
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
@@ -48,7 +49,8 @@
             latin:keyStyle="num6KeyStyle" />
         <Key
             latin:keySpec="."
-            latin:keyStyle="numFunctionalKeyStyle"
+            latin:keyStyle="numKeyStyle"
+            latin:backgroundType="functional"
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
diff --git a/java/res/xml/rows_phone_symbols.xml b/java/res/xml/rows_phone_symbols.xml
index 983bfb5..195a183 100644
--- a/java/res/xml/rows_phone_symbols.xml
+++ b/java/res/xml/rows_phone_symbols.xml
@@ -28,45 +28,53 @@
     <Row>
         <Key
             latin:keySpec="("
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec="/"
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec=")"
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec="-"
             latin:moreKeys="+"
             latin:keyLabelFlags="hasPopupHint"
-            latin:keyStyle="numFunctionalKeyStyle"
+            latin:keyStyle="numKeyStyle"
+            latin:backgroundType="functional"
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
         <Key
             latin:keySpec="N"
-            latin:keyStyle="numKeyBaseStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <!-- Pause is a comma. Check PhoneNumberUtils.java to see if this
             has changed. -->
         <Key
-            latin:keyStyle="numPauseKeyStyle" />
+            latin:keySpec="!string/label_pause_key|,"
+            latin:keyLabelFlags="followKeyLabelRatio|autoXScale"
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec=","
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec="."
-            latin:keyStyle="numFunctionalKeyStyle"
+            latin:keyStyle="numKeyStyle"
+            latin:backgroundType="functional"
             latin:keyWidth="fillRight" />
     </Row>
     <Row>
+        <!-- U+FF0A: "*" FULLWIDTH ASTERISK -->
         <Key
-            latin:keyStyle="numStarKeyStyle" />
+            latin:keySpec="&#xFF0A;|*"
+            latin:keyStyle="numSymbolKeyStyle" />
         <!-- Wait is a semicolon. -->
         <Key
-            latin:keyStyle="numWaitKeyStyle" />
+            latin:keySpec="!string/label_wait_key|;"
+            latin:keyLabelFlags="followKeyLabelRatio|autoXScale"
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keySpec="\#"
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keyStyle="deleteKeyStyle"
             latin:keyWidth="fillRight" />
@@ -76,7 +84,7 @@
             latin:keyStyle="numPhoneToNumericKeyStyle" />
         <Key
             latin:keySpec="+"
-            latin:keyStyle="numKeyStyle" />
+            latin:keyStyle="numSymbolKeyStyle" />
         <Key
             latin:keyStyle="numSpaceKeyStyle" />
         <Key
diff --git a/java/res/xml/rows_serbian_qwertz.xml b/java/res/xml/rows_serbian_qwertz.xml
new file mode 100644
index 0000000..4be2abf
--- /dev/null
+++ b/java/res/xml/rows_serbian_qwertz.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz1" />
+    </Row>
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz2" />
+    </Row>
+    <Row latin:keyWidth="8.711%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="10.8%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_serbian_qwertz3" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
\ No newline at end of file
diff --git a/java/res/xml/rows_uzbek.xml b/java/res/xml/rows_uzbek.xml
new file mode 100644
index 0000000..ae655d8
--- /dev/null
+++ b/java/res/xml/rows_uzbek.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" >
+    <include latin:keyboardLayout="@xml/key_styles_common" />
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek1" />
+    </Row>
+    <Row latin:keyWidth="9.091%p" >
+        <include latin:keyboardLayout="@xml/rowkeys_uzbek2" />
+    </Row>
+    <Row latin:keyWidth="9.2%p" >
+        <Key
+            latin:keyStyle="shiftKeyStyle"
+            latin:keyWidth="15%p"
+            latin:visualInsetsRight="1%p" />
+        <Spacer latin:keyWidth="2.8%p" />
+        <include latin:keyboardLayout="@xml/rowkeys_qwerty3" />
+        <Key
+            latin:keyStyle="deleteKeyStyle"
+            latin:keyWidth="fillRight"
+            latin:keyXPos="-15%p"
+            latin:visualInsetsLeft="1%p" />
+    </Row>
+    <include latin:keyboardLayout="@xml/row_qwerty4" />
+</merge>
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 2762a9f..b0072ee 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -152,12 +152,16 @@
      * will occur when a key is typed.
      *
      * @param suggestedWords the list of suggested auto-correction words
-     * @param typedWord the currently typed word
      */
-    public void setAutoCorrection(final SuggestedWords suggestedWords, final String typedWord) {
+    public void setAutoCorrection(final SuggestedWords suggestedWords) {
         if (suggestedWords.mWillAutoCorrect) {
             mAutoCorrectionWord = suggestedWords.getWord(SuggestedWords.INDEX_OF_AUTO_CORRECTION);
-            mTypedWord = typedWord;
+            final SuggestedWords.SuggestedWordInfo typedWordInfo = suggestedWords.mTypedWordInfo;
+            if (null == typedWordInfo) {
+                mTypedWord = null;
+            } else {
+                mTypedWord = typedWordInfo.mWord;
+            }
         } else {
             mAutoCorrectionWord = null;
             mTypedWord = null;
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 7a3510e..bbda9f8 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -26,9 +26,9 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.Locale;
 
@@ -37,6 +37,8 @@
     private static final String SPOKEN_LETTER_RESOURCE_NAME_FORMAT = "spoken_accented_letter_%04X";
     private static final String SPOKEN_SYMBOL_RESOURCE_NAME_FORMAT = "spoken_symbol_%04X";
     private static final String SPOKEN_EMOJI_RESOURCE_NAME_FORMAT = "spoken_emoji_%04X";
+    private static final String SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX = "spoken_emoticon";
+    private static final String SPOKEN_EMOTICON_CODE_POINT_FORMAT = "_%02X";
 
     // The resource ID of the string spoken for obscured keys
     private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot;
@@ -109,7 +111,9 @@
         }
 
         if (code == Constants.CODE_OUTPUT_TEXT) {
-            return key.getOutputText();
+            final String outputText = key.getOutputText();
+            final String description = getSpokenEmoticonDescription(context, outputText);
+            return TextUtils.isEmpty(description) ? outputText : description;
         }
 
         // Just attempt to speak the description.
@@ -340,4 +344,22 @@
         }
         return resId;
     }
+
+    // TODO: Remove this method once TTS supports emoticon verbalization.
+    private static String getSpokenEmoticonDescription(final Context context,
+            final String outputText) {
+        final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX);
+        final int textLength = outputText.length();
+        for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) {
+            final int codePoint = outputText.codePointAt(index);
+            sb.append(String.format(Locale.ROOT, SPOKEN_EMOTICON_CODE_POINT_FORMAT, codePoint));
+        }
+        final String resourceName = sb.toString();
+        final Resources resources = context.getResources();
+        // Note that the resource package name may differ from the context package name.
+        final String resourcePackageName = resources.getResourcePackageName(
+                R.string.spoken_description_unknown);
+        final int resId = resources.getIdentifier(resourceName, "string", resourcePackageName);
+        return (resId == 0) ? null : resources.getString(resId);
+    }
 }
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
index 66b0acb..2de71ce 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
@@ -31,9 +31,9 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
 
 import java.util.List;
 
@@ -329,9 +329,8 @@
         if (currentSettings.isWordSeparator(key.getCode())) {
             return mAccessibilityUtils.getAutoCorrectionDescription(
                     keyCodeDescription, shouldObscure);
-        } else {
-            return keyCodeDescription;
         }
+        return keyCodeDescription;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
index b84d402..e80982f 100644
--- a/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/MainKeyboardAccessibilityDelegate.java
@@ -121,7 +121,7 @@
      */
     private void announceKeyboardLanguage(final Keyboard keyboard) {
         final String languageText = SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(
-                keyboard.mId.mSubtype);
+                keyboard.mId.mSubtype.getRawSubtype());
         sendWindowStateChanged(languageText);
     }
 
@@ -269,13 +269,9 @@
                 eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0 /* metaState */);
         // Inject a fake down event to {@link PointerTracker} to handle a long press correctly.
         tracker.processMotionEvent(downEvent, mKeyDetector);
-        // The above fake down event triggers an unnecessary long press timer that should be
-        // canceled.
-        tracker.cancelLongPressTimer();
         downEvent.recycle();
-        // Invoke {@link MainKeyboardView#onLongPress(PointerTracker)} as if a long press timeout
-        // has passed.
-        mKeyboardView.onLongPress(tracker);
+        // Invoke {@link PointerTracker#onLongPressed()} as if a long press timeout has passed.
+        tracker.onLongPressed();
         // If {@link Key#hasNoPanelAutoMoreKeys()} is true (such as "0 +" key on the phone layout)
         // or a key invokes IME switcher dialog, we should just ignore the next
         // {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether
diff --git a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
index 7d1717b..5d56f12 100644
--- a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java
@@ -33,11 +33,4 @@
     public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD
             ? Build.VERSION.SDK_INT
             : Build.VERSION.SDK_INT + 1;
-
-    /**
-     * API version for L-release.
-     */
-    // TODO: Substitute this constant reference with Build.VERSION_CODES.L* once the *next* version
-    // becomes available.
-    public static final int VERSION_CODES_LXX = 21;
 }
diff --git a/java/src/com/android/inputmethod/compat/CharacterCompat.java b/java/src/com/android/inputmethod/compat/CharacterCompat.java
new file mode 100644
index 0000000..609fe16
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/CharacterCompat.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.compat;
+
+import java.lang.reflect.Method;
+
+public final class CharacterCompat {
+    // Note that Character.isAlphabetic(int), has been introduced in API level 19
+    // (Build.VERSION_CODE.KITKAT).
+    private static final Method METHOD_isAlphabetic = CompatUtils.getMethod(
+            Character.class, "isAlphabetic", int.class);
+
+    private CharacterCompat() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public static boolean isAlphabetic(final int code) {
+        if (METHOD_isAlphabetic != null) {
+            return (Boolean)CompatUtils.invoke(null, false, METHOD_isAlphabetic, code);
+        }
+        switch (Character.getType(code)) {
+        case Character.UPPERCASE_LETTER:
+        case Character.LOWERCASE_LETTER:
+        case Character.TITLECASE_LETTER:
+        case Character.MODIFIER_LETTER:
+        case Character.OTHER_LETTER:
+        case Character.LETTER_NUMBER:
+            return true;
+        default:
+            return false;
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java
index 6aa2736..5db8019 100644
--- a/java/src/com/android/inputmethod/compat/CompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/CompatUtils.java
@@ -144,7 +144,7 @@
 
         public <T> ToObjectMethodWrapper<T> getMethod(final String name,
                 final T defaultValue, final Class<?>... parameterTypes) {
-            return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes),
+            return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes),
                     defaultValue);
         }
 
diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
index 5af3179..01a9e67 100644
--- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java
@@ -16,13 +16,20 @@
 
 package com.android.inputmethod.compat;
 
+import android.annotation.TargetApi;
 import android.graphics.Matrix;
 import android.graphics.RectF;
+import android.os.Build;
+import android.view.inputmethod.CursorAnchorInfo;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
-@UsedForTesting
-public final class CursorAnchorInfoCompatWrapper {
+/**
+ * A wrapper for {@link CursorAnchorInfo}, which has been introduced in API Level 21. You can use
+ * this wrapper to avoid direct dependency on newly introduced types.
+ */
+public class CursorAnchorInfoCompatWrapper {
 
     /**
      * The insertion marker or character bounds have at least one visible region.
@@ -39,123 +46,140 @@
      */
     public static final int FLAG_IS_RTL = 0x04;
 
-    // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX).
-    private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass;
-    private static final CompatUtils.ToIntMethodWrapper sGetSelectionStartMethod;
-    private static final CompatUtils.ToIntMethodWrapper sGetSelectionEndMethod;
-    private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterBoundsMethod;
-    private static final CompatUtils.ToIntMethodWrapper sGetCharacterBoundsFlagsMethod;
-    private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod;
-    private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod;
-    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod;
-    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBottomMethod;
-    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerHorizontalMethod;
-    private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerTopMethod;
-    private static final CompatUtils.ToObjectMethodWrapper<Matrix> sGetMatrixMethod;
-    private static final CompatUtils.ToIntMethodWrapper sGetInsertionMarkerFlagsMethod;
-
-    private static int INVALID_TEXT_INDEX = -1;
-    static {
-        sCursorAnchorInfoClass = CompatUtils.getClassWrapper(
-                "android.view.inputmethod.CursorAnchorInfo");
-        sGetSelectionStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getSelectionStart", INVALID_TEXT_INDEX);
-        sGetSelectionEndMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getSelectionEnd", INVALID_TEXT_INDEX);
-        sGetCharacterBoundsMethod = sCursorAnchorInfoClass.getMethod(
-                "getCharacterBounds", (RectF)null, int.class);
-        sGetCharacterBoundsFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getCharacterBoundsFlags", 0, int.class);
-        sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod(
-                "getComposingText", (CharSequence)null);
-        sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getComposingTextStart", INVALID_TEXT_INDEX);
-        sGetInsertionMarkerBaselineMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getInsertionMarkerBaseline", 0.0f);
-        sGetInsertionMarkerBottomMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getInsertionMarkerBottom", 0.0f);
-        sGetInsertionMarkerHorizontalMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getInsertionMarkerHorizontal", 0.0f);
-        sGetInsertionMarkerTopMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getInsertionMarkerTop", 0.0f);
-        sGetMatrixMethod = sCursorAnchorInfoClass.getMethod("getMatrix", (Matrix)null);
-        sGetInsertionMarkerFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod(
-                "getInsertionMarkerFlags", 0);
+    CursorAnchorInfoCompatWrapper() {
+        // This class is not publicly instantiable.
     }
 
-    @UsedForTesting
-    public boolean isAvailable() {
-        return sCursorAnchorInfoClass.exists() && mInstance != null;
-    }
-
-    private Object mInstance;
-
-    private CursorAnchorInfoCompatWrapper(final Object instance) {
-        mInstance = instance;
-    }
-
-    @UsedForTesting
-    public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) {
-        if (!sCursorAnchorInfoClass.exists()) {
-            return new CursorAnchorInfoCompatWrapper(null);
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @Nullable
+    public static CursorAnchorInfoCompatWrapper wrap(@Nullable final CursorAnchorInfo instance) {
+        if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            return null;
         }
-        return new CursorAnchorInfoCompatWrapper(instance);
-    }
-
-    private static final class FakeHolder {
-        static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null);
-    }
-
-    @UsedForTesting
-    public static CursorAnchorInfoCompatWrapper getFake() {
-        return FakeHolder.sInstance;
+        if (instance == null) {
+            return null;
+        }
+        return new RealWrapper(instance);
     }
 
     public int getSelectionStart() {
-        return sGetSelectionStartMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public int getSelectionEnd() {
-        return sGetSelectionEndMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public CharSequence getComposingText() {
-        return sGetComposingTextMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public int getComposingTextStart() {
-        return sGetComposingTextStartMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public Matrix getMatrix() {
-        return sGetMatrixMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
+    @SuppressWarnings("unused")
     public RectF getCharacterBounds(final int index) {
-        return sGetCharacterBoundsMethod.invoke(mInstance, index);
+        throw new UnsupportedOperationException("not supported.");
     }
 
+    @SuppressWarnings("unused")
     public int getCharacterBoundsFlags(final int index) {
-        return sGetCharacterBoundsFlagsMethod.invoke(mInstance, index);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public float getInsertionMarkerBaseline() {
-        return sGetInsertionMarkerBaselineMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public float getInsertionMarkerBottom() {
-        return sGetInsertionMarkerBottomMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public float getInsertionMarkerHorizontal() {
-        return sGetInsertionMarkerHorizontalMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public float getInsertionMarkerTop() {
-        return sGetInsertionMarkerTopMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
     }
 
     public int getInsertionMarkerFlags() {
-        return sGetInsertionMarkerFlagsMethod.invoke(mInstance);
+        throw new UnsupportedOperationException("not supported.");
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    private static final class RealWrapper extends CursorAnchorInfoCompatWrapper {
+
+        @Nonnull
+        private final CursorAnchorInfo mInstance;
+
+        public RealWrapper(@Nonnull final CursorAnchorInfo info) {
+            mInstance = info;
+        }
+
+        @Override
+        public int getSelectionStart() {
+            return mInstance.getSelectionStart();
+        }
+
+        @Override
+        public int getSelectionEnd() {
+            return mInstance.getSelectionEnd();
+        }
+
+        @Override
+        public CharSequence getComposingText() {
+            return mInstance.getComposingText();
+        }
+
+        @Override
+        public int getComposingTextStart() {
+            return mInstance.getComposingTextStart();
+        }
+
+        @Override
+        public Matrix getMatrix() {
+            return mInstance.getMatrix();
+        }
+
+        @Override
+        public RectF getCharacterBounds(final int index) {
+            return mInstance.getCharacterBounds(index);
+        }
+
+        @Override
+        public int getCharacterBoundsFlags(final int index) {
+            return mInstance.getCharacterBoundsFlags(index);
+        }
+
+        @Override
+        public float getInsertionMarkerBaseline() {
+            return mInstance.getInsertionMarkerBaseline();
+        }
+
+        @Override
+        public float getInsertionMarkerBottom() {
+            return mInstance.getInsertionMarkerBottom();
+        }
+
+        @Override
+        public float getInsertionMarkerHorizontal() {
+            return mInstance.getInsertionMarkerHorizontal();
+        }
+
+        @Override
+        public float getInsertionMarkerTop() {
+            return mInstance.getInsertionMarkerTop();
+        }
+
+        @Override
+        public int getInsertionMarkerFlags() {
+            return mInstance.getInsertionMarkerFlags();
+        }
     }
 }
diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
index 3658672..58ad4bd 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java
@@ -20,11 +20,14 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
+import javax.annotation.Nonnull;
+
 public final class InputMethodSubtypeCompatUtils {
     private static final String TAG = InputMethodSubtypeCompatUtils.class.getSimpleName();
     // Note that InputMethodSubtype(int nameId, int iconId, String locale, String mode,
@@ -51,6 +54,8 @@
         // This utility class is not publicly instantiable.
     }
 
+    @SuppressWarnings("deprecation")
+    @Nonnull
     public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale,
             String mode, String extraValue, boolean isAuxiliary,
             boolean overridesImplicitlyEnabledSubtype, int id) {
@@ -64,6 +69,10 @@
                 overridesImplicitlyEnabledSubtype, id);
     }
 
+    public static boolean isAsciiCapable(final RichInputMethodSubtype subtype) {
+        return isAsciiCapable(subtype.getRawSubtype());
+    }
+
     public static boolean isAsciiCapable(final InputMethodSubtype subtype) {
         return isAsciiCapableWithAPI(subtype)
                 || subtype.containsExtraValueKey(Constants.Subtype.ExtraValue.ASCII_CAPABLE);
diff --git a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
index f411f18..58e5a36 100644
--- a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.compat;
 
 import android.text.Spannable;
+import android.text.Spanned;
 import android.text.style.LocaleSpan;
 import android.util.Log;
 
@@ -127,13 +128,13 @@
             final int spanFlag = spannable.getSpanFlags(existingLocaleSpan);
             if (spanStart < newStart) {
                 newStart = spanStart;
-                isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             }
             if (newEnd < spanEnd) {
                 newEnd = spanEnd;
-                isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) ==
-                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
+                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             }
             existingLocaleSpansToBeMerged.add(existingLocaleSpan);
         }
@@ -201,24 +202,17 @@
 
     private static int getSpanFlag(final int originalFlag,
             final boolean isStartExclusive, final boolean isEndExclusive) {
-        return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) |
+        return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) |
                 getSpanPointMarkFlag(isStartExclusive, isEndExclusive);
     }
 
     private static int getSpanPointMarkFlag(final boolean isStartExclusive,
             final boolean isEndExclusive) {
         if (isStartExclusive) {
-            if (isEndExclusive) {
-                return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
-            } else {
-                return Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
-            }
-        } else {
-            if (isEndExclusive) {
-                return Spannable.SPAN_INCLUSIVE_EXCLUSIVE;
-            } else {
-                return Spannable.SPAN_INCLUSIVE_INCLUSIVE;
-            }
+            return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+                    : Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
         }
+        return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE
+                : Spanned.SPAN_INCLUSIVE_INCLUSIVE;
     }
 }
diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
index eb18007..70ab972 100644
--- a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java
@@ -71,13 +71,13 @@
         CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW);
     }
 
+    @SuppressWarnings("deprecation")
     public static Notification build(final Notification.Builder builder) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
             // #build was added in API level 16, JELLY_BEAN
             return (Notification) CompatUtils.invoke(builder, null, METHOD_build);
-        } else {
-            // #getNotification was deprecated in API level 16, JELLY_BEAN
-            return builder.getNotification();
         }
+        // #getNotification was deprecated in API level 16, JELLY_BEAN
+        return builder.getNotification();
     }
 }
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index c33c015..4d2925d 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -23,13 +23,17 @@
 import android.text.TextUtils;
 import android.text.style.SuggestionSpan;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.LocaleUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.SuggestionSpanPickedNotificationReceiver;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Locale;
+
+import javax.annotation.Nullable;
 
 public final class SuggestionSpanUtils {
     // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
@@ -51,20 +55,22 @@
         // This utility class is not publicly instantiable.
     }
 
+    @UsedForTesting
     public static CharSequence getTextWithAutoCorrectionIndicatorUnderline(
             final Context context, final String text) {
         if (TextUtils.isEmpty(text) || OBJ_FLAG_AUTO_CORRECTION == null) {
             return text;
         }
         final Spannable spannable = new SpannableString(text);
+        // TODO: Set locale if it is feasible.
         final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
-                new String[] {} /* suggestions */, OBJ_FLAG_AUTO_CORRECTION,
-                SuggestionSpanPickedNotificationReceiver.class);
+                new String[] {} /* suggestions */, OBJ_FLAG_AUTO_CORRECTION, null);
         spannable.setSpan(suggestionSpan, 0, text.length(),
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
         return spannable;
     }
 
+    @UsedForTesting
     public static CharSequence getTextWithSuggestionSpan(final Context context,
             final String pickedWord, final SuggestedWords suggestedWords) {
         if (TextUtils.isEmpty(pickedWord) || suggestedWords.isEmpty()
@@ -86,11 +92,31 @@
                 suggestionsList.add(word.toString());
             }
         }
+        // TODO: Set locale if it is feasible.
         final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
-                suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */,
-                SuggestionSpanPickedNotificationReceiver.class);
+                suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */, null);
         final Spannable spannable = new SpannableString(pickedWord);
         spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         return spannable;
     }
+
+    /**
+     * Returns first {@link Locale} found in the given array of {@link SuggestionSpan}.
+     * @param suggestionSpans the array of {@link SuggestionSpan} to be examined.
+     * @return the first {@link Locale} found in {@code suggestionSpans}. {@code null} when not
+     * found.
+     */
+    @UsedForTesting
+    @Nullable
+    public static Locale findFirstLocaleFromSuggestionSpans(
+            final SuggestionSpan[] suggestionSpans) {
+        for (final SuggestionSpan suggestionSpan : suggestionSpans) {
+            final String localeString = suggestionSpan.getLocale();
+            if (TextUtils.isEmpty(localeString)) {
+                continue;
+            }
+            return LocaleUtils.constructLocaleFromString(localeString);
+        }
+        return null;
+    }
 }
diff --git a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java b/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java
deleted file mode 100644
index 1fb597b..0000000
--- a/java/src/com/android/inputmethod/compat/UserDictionaryCompatUtils.java
+++ /dev/null
@@ -1,57 +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.compat;
-
-import android.content.Context;
-import android.provider.UserDictionary.Words;
-
-import java.lang.reflect.Method;
-import java.util.Locale;
-
-public final class UserDictionaryCompatUtils {
-    // UserDictionary.Words#addWord(Context, String, int, String, Locale) was introduced
-    // in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
-    private static final Method METHOD_addWord = CompatUtils.getMethod(Words.class, "addWord",
-            Context.class, String.class, int.class, String.class, Locale.class);
-
-    @SuppressWarnings("deprecation")
-    public static void addWord(final Context context, final String word,
-            final int freq, final String shortcut, final Locale locale) {
-        if (hasNewerAddWord()) {
-            CompatUtils.invoke(Words.class, null, METHOD_addWord, context, word, freq, shortcut,
-                    locale);
-        } else {
-            // Fall back to the pre-JellyBean method.
-            final int localeType;
-            if (null == locale) {
-                localeType = Words.LOCALE_TYPE_ALL;
-            } else {
-                final Locale currentLocale = context.getResources().getConfiguration().locale;
-                if (locale.equals(currentLocale)) {
-                    localeType = Words.LOCALE_TYPE_CURRENT;
-                } else {
-                    localeType = Words.LOCALE_TYPE_ALL;
-                }
-            }
-            Words.addWord(context, word, freq, localeType);
-        }
-    }
-
-    public static final boolean hasNewerAddWord() {
-        return null != METHOD_addWord;
-    }
-}
diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
index 0f00be1..16260ab 100644
--- a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java
@@ -31,9 +31,6 @@
     private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod(
             View.class, "setPaddingRelative",
             int.class, int.class, int.class, int.class);
-    // Note that View.setElevation(float) has been introduced in API level 21.
-    private static final Method METHOD_setElevation = CompatUtils.getMethod(
-            View.class, "setElevation", float.class);
     // Note that View.setTextAlignment(int) has been introduced in API level 17.
     private static final Method METHOD_setTextAlignment = CompatUtils.getMethod(
             View.class, "setTextAlignment", int.class);
@@ -58,10 +55,6 @@
         CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom);
     }
 
-    public static void setElevation(final View view, final float elevation) {
-        CompatUtils.invoke(view, null, METHOD_setElevation, elevation);
-    }
-
     // These TEXT_ALIGNMENT_* constants have been introduced in API 17.
     public static final int TEXT_ALIGNMENT_INHERIT = 0;
     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
diff --git a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java
new file mode 100644
index 0000000..0c8e5b7
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.compat;
+
+import android.inputmethodservice.InputMethodService;
+import android.os.Build;
+import android.view.View;
+
+public class ViewOutlineProviderCompatUtils {
+    private ViewOutlineProviderCompatUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public interface InsetsUpdater {
+        public void setInsets(final InputMethodService.Insets insets);
+    }
+
+    private static final InsetsUpdater EMPTY_INSETS_UPDATER = new InsetsUpdater() {
+        @Override
+        public void setInsets(final InputMethodService.Insets insets) {}
+    };
+
+    public static InsetsUpdater setInsetsOutlineProvider(final View view) {
+        if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            return EMPTY_INSETS_UPDATER;
+        }
+        return ViewOutlineProviderCompatUtilsLXX.setInsetsOutlineProvider(view);
+    }
+}
diff --git a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java
new file mode 100644
index 0000000..5bbb5ce
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 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.compat;
+
+import android.annotation.TargetApi;
+import android.graphics.Outline;
+import android.inputmethodservice.InputMethodService;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
+
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+class ViewOutlineProviderCompatUtilsLXX {
+    private ViewOutlineProviderCompatUtilsLXX() {
+        // This utility class is not publicly instantiable.
+    }
+
+    static InsetsUpdater setInsetsOutlineProvider(final View view) {
+        final InsetsOutlineProvider provider = new InsetsOutlineProvider(view);
+        view.setOutlineProvider(provider);
+        return provider;
+    }
+
+    private static class InsetsOutlineProvider extends ViewOutlineProvider
+            implements InsetsUpdater {
+        private final View mView;
+        private static final int NO_DATA = -1;
+        private int mLastVisibleTopInsets = NO_DATA;
+
+        public InsetsOutlineProvider(final View view) {
+            mView = view;
+            view.setOutlineProvider(this);
+        }
+
+        @Override
+        public void setInsets(final InputMethodService.Insets insets) {
+            final int visibleTopInsets = insets.visibleTopInsets;
+            if (mLastVisibleTopInsets != visibleTopInsets) {
+                mLastVisibleTopInsets = visibleTopInsets;
+                mView.invalidateOutline();
+            }
+        }
+
+        @Override
+        public void getOutline(final View view, final Outline outline) {
+            if (mLastVisibleTopInsets == NO_DATA) {
+                // Call default implementation.
+                ViewOutlineProvider.BACKGROUND.getOutline(view, outline);
+                return;
+            }
+            // TODO: Revisit this when floating/resize keyboard is supported.
+            outline.setRect(
+                    view.getLeft(), mLastVisibleTopInsets, view.getRight(), view.getBottom());
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
index 3d294ac..ee142d8 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
@@ -120,9 +120,10 @@
             if (MetadataDbHelper.STATUS_DOWNLOADING == status) {
                 // The word list is still downloading. Cancel the download and revert the
                 // word list status to "available".
-                 manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
+                manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
                 MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
-            } else if (MetadataDbHelper.STATUS_AVAILABLE != status) {
+            } else if (MetadataDbHelper.STATUS_AVAILABLE != status
+                    && MetadataDbHelper.STATUS_RETRYING != status) {
                 // Should never happen
                 Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + "' : " + status
                         + " for an upgrade action. Fall back to download.");
@@ -171,6 +172,8 @@
 
             final long downloadId = UpdateHandler.registerDownloadRequest(manager, request, db,
                     mWordList.mId, mWordList.mVersion);
+            Log.i(TAG, String.format("Starting the dictionary download with version:"
+                            + " %d and Url: %s", mWordList.mVersion, uri));
             DebugLogUtils.l("Starting download of", uri, "with id", downloadId);
             PrivateLog.log("Starting download of " + uri + ", id : " + downloadId);
         }
@@ -325,8 +328,8 @@
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                     null == mWordList.mLocalFilename ? "" : mWordList.mLocalFilename,
                     mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
-                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
-                    mWordList.mFormatVersion);
+                    mWordList.mChecksum, mWordList.mRetryCount, mWordList.mFileSize,
+                    mWordList.mVersion, mWordList.mFormatVersion);
             PrivateLog.log("Insert 'available' record for " + mWordList.mDescription
                     + " and locale " + mWordList.mLocale);
             db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
@@ -374,9 +377,9 @@
             final ContentValues values = MetadataDbHelper.makeContentValues(0,
                     MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_INSTALLED,
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
-                    "", mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
-                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
-                    mWordList.mFormatVersion);
+                    "", mWordList.mRemoteFilename, mWordList.mLastUpdate,
+                    mWordList.mRawChecksum, mWordList.mChecksum, mWordList.mRetryCount,
+                    mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
             PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription
                     + " and locale " + mWordList.mLocale);
             db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
@@ -417,8 +420,8 @@
                     mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                     oldValues.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN),
                     mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mRawChecksum,
-                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
-                    mWordList.mFormatVersion);
+                    mWordList.mChecksum, mWordList.mRetryCount, mWordList.mFileSize,
+                    mWordList.mVersion, mWordList.mFormatVersion);
             PrivateLog.log("Updating record for " + mWordList.mDescription
                     + " and locale " + mWordList.mLocale);
             db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
diff --git a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
index 6d6c8f5..0fa72c3 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ButtonSwitcher.java
@@ -122,19 +122,23 @@
         mDeleteButton.setTranslationX(STATUS_DELETE == status ? 0 : width);
     }
 
+    // The helper method for {@link AnimatorListenerAdapter}.
+    void animateButtonIfStatusIsEqual(final View newButton, final int newStatus) {
+        if (newStatus != mStatus) return;
+        animateButton(newButton, ANIMATION_IN);
+    }
+
     private void animateButtonPosition(final int oldStatus, final int newStatus) {
         final View oldButton = getButton(oldStatus);
         final View newButton = getButton(newStatus);
         if (null != oldButton && null != newButton) {
             // Transition between two buttons : animate out, then in
-            animateButton(oldButton, ANIMATION_OUT).setListener(
-                    new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(final Animator animation) {
-                            if (newStatus != mStatus) return;
-                            animateButton(newButton, ANIMATION_IN);
-                        }
-                    });
+            animateButton(oldButton, ANIMATION_OUT).setListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(final Animator animation) {
+                    animateButtonIfStatusIsEqual(newButton, newStatus);
+                }
+            });
         } else if (null != oldButton) {
             animateButton(oldButton, ANIMATION_OUT);
         } else if (null != newButton) {
@@ -159,9 +163,8 @@
         if (ANIMATION_IN == direction) {
             button.setClickable(true);
             return button.animate().translationX(0);
-        } else {
-            button.setClickable(false);
-            return button.animate().translationX(outerX - innerX);
         }
+        button.setClickable(false);
+        return button.animate().translationX(outerX - innerX);
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java b/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java
index 3d0e29e..3cd822a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java
+++ b/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java
@@ -22,6 +22,8 @@
 public final class CommonPreferences {
     private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs";
 
+    public static final String PREF_FORCE_DOWNLOAD_DICT = "pref_key_force_download_dict";
+
     public static SharedPreferences getCommonPreferences(final Context context) {
         return context.getSharedPreferences(COMMON_PREFERENCES_NAME, 0);
     }
@@ -37,4 +39,14 @@
         editor.putBoolean(id, false);
         editor.apply();
     }
+
+    public static boolean isForceDownloadDict(Context context) {
+        return getCommonPreferences(context).getBoolean(PREF_FORCE_DOWNLOAD_DICT, false);
+    }
+
+    public static void setForceDownloadDict(Context context, boolean forceDownload) {
+        SharedPreferences.Editor editor = getCommonPreferences(context).edit();
+        editor.putBoolean(PREF_FORCE_DOWNLOAD_DICT, forceDownload);
+        editor.apply();
+    }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
index 1d84e58..7598520 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryDownloadProgressBar.java
@@ -148,7 +148,7 @@
             }
         }
 
-        private class UpdateHelper implements Runnable {
+        class UpdateHelper implements Runnable {
             private int mProgress;
             @Override
             public void run() {
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
index 8e02617..836340a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryListInterfaceState.java
@@ -32,7 +32,7 @@
  * in case some dictionaries appeared, disappeared, changed states etc.
  */
 public class DictionaryListInterfaceState {
-    private static class State {
+    static class State {
         public boolean mOpen = false;
         public int mStatus = MetadataDbHelper.STATUS_UNKNOWN;
     }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index f5bd84c..659fe5c 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
 
 import java.io.File;
@@ -255,10 +256,9 @@
                 if (null != dictFiles && dictFiles.size() > 0) {
                     PrivateLog.log("Returned " + dictFiles.size() + " files");
                     return new ResourcePathCursor(dictFiles);
-                } else {
-                    PrivateLog.log("No dictionary files for this URL");
-                    return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
                 }
+                PrivateLog.log("No dictionary files for this URL");
+                return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
             // V2_METADATA and V2_DATAFILE are not supported for query()
             default:
                 return null;
@@ -319,14 +319,13 @@
                 final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
                         R.raw.empty);
                 return afd;
-            } else {
-                final String localFilename =
-                        wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
-                final File f = getContext().getFileStreamPath(localFilename);
-                final ParcelFileDescriptor pfd =
-                        ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
-                return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
             }
+            final String localFilename =
+                    wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
+            final File f = getContext().getFileStreamPath(localFilename);
+            final ParcelFileDescriptor pfd =
+                    ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
+            return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
         } catch (FileNotFoundException e) {
             // No file : fall through and return null
         }
@@ -461,30 +460,32 @@
         final String wordlistId = uri.getLastPathSegment();
         final String clientId = getClientId(uri);
         final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);
-        if (null == wordList) return 0;
+        if (null == wordList) {
+            return 0;
+        }
         final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
         final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
         if (MetadataDbHelper.STATUS_DELETING == status) {
             UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
             return 1;
-        } else if (MetadataDbHelper.STATUS_INSTALLED == status) {
+        }
+        if (MetadataDbHelper.STATUS_INSTALLED == status) {
             final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
             if (QUERY_PARAMETER_FAILURE.equals(result)) {
-                UpdateHandler.markAsBroken(getContext(), clientId, wordlistId, version);
+                if (DEBUG) {
+                    Log.d(TAG,
+                            "Dictionary is broken, attempting to retry download & installation.");
+                }
+                UpdateHandler.markAsBrokenOrRetrying(getContext(), clientId, wordlistId, version);
             }
             final String localFilename =
                     wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
             final File f = getContext().getFileStreamPath(localFilename);
             // f.delete() returns true if the file was successfully deleted, false otherwise
-            if (f.delete()) {
-                return 1;
-            } else {
-                return 0;
-            }
-        } else {
-            Log.e(TAG, "Attempt to delete a file whose status is " + status);
-            return 0;
+            return f.delete() ? 1 : 0;
         }
+        Log.e(TAG, "Attempt to delete a file whose status is " + status);
+        return 0;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
index 41916b6..bbdf2a3 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
@@ -22,9 +22,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.IBinder;
+import android.util.Log;
 import android.widget.Toast;
 
+import com.android.inputmethod.latin.BinaryDictionaryFileDumper;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
 
 import java.util.Locale;
 import java.util.Random;
@@ -32,6 +35,8 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+
 /**
  * Service that handles background tasks for the dictionary provider.
  *
@@ -50,6 +55,8 @@
  *     to access, and mark the current state as such.
  */
 public final class DictionaryService extends Service {
+    private static final String TAG = DictionaryService.class.getSimpleName();
+
     /**
      * The package name, to use in the intent actions.
      */
@@ -76,19 +83,29 @@
      * How often, in milliseconds, we want to update the metadata. This is a
      * floor value; actually, it may happen several hours later, or even more.
      */
-    private static final long UPDATE_FREQUENCY = TimeUnit.DAYS.toMillis(4);
+    private static final long UPDATE_FREQUENCY_MILLIS = TimeUnit.DAYS.toMillis(4);
 
     /**
      * We are waked around midnight, local time. We want to wake between midnight and 6 am,
      * roughly. So use a random time between 0 and this delay.
      */
-    private static final int MAX_ALARM_DELAY = (int)TimeUnit.HOURS.toMillis(6);
+    private static final int MAX_ALARM_DELAY_MILLIS = (int)TimeUnit.HOURS.toMillis(6);
 
     /**
      * How long we consider a "very long time". If no update took place in this time,
      * the content provider will trigger an update in the background.
      */
-    private static final long VERY_LONG_TIME = TimeUnit.DAYS.toMillis(14);
+    private static final long VERY_LONG_TIME_MILLIS = TimeUnit.DAYS.toMillis(14);
+
+    /**
+     * After starting a download, how long we wait before considering it may be stuck. After this
+     * period is elapsed, if the keyboard tries to download again, then we cancel and re-register
+     * the request; if it's within this time, we just leave it be.
+     * It's important to note that we do not re-submit the request merely because the time is up.
+     * This is only to decide whether to cancel the old one and re-requesting when the keyboard
+     * fires a new request for the same data.
+     */
+    public static final long NO_CANCEL_DOWNLOAD_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(30);
 
     /**
      * An executor that serializes tasks given to it.
@@ -145,9 +162,14 @@
             final int startId) {
         final DictionaryService self = this;
         if (SHOW_DOWNLOAD_TOAST_INTENT_ACTION.equals(intent.getAction())) {
-            // This is a UI action, it can't be run in another thread
-            showStartDownloadingToast(this, LocaleUtils.constructLocaleFromString(
-                    intent.getStringExtra(LOCALE_INTENT_ARGUMENT)));
+            final String localeString = intent.getStringExtra(LOCALE_INTENT_ARGUMENT);
+            if (localeString == null) {
+                Log.e(TAG, "Received " + intent.getAction() + " without locale; skipped");
+            } else {
+                // This is a UI action, it can't be run in another thread
+                showStartDownloadingToast(
+                        this, LocaleUtils.constructLocaleFromString(localeString));
+            }
         } else {
             // If it's a command that does not require UI, arrange for the work to be done on a
             // separate thread, so that we can return right away. The executor will spawn a thread
@@ -169,15 +191,28 @@
         return Service.START_REDELIVER_INTENT;
     }
 
-    private static void dispatchBroadcast(final Context context, final Intent intent) {
+    static void dispatchBroadcast(final Context context, final Intent intent) {
         if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) {
+            // Do not force download dictionaries on date change updates.
+            CommonPreferences.setForceDownloadDict(context, false);
             // This happens when the date of the device changes. This normally happens
             // at midnight local time, but it may happen if the user changes the date
             // by hand or something similar happens.
             checkTimeAndMaybeSetupUpdateAlarm(context);
         } else if (DictionaryPackConstants.UPDATE_NOW_INTENT_ACTION.equals(intent.getAction())) {
             // Intent to trigger an update now.
-            UpdateHandler.tryUpdate(context, false);
+            UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context));
+        } else if (DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION.equals(
+                intent.getAction())) {
+            // Enable force download of dictionaries irrespective of wifi or metered connection.
+            CommonPreferences.setForceDownloadDict(context, true);
+
+            // Initialize the client Db.
+            final String mClientId = context.getString(R.string.dictionary_pack_client_id);
+            BinaryDictionaryFileDumper.initializeClientRecordHelper(context, mClientId);
+
+            // Updates the metadata and the download the dictionaries.
+            UpdateHandler.tryUpdate(context, true);
         } else {
             UpdateHandler.downloadFinished(context, intent);
         }
@@ -188,16 +223,16 @@
      */
     private static void checkTimeAndMaybeSetupUpdateAlarm(final Context context) {
         // Of all clients, if the one that hasn't been updated for the longest
-        // is still more recent than UPDATE_FREQUENCY, do nothing.
-        if (!isLastUpdateAtLeastThisOld(context, UPDATE_FREQUENCY)) return;
+        // is still more recent than UPDATE_FREQUENCY_MILLIS, do nothing.
+        if (!isLastUpdateAtLeastThisOld(context, UPDATE_FREQUENCY_MILLIS)) return;
 
         PrivateLog.log("Date changed - registering alarm");
         AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
 
-        // Best effort to wake between midnight and MAX_ALARM_DELAY in the morning.
+        // Best effort to wake between midnight and MAX_ALARM_DELAY_MILLIS in the morning.
         // It doesn't matter too much if this is very inexact.
         final long now = System.currentTimeMillis();
-        final long alarmTime = now + new Random().nextInt(MAX_ALARM_DELAY);
+        final long alarmTime = now + new Random().nextInt(MAX_ALARM_DELAY_MILLIS);
         final Intent updateIntent = new Intent(DictionaryPackConstants.UPDATE_NOW_INTENT_ACTION);
         final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                 updateIntent, PendingIntent.FLAG_CANCEL_CURRENT);
@@ -223,18 +258,19 @@
     /**
      * Refreshes data if it hasn't been refreshed in a very long time.
      *
-     * This will check the last update time, and if it's been more than VERY_LONG_TIME,
+     * This will check the last update time, and if it's been more than VERY_LONG_TIME_MILLIS,
      * update metadata now - and possibly take subsequent update actions.
      */
     public static void updateNowIfNotUpdatedInAVeryLongTime(final Context context) {
-        if (!isLastUpdateAtLeastThisOld(context, VERY_LONG_TIME)) return;
-        UpdateHandler.tryUpdate(context, false);
+        if (!isLastUpdateAtLeastThisOld(context, VERY_LONG_TIME_MILLIS)) return;
+        UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context));
     }
 
     /**
      * Shows a toast informing the user that an automatic dictionary download is starting.
      */
-    private static void showStartDownloadingToast(final Context context, final Locale locale) {
+    private static void showStartDownloadingToast(final Context context,
+            @Nonnull final Locale locale) {
         final String toastText = String.format(
                 context.getString(R.string.toast_downloading_suggestions),
                 locale.getDisplayName());
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
index 4366348..284032b 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsActivity.java
@@ -18,7 +18,9 @@
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
+import android.annotation.TargetApi;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceActivity;
 
@@ -44,8 +46,8 @@
         return modIntent;
     }
 
-    // TODO: Uncomment the override annotation once we start using SDK version 19.
-    // @Override
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    @Override
     public boolean isValidFragment(String fragmentName) {
         return FragmentUtils.isValidFragment(fragmentName);
     }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index 11982fa..88ea4e6 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.inputmethod.dictionarypack;
 
+import com.android.inputmethod.latin.common.LocaleUtils;
+
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -26,12 +28,12 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -105,16 +107,27 @@
 
     @Override
     public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
-        final String metadataUri =
-                MetadataDbHelper.getMetadataUriAsString(getActivity(), mClientId);
-        // We only add the "Refresh" button if we have a non-empty URL to refresh from. If the
-        // URL is empty, of course we can't refresh so it makes no sense to display this.
-        if (!TextUtils.isEmpty(metadataUri)) {
-            mUpdateNowMenu =
-                    menu.add(Menu.NONE, MENU_UPDATE_NOW, 0, R.string.check_for_updates_now);
-            mUpdateNowMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-            refreshNetworkState();
-        }
+        new AsyncTask<Void, Void, String>() {
+            @Override
+            protected String doInBackground(Void... params) {
+                return MetadataDbHelper.getMetadataUriAsString(getActivity(), mClientId);
+            }
+
+            @Override
+            protected void onPostExecute(String metadataUri) {
+                // We only add the "Refresh" button if we have a non-empty URL to refresh from. If
+                // the URL is empty, of course we can't refresh so it makes no sense to display
+                // this.
+                if (!TextUtils.isEmpty(metadataUri)) {
+                    if (mUpdateNowMenu == null) {
+                        mUpdateNowMenu = menu.add(Menu.NONE, MENU_UPDATE_NOW, 0,
+                                        R.string.check_for_updates_now);
+                        mUpdateNowMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                    }
+                    refreshNetworkState();
+                }
+            }
+        }.execute();
     }
 
     @Override
@@ -123,18 +136,25 @@
         mChangedSettings = false;
         UpdateHandler.registerUpdateEventListener(this);
         final Activity activity = getActivity();
-        if (!MetadataDbHelper.isClientKnown(activity, mClientId)) {
-            Log.i(TAG, "Unknown dictionary pack client: " + mClientId + ". Requesting info.");
-            final Intent unknownClientBroadcast =
-                    new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT);
-            unknownClientBroadcast.putExtra(
-                    DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId);
-            activity.sendBroadcast(unknownClientBroadcast);
-        }
         final IntentFilter filter = new IntentFilter();
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         getActivity().registerReceiver(mConnectivityChangedReceiver, filter);
         refreshNetworkState();
+
+        new Thread("onResume") {
+            @Override
+            public void run() {
+                if (!MetadataDbHelper.isClientKnown(activity, mClientId)) {
+                    Log.i(TAG, "Unknown dictionary pack client: " + mClientId
+                            + ". Requesting info.");
+                    final Intent unknownClientBroadcast =
+                            new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT);
+                    unknownClientBroadcast.putExtra(
+                            DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId);
+                    activity.sendBroadcast(unknownClientBroadcast);
+                }
+            }
+        }.start();
     }
 
     @Override
@@ -203,25 +223,19 @@
     @Override
     public void updateCycleCompleted() {}
 
-    private void refreshNetworkState() {
+    void refreshNetworkState() {
         NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
         boolean isConnected = null == info ? false : info.isConnected();
         if (null != mUpdateNowMenu) mUpdateNowMenu.setEnabled(isConnected);
     }
 
-    private void refreshInterface() {
+    void refreshInterface() {
         final Activity activity = getActivity();
         if (null == activity) return;
-        final long lastUpdateDate =
-                MetadataDbHelper.getLastUpdateDateForClient(getActivity(), mClientId);
         final PreferenceGroup prefScreen = getPreferenceScreen();
         final Collection<? extends Preference> prefList =
                 createInstalledDictSettingsCollection(mClientId);
 
-        final String updateNowSummary = getString(R.string.last_update) + " "
-                + DateUtils.formatDateTime(activity, lastUpdateDate,
-                        DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
-
         activity.runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -239,14 +253,14 @@
             });
     }
 
-    private Preference createErrorMessage(final Activity activity, final int messageResource) {
+    private static Preference createErrorMessage(final Activity activity, final int messageResource) {
         final Preference message = new Preference(activity);
         message.setTitle(messageResource);
         message.setEnabled(false);
         return message;
     }
 
-    private void removeAnyDictSettings(final PreferenceGroup prefGroup) {
+    static void removeAnyDictSettings(final PreferenceGroup prefGroup) {
         for (int i = prefGroup.getPreferenceCount() - 1; i >= 0; --i) {
             prefGroup.removePreference(prefGroup.getPreference(i));
         }
@@ -276,7 +290,7 @@
                 .appendQueryParameter(DictionaryProvider.QUERY_PARAMETER_PROTOCOL_VERSION, "2")
                 .build();
         final Activity activity = getActivity();
-        final Cursor cursor = null == activity ? null
+        final Cursor cursor = (null == activity) ? null
                 : activity.getContentResolver().query(contentUri, null, null, null, null);
 
         if (null == cursor) {
@@ -289,61 +303,57 @@
                 final ArrayList<Preference> result = new ArrayList<>();
                 result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
                 return result;
-            } else {
-                final String systemLocaleString = Locale.getDefault().toString();
-                final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
-                final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
-                final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
-                final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
-                final int descriptionIndex =
-                        cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
-                final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
-                final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
-                do {
-                    final String wordlistId = cursor.getString(idIndex);
-                    final int version = cursor.getInt(versionIndex);
-                    final String localeString = cursor.getString(localeIndex);
-                    final Locale locale = new Locale(localeString);
-                    final String description = cursor.getString(descriptionIndex);
-                    final int status = cursor.getInt(statusIndex);
-                    final int matchLevel =
-                            LocaleUtils.getMatchLevel(systemLocaleString, localeString);
-                    final String matchLevelString =
-                            LocaleUtils.getMatchLevelSortedString(matchLevel);
-                    final int filesize = cursor.getInt(filesizeIndex);
-                    // The key is sorted in lexicographic order, according to the match level, then
-                    // the description.
-                    final String key = matchLevelString + "." + description + "." + wordlistId;
-                    final WordListPreference existingPref = prefMap.get(key);
-                    if (null == existingPref || existingPref.hasPriorityOver(status)) {
-                        final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
-                        final WordListPreference pref;
-                        if (null != oldPreference
-                                && oldPreference.mVersion == version
-                                && oldPreference.hasStatus(status)
-                                && oldPreference.mLocale.equals(locale)) {
-                            // If the old preference has all the new attributes, reuse it. Ideally,
-                            // we should reuse the old pref even if its status is different and call
-                            // setStatus here, but setStatus calls Preference#setSummary() which
-                            // needs to be done on the UI thread and we're not on the UI thread
-                            // here. We could do all this work on the UI thread, but in this case
-                            // it's probably lighter to stay on a background thread and throw this
-                            // old preference out.
-                            pref = oldPreference;
-                        } else {
-                            // Otherwise, discard it and create a new one instead.
-                            // TODO: when the status is different from the old one, we need to
-                            // animate the old one out before animating the new one in.
-                            pref = new WordListPreference(activity, mDictionaryListInterfaceState,
-                                    mClientId, wordlistId, version, locale, description, status,
-                                    filesize);
-                        }
-                        prefMap.put(key, pref);
-                    }
-                } while (cursor.moveToNext());
-                mCurrentPreferenceMap = prefMap;
-                return prefMap.values();
             }
+            final String systemLocaleString = Locale.getDefault().toString();
+            final TreeMap<String, WordListPreference> prefMap = new TreeMap<>();
+            final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
+            final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
+            final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
+            final int descriptionIndex = cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
+            final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
+            final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
+            do {
+                final String wordlistId = cursor.getString(idIndex);
+                final int version = cursor.getInt(versionIndex);
+                final String localeString = cursor.getString(localeIndex);
+                final Locale locale = new Locale(localeString);
+                final String description = cursor.getString(descriptionIndex);
+                final int status = cursor.getInt(statusIndex);
+                final int matchLevel = LocaleUtils.getMatchLevel(systemLocaleString, localeString);
+                final String matchLevelString = LocaleUtils.getMatchLevelSortedString(matchLevel);
+                final int filesize = cursor.getInt(filesizeIndex);
+                // The key is sorted in lexicographic order, according to the match level, then
+                // the description.
+                final String key = matchLevelString + "." + description + "." + wordlistId;
+                final WordListPreference existingPref = prefMap.get(key);
+                if (null == existingPref || existingPref.hasPriorityOver(status)) {
+                    final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
+                    final WordListPreference pref;
+                    if (null != oldPreference
+                            && oldPreference.mVersion == version
+                            && oldPreference.hasStatus(status)
+                            && oldPreference.mLocale.equals(locale)) {
+                        // If the old preference has all the new attributes, reuse it. Ideally,
+                        // we should reuse the old pref even if its status is different and call
+                        // setStatus here, but setStatus calls Preference#setSummary() which
+                        // needs to be done on the UI thread and we're not on the UI thread
+                        // here. We could do all this work on the UI thread, but in this case
+                        // it's probably lighter to stay on a background thread and throw this
+                        // old preference out.
+                        pref = oldPreference;
+                    } else {
+                        // Otherwise, discard it and create a new one instead.
+                        // TODO: when the status is different from the old one, we need to
+                        // animate the old one out before animating the new one in.
+                        pref = new WordListPreference(activity, mDictionaryListInterfaceState,
+                                mClientId, wordlistId, version, locale, description, status,
+                                filesize);
+                    }
+                    prefMap.put(key, pref);
+                }
+            } while (cursor.moveToNext());
+            mCurrentPreferenceMap = prefMap;
+            return prefMap.values();
         } finally {
             cursor.close();
         }
@@ -384,8 +394,13 @@
     private void cancelRefresh() {
         UpdateHandler.unregisterUpdateEventListener(this);
         final Context context = getActivity();
-        UpdateHandler.cancelUpdate(context, mClientId);
-        stopLoadingAnimation();
+        new Thread("cancelByHand") {
+            @Override
+            public void run() {
+                UpdateHandler.cancelUpdate(context, mClientId);
+                stopLoadingAnimation();
+            }
+        }.start();
     }
 
     private void startLoadingAnimation() {
@@ -396,26 +411,28 @@
         if (null != mUpdateNowMenu) mUpdateNowMenu.setTitle(R.string.cancel);
     }
 
-    private void stopLoadingAnimation() {
+    void stopLoadingAnimation() {
         final View preferenceView = getView();
         final Activity activity = getActivity();
         if (null == activity) return;
+        final View loadingView = mLoadingView;
+        final MenuItem updateNowMenu = mUpdateNowMenu;
         activity.runOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    mLoadingView.setVisibility(View.GONE);
-                    preferenceView.setVisibility(View.VISIBLE);
-                    mLoadingView.startAnimation(AnimationUtils.loadAnimation(
-                            getActivity(), android.R.anim.fade_out));
-                    preferenceView.startAnimation(AnimationUtils.loadAnimation(
-                            getActivity(), android.R.anim.fade_in));
-                    // The menu is created by the framework asynchronously after the activity,
-                    // which means it's possible to have the activity running but the menu not
-                    // created yet - hence the necessity for a null check here.
-                    if (null != mUpdateNowMenu) {
-                        mUpdateNowMenu.setTitle(R.string.check_for_updates_now);
-                    }
+            @Override
+            public void run() {
+                loadingView.setVisibility(View.GONE);
+                preferenceView.setVisibility(View.VISIBLE);
+                loadingView.startAnimation(AnimationUtils.loadAnimation(
+                        activity, android.R.anim.fade_out));
+                preferenceView.startAnimation(AnimationUtils.loadAnimation(
+                        activity, android.R.anim.fade_in));
+                // The menu is created by the framework asynchronously after the activity,
+                // which means it's possible to have the activity running but the menu not
+                // created yet - hence the necessity for a null check here.
+                if (null != updateNowMenu) {
+                    updateNowMenu.setTitle(R.string.check_for_updates_now);
                 }
-            });
+            }
+        });
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadIdAndStartDate.java b/java/src/com/android/inputmethod/dictionarypack/DownloadIdAndStartDate.java
new file mode 100644
index 0000000..6247a15
--- /dev/null
+++ b/java/src/com/android/inputmethod/dictionarypack/DownloadIdAndStartDate.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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.dictionarypack;
+
+/**
+ * A simple container of download ID and download start date.
+ */
+public class DownloadIdAndStartDate {
+    public final long mId;
+    public final long mStartDate;
+    public DownloadIdAndStartDate(final long id, final long startDate) {
+        mId = id;
+        mStartDate = startDate;
+    }
+}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
index d3c0a91..91ed673 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DownloadOverMeteredDialog.java
@@ -24,9 +24,11 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
 
-import java.util.Locale;
+import javax.annotation.Nullable;
 
 /**
  * This implements the dialog for asking the user whether it's okay to download dictionaries over
@@ -52,22 +54,30 @@
         setTexts(localeString, size);
     }
 
-    private void setTexts(final String localeString, final long size) {
+    private void setTexts(@Nullable final String localeString, final long size) {
         final String promptFormat = getString(R.string.should_download_over_metered_prompt);
         final String allowButtonFormat = getString(R.string.download_over_metered);
-        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
-        final String language = (null == locale ? "" : locale.getDisplayLanguage());
+        final String language = (null == localeString) ? ""
+                : LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage();
         final TextView prompt = (TextView)findViewById(R.id.download_over_metered_prompt);
         prompt.setText(Html.fromHtml(String.format(promptFormat, language)));
         final Button allowButton = (Button)findViewById(R.id.allow_button);
         allowButton.setText(String.format(allowButtonFormat, ((float)size)/(1024*1024)));
     }
 
+    // This method is externally referenced from layout/download_over_metered.xml using onClick
+    // attribute of Button.
+    @ExternallyReferenced
+    @SuppressWarnings("unused")
     public void onClickDeny(final View v) {
         UpdateHandler.setDownloadOverMeteredSetting(this, false);
         finish();
     }
 
+    // This method is externally referenced from layout/download_over_metered.xml using onClick
+    // attribute of Button.
+    @ExternallyReferenced
+    @SuppressWarnings("unused")
     public void onClickAllow(final View v) {
         UpdateHandler.setDownloadOverMeteredSetting(this, true);
         UpdateHandler.installIfNeverRequested(this, mClientId, mWordListToDownload,
diff --git a/java/src/com/android/inputmethod/dictionarypack/LocaleUtils.java b/java/src/com/android/inputmethod/dictionarypack/LocaleUtils.java
deleted file mode 100644
index 4f0805c..0000000
--- a/java/src/com/android/inputmethod/dictionarypack/LocaleUtils.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2011 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.dictionarypack;
-
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.Locale;
-
-/**
- * A class to help with handling Locales in string form.
- *
- * This file has the same meaning and features (and shares all of its code) with the one with the
- * same name in Latin IME. They need to be kept synchronized; for any update/bugfix to
- * this file, consider also updating/fixing the version in Latin IME.
- */
-public final class LocaleUtils {
-    private LocaleUtils() {
-        // Intentional empty constructor for utility class.
-    }
-
-    // Locale match level constants.
-    // A higher level of match is guaranteed to have a higher numerical value.
-    // Some room is left within constants to add match cases that may arise necessary
-    // in the future, for example differentiating between the case where the countries
-    // are both present and different, and the case where one of the locales does not
-    // specify the countries. This difference is not needed now.
-
-    // Nothing matches.
-    public static final int LOCALE_NO_MATCH = 0;
-    // The languages matches, but the country are different. Or, the reference locale requires a
-    // country and the tested locale does not have one.
-    public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
-    // The languages and country match, but the variants are different. Or, the reference locale
-    // requires a variant and the tested locale does not have one.
-    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
-    // The required locale is null or empty so it will accept anything, and the tested locale
-    // is non-null and non-empty.
-    public static final int LOCALE_ANY_MATCH = 10;
-    // The language matches, and the tested locale specifies a country but the reference locale
-    // does not require one.
-    public static final int LOCALE_LANGUAGE_MATCH = 15;
-    // The language and the country match, and the tested locale specifies a variant but the
-    // reference locale does not require one.
-    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
-    // The compared locales are fully identical. This is the best match level.
-    public static final int LOCALE_FULL_MATCH = 30;
-
-    // The level at which a match is "normally" considered a locale match with standard algorithms.
-    // Don't use this directly, use #isMatch to test.
-    private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
-
-    // Make this match the maximum match level. If this evolves to have more than 2 digits
-    // when written in base 10, also adjust the getMatchLevelSortedString method.
-    private static final int MATCH_LEVEL_MAX = 30;
-
-    /**
-     * Return how well a tested locale matches a reference locale.
-     *
-     * This will check the tested locale against the reference locale and return a measure of how
-     * a well it matches the reference. The general idea is that the tested locale has to match
-     * every specified part of the required locale. A full match occur when they are equal, a
-     * partial match when the tested locale agrees with the reference locale but is more specific,
-     * and a difference when the tested locale does not comply with all requirements from the
-     * reference locale.
-     * In more detail, if the reference locale specifies at least a language and the testedLocale
-     * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
-     * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
-     * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
-     * tested locale agree on the language, but not on the country,
-     * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
-     * and LOCALE_LANGUAGE_MATCH otherwise.
-     * If they agree on both the language and the country, but not on the variant,
-     * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
-     * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
-     * LOCALE_FULL_MATCH is returned.
-     * Examples:
-     * en <=> en_US  => LOCALE_LANGUAGE_MATCH
-     * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
-     * en_US_POSIX <=> en_US_Android  =>  LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
-     * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
-     * sp_US <=> en_US  =>  LOCALE_NO_MATCH
-     * de <=> de  => LOCALE_FULL_MATCH
-     * en_US <=> en_US => LOCALE_FULL_MATCH
-     * "" <=> en_US => LOCALE_ANY_MATCH
-     *
-     * @param referenceLocale the reference locale to test against.
-     * @param testedLocale the locale to test.
-     * @return a constant that measures how well the tested locale matches the reference locale.
-     */
-    public static int getMatchLevel(final String referenceLocale, final String testedLocale) {
-        if (TextUtils.isEmpty(referenceLocale)) {
-            return TextUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
-        }
-        if (null == testedLocale) return LOCALE_NO_MATCH;
-        final String[] referenceParams = referenceLocale.split("_", 3);
-        final String[] testedParams = testedLocale.split("_", 3);
-        // By spec of String#split, [0] cannot be null and length cannot be 0.
-        if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
-        switch (referenceParams.length) {
-        case 1:
-            return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
-        case 2:
-            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (!referenceParams[1].equals(testedParams[1]))
-                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
-            return LOCALE_FULL_MATCH;
-        case 3:
-            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (!referenceParams[1].equals(testedParams[1]))
-                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
-            if (!referenceParams[2].equals(testedParams[2]))
-                return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
-            return LOCALE_FULL_MATCH;
-        }
-        // It should be impossible to come here
-        return LOCALE_NO_MATCH;
-    }
-
-    /**
-     * Return a string that represents this match level, with better matches first.
-     *
-     * The strings are sorted in lexicographic order: a better match will always be less than
-     * a worse match when compared together.
-     */
-    public static String getMatchLevelSortedString(final int matchLevel) {
-        // This works because the match levels are 0~99 (actually 0~30)
-        // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
-        return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
-    }
-
-    /**
-     * Find out whether a match level should be considered a match.
-     *
-     * This method takes a match level as returned by the #getMatchLevel method, and returns whether
-     * it should be considered a match in the usual sense with standard Locale functions.
-     *
-     * @param level the match level, as returned by getMatchLevel.
-     * @return whether this is a match or not.
-     */
-    public static boolean isMatch(final int level) {
-        return LOCALE_MATCH <= level;
-    }
-
-    /**
-     * Sets the system locale for this process.
-     *
-     * @param res the resources to use. Pass current resources.
-     * @param newLocale the locale to change to.
-     * @return the old locale.
-     */
-    public static Locale setSystemLocale(final Resources res, final Locale newLocale) {
-        final Configuration conf = res.getConfiguration();
-        final Locale saveLocale = conf.locale;
-        conf.locale = newLocale;
-        res.updateConfiguration(conf, res.getDisplayMetrics());
-        return saveLocale;
-    }
-
-    private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
-
-    /**
-     * Creates a locale from a string specification.
-     */
-    public static Locale constructLocaleFromString(final String localeStr) {
-        if (localeStr == null)
-            return null;
-        synchronized (sLocaleCache) {
-            if (sLocaleCache.containsKey(localeStr))
-                return sLocaleCache.get(localeStr);
-            Locale retval = null;
-            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/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 17dd781..a2789cc 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -47,10 +47,14 @@
     // used to identify the versions for upgrades. This should never change going forward.
     private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
     // The current database version.
-    private static final int CURRENT_METADATA_DATABASE_VERSION = 9;
+    // This MUST be increased every time the dictionary pack metadata URL changes.
+    private static final int CURRENT_METADATA_DATABASE_VERSION = 14;
 
     private final static long NOT_A_DOWNLOAD_ID = -1;
 
+    // The number of retries allowed when attempting to download a broken dictionary.
+    public static final int DICTIONARY_RETRY_THRESHOLD = 2;
+
     public static final String METADATA_TABLE_NAME = "pendingUpdates";
     static final String CLIENT_TABLE_NAME = "clients";
     public static final String PENDINGID_COLUMN = "pendingid"; // Download Manager ID
@@ -68,7 +72,8 @@
     public static final String FORMATVERSION_COLUMN = "formatversion";
     public static final String FLAGS_COLUMN = "flags";
     public static final String RAW_CHECKSUM_COLUMN = "rawChecksum";
-    public static final int COLUMN_COUNT = 14;
+    public static final String RETRY_COUNT_COLUMN = "remainingRetries";
+    public static final int COLUMN_COUNT = 15;
 
     private static final String CLIENT_CLIENT_ID_COLUMN = "clientid";
     private static final String CLIENT_METADATA_URI_COLUMN = "uri";
@@ -98,6 +103,8 @@
     // Deleting: the user marked this word list to be deleted, but it has not been yet because
     // Latin IME is not up yet.
     public static final int STATUS_DELETING = 5;
+    // Retry: dictionary got corrupted, so an attempt must be done to download & install it again.
+    public static final int STATUS_RETRYING = 6;
 
     // Types, for storing in the TYPE_COLUMN
     // This is metadata about what is available.
@@ -124,6 +131,7 @@
             + FORMATVERSION_COLUMN + " INTEGER, "
             + FLAGS_COLUMN + " INTEGER, "
             + RAW_CHECKSUM_COLUMN + " TEXT,"
+            + RETRY_COUNT_COLUMN + " INTEGER, "
             + "PRIMARY KEY (" + WORDLISTID_COLUMN + "," + VERSION_COLUMN + "));";
     private static final String METADATA_CREATE_CLIENT_TABLE =
             "CREATE TABLE IF NOT EXISTS " + CLIENT_TABLE_NAME + " ("
@@ -140,7 +148,7 @@
             STATUS_COLUMN, WORDLISTID_COLUMN, LOCALE_COLUMN, DESCRIPTION_COLUMN,
             LOCAL_FILENAME_COLUMN, REMOTE_FILENAME_COLUMN, DATE_COLUMN, CHECKSUM_COLUMN,
             FILESIZE_COLUMN, VERSION_COLUMN, FORMATVERSION_COLUMN, FLAGS_COLUMN,
-            RAW_CHECKSUM_COLUMN };
+            RAW_CHECKSUM_COLUMN, RETRY_COUNT_COLUMN };
     // List of all client table columns.
     static final String[] CLIENT_TABLE_COLUMNS = { CLIENT_CLIENT_ID_COLUMN,
             CLIENT_METADATA_URI_COLUMN, CLIENT_PENDINGID_COLUMN, FLAGS_COLUMN };
@@ -219,7 +227,7 @@
         createClientTable(db);
     }
 
-    private void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db, final String clientId) {
+    private static void addRawChecksumColumnUnlessPresent(final SQLiteDatabase db) {
         try {
             db.execSQL("SELECT " + RAW_CHECKSUM_COLUMN + " FROM "
                     + METADATA_TABLE_NAME + " LIMIT 0;");
@@ -230,6 +238,17 @@
         }
     }
 
+    private static void addRetryCountColumnUnlessPresent(final SQLiteDatabase db) {
+        try {
+            db.execSQL("SELECT " + RETRY_COUNT_COLUMN + " FROM "
+                    + METADATA_TABLE_NAME + " LIMIT 0;");
+        } catch (SQLiteException e) {
+            Log.i(TAG, "No " + RETRY_COUNT_COLUMN + " column : creating it");
+            db.execSQL("ALTER TABLE " + METADATA_TABLE_NAME + " ADD COLUMN "
+                    + RETRY_COUNT_COLUMN + " INTEGER DEFAULT " + DICTIONARY_RETRY_THRESHOLD + ";");
+        }
+    }
+
     /**
      * Upgrade the database. Upgrade from version 3 is supported.
      * Version 3 has a DB named METADATA_DATABASE_NAME_STEM containing a table METADATA_TABLE_NAME.
@@ -245,6 +264,8 @@
      */
     @Override
     public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
+        // Allow automatic download of dictionaries on upgrading the database.
+        CommonPreferences.setForceDownloadDict(mContext, true);
         if (METADATA_DATABASE_INITIAL_VERSION == oldVersion
                 && METADATA_DATABASE_VERSION_WITH_CLIENTID <= newVersion
                 && CURRENT_METADATA_DATABASE_VERSION >= newVersion) {
@@ -280,7 +301,14 @@
         // strengthen the system against corrupted dictionary files.
         // The most secure way to upgrade a database is to just test for the column presence, and
         // add it if it's not there.
-        addRawChecksumColumnUnlessPresent(db, mClientId);
+        addRawChecksumColumnUnlessPresent(db);
+
+        // A retry count column that did not exist in the previous versions was added that
+        // corresponds to the number of download & installation attempts that have been made
+        // in order to strengthen the system recovery from corrupted dictionary files.
+        // The most secure way to upgrade a database is to just test for the column presence, and
+        // add it if it's not there.
+        addRetryCountColumnUnlessPresent(db);
     }
 
     /**
@@ -408,18 +436,18 @@
      *
      * @param context a context instance to open the database on
      * @param uri the URI to retrieve the metadata download ID of
-     * @return the metadata download ID, or NOT_AN_ID if no download is in progress
+     * @return the download id and start date, or null if the URL is not known
      */
-    public static long getMetadataDownloadIdForURI(final Context context,
-            final String uri) {
+    public static DownloadIdAndStartDate getMetadataDownloadIdAndStartDateForURI(
+            final Context context, final String uri) {
         SQLiteDatabase defaultDb = getDb(context, null);
         final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
-                new String[] { CLIENT_PENDINGID_COLUMN },
+                new String[] { CLIENT_PENDINGID_COLUMN, CLIENT_LAST_UPDATE_DATE_COLUMN },
                 CLIENT_METADATA_URI_COLUMN + " = ?", new String[] { uri },
                 null, null, null, null);
         try {
-            if (!cursor.moveToFirst()) return UpdateHandler.NOT_AN_ID;
-            return cursor.getInt(0); // Only one column, return it
+            if (!cursor.moveToFirst()) return null;
+            return new DownloadIdAndStartDate(cursor.getInt(0), cursor.getLong(1));
         } finally {
             cursor.close();
         }
@@ -452,8 +480,8 @@
     public static ContentValues makeContentValues(final int pendingId, final int type,
             final int status, final String wordlistId, final String locale,
             final String description, final String filename, final String url, final long date,
-            final String rawChecksum, final String checksum, final long filesize, final int version,
-            final int formatVersion) {
+            final String rawChecksum, final String checksum, final int retryCount,
+            final long filesize, final int version, final int formatVersion) {
         final ContentValues result = new ContentValues(COLUMN_COUNT);
         result.put(PENDINGID_COLUMN, pendingId);
         result.put(TYPE_COLUMN, type);
@@ -465,6 +493,7 @@
         result.put(REMOTE_FILENAME_COLUMN, url);
         result.put(DATE_COLUMN, date);
         result.put(RAW_CHECKSUM_COLUMN, rawChecksum);
+        result.put(RETRY_COUNT_COLUMN, retryCount);
         result.put(CHECKSUM_COLUMN, checksum);
         result.put(FILESIZE_COLUMN, filesize);
         result.put(VERSION_COLUMN, version);
@@ -502,6 +531,9 @@
         if (null == result.get(DATE_COLUMN)) result.put(DATE_COLUMN, 0);
         // Raw checksum unknown unless specified
         if (null == result.get(RAW_CHECKSUM_COLUMN)) result.put(RAW_CHECKSUM_COLUMN, "");
+        // Retry column 0 unless specified
+        if (null == result.get(RETRY_COUNT_COLUMN)) result.put(RETRY_COUNT_COLUMN,
+                DICTIONARY_RETRY_THRESHOLD);
         // Checksum unknown unless specified
         if (null == result.get(CHECKSUM_COLUMN)) result.put(CHECKSUM_COLUMN, "");
         // No filesize unless specified
@@ -551,6 +583,7 @@
             putIntResult(result, cursor, DATE_COLUMN);
             putStringResult(result, cursor, RAW_CHECKSUM_COLUMN);
             putStringResult(result, cursor, CHECKSUM_COLUMN);
+            putIntResult(result, cursor, RETRY_COUNT_COLUMN);
             putIntResult(result, cursor, FILESIZE_COLUMN);
             putIntResult(result, cursor, VERSION_COLUMN);
             putIntResult(result, cursor, FORMATVERSION_COLUMN);
@@ -676,8 +709,16 @@
             final String id, final int version) {
         final Cursor cursor = db.query(METADATA_TABLE_NAME,
                 METADATA_TABLE_COLUMNS,
-                WORDLISTID_COLUMN + "= ? AND " + VERSION_COLUMN + "= ?",
-                new String[] { id, Integer.toString(version) }, null, null, null);
+                WORDLISTID_COLUMN + "= ? AND " + VERSION_COLUMN + "= ? AND "
+                        + FORMATVERSION_COLUMN + "<= ?",
+                new String[]
+                        { id,
+                          Integer.toString(version),
+                          Integer.toString(UpdateHandler.MAXIMUM_SUPPORTED_FORMAT_VERSION)
+                        },
+                null /* groupBy */,
+                null /* having */,
+                FORMATVERSION_COLUMN + " DESC"/* orderBy */);
         if (null == cursor) {
             return null;
         }
@@ -706,7 +747,7 @@
             return null;
         }
         try {
-            // This is a lookup by primary key, so there can't be more than one result.
+            // Return the first result from the list of results.
             return getFirstLineAsContentValues(cursor);
         } finally {
             cursor.close();
@@ -884,6 +925,7 @@
             final long downloadId) {
         final ContentValues values = new ContentValues();
         values.put(CLIENT_PENDINGID_COLUMN, downloadId);
+        values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
         final SQLiteDatabase defaultDb = getDb(context, "");
         final Cursor cursor = MetadataDbHelper.queryClientIds(context);
         if (null == cursor) return;
@@ -1085,4 +1127,27 @@
             final int version) {
         markEntryAs(db, id, version, STATUS_DELETING, NOT_A_DOWNLOAD_ID);
     }
+
+    /**
+     * Checks retry counts and marks the word list as retrying if retry is possible.
+     *
+     * @param db the metadata database.
+     * @param id the id of the word list.
+     * @param version the version of the word list.
+     * @return {@code true} if the retry is possible.
+     */
+    public static boolean maybeMarkEntryAsRetrying(final SQLiteDatabase db, final String id,
+            final int version) {
+        final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db, id, version);
+        int retryCount = values.getAsInteger(MetadataDbHelper.RETRY_COUNT_COLUMN);
+        if (retryCount > 1) {
+            values.put(STATUS_COLUMN, STATUS_RETRYING);
+            values.put(RETRY_COUNT_COLUMN, retryCount - 1);
+            db.update(METADATA_TABLE_NAME, values,
+                    WORDLISTID_COLUMN + " = ? AND " + VERSION_COLUMN + " = ?",
+                    new String[] { id, Integer.toString(version) });
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
index d66b690..329b9f6 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.dictionarypack;
 
+import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 
@@ -29,9 +30,6 @@
  * Helper class to easy up manipulation of dictionary pack metadata.
  */
 public class MetadataHandler {
-    @SuppressWarnings("unused")
-    private static final String TAG = "DictionaryProvider:" + MetadataHandler.class.getSimpleName();
-
     // The canonical file name for metadata. This is not the name of a real file on the
     // device, but a symbolic name used in the database and in metadata handling. It is never
     // tested against, only used for human-readability as the file name for the metadata.
@@ -55,6 +53,7 @@
             final int rawChecksumIndex =
                     results.getColumnIndex(MetadataDbHelper.RAW_CHECKSUM_COLUMN);
             final int checksumIndex = results.getColumnIndex(MetadataDbHelper.CHECKSUM_COLUMN);
+            final int retryCountIndex = results.getColumnIndex(MetadataDbHelper.RETRY_COUNT_COLUMN);
             final int localFilenameIndex =
                     results.getColumnIndex(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
             final int remoteFilenameIndex =
@@ -70,6 +69,7 @@
                         results.getLong(fileSizeIndex),
                         results.getString(rawChecksumIndex),
                         results.getString(checksumIndex),
+                        results.getInt(retryCountIndex),
                         results.getString(localFilenameIndex),
                         results.getString(remoteFilenameIndex),
                         results.getInt(versionIndex),
@@ -102,6 +102,22 @@
     }
 
     /**
+     * Gets the metadata, for a specific dictionary.
+     *
+     * @param context The context to open files over.
+     * @param clientId the client id for retrieving the database. null for default (deprecated).
+     * @param wordListId the word list ID.
+     * @param version the word list version.
+     * @return the current metaData
+     */
+    public static WordListMetadata getCurrentMetadataForWordList(final Context context,
+            final String clientId, final String wordListId, final int version) {
+        final ContentValues contentValues = MetadataDbHelper.getContentValuesByWordListId(
+                MetadataDbHelper.getDb(context, clientId), wordListId, version);
+        return WordListMetadata.createFromContentValues(contentValues);
+    }
+
+    /**
      * Read metadata from a stream.
      * @param input The stream to read from.
      * @return The read metadata.
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java b/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
index 52290ca..2b67ae9 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataParser.java
@@ -83,6 +83,7 @@
                 Long.parseLong(arguments.get(FILESIZE_FIELD_NAME)),
                 arguments.get(RAW_CHECKSUM_FIELD_NAME),
                 arguments.get(CHECKSUM_FIELD_NAME),
+                MetadataDbHelper.DICTIONARY_RETRY_THRESHOLD /* retryCount */,
                 null,
                 arguments.get(REMOTE_FILENAME_FIELD_NAME),
                 Integer.parseInt(arguments.get(VERSION_FIELD_NAME)),
diff --git a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
index 67dd7b9..bb64721 100644
--- a/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
+++ b/java/src/com/android/inputmethod/dictionarypack/PrivateLog.java
@@ -43,8 +43,8 @@
             + COLUMN_DATE + " TEXT,"
             + COLUMN_EVENT + " TEXT);";
 
-    private static final SimpleDateFormat sDateFormat =
-            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
+    static final SimpleDateFormat sDateFormat = new SimpleDateFormat(
+            "yyyy/MM/dd HH:mm:ss", Locale.ROOT);
 
     private static PrivateLog sInstance = new PrivateLog();
     private static DebugHelper sDebugHelper = null;
@@ -62,9 +62,9 @@
         }
     }
 
-    private static class DebugHelper extends SQLiteOpenHelper {
+    static class DebugHelper extends SQLiteOpenHelper {
 
-        private DebugHelper(final Context context) {
+        DebugHelper(final Context context) {
             super(context, LOG_DATABASE_NAME, null, LOG_DATABASE_VERSION);
         }
 
@@ -84,7 +84,7 @@
             insert(db, "Upgrade finished");
         }
 
-        private static void insert(SQLiteDatabase db, String event) {
+        static void insert(SQLiteDatabase db, String event) {
             if (!DEBUG) return;
             final ContentValues c = new ContentValues(2);
             c.put(COLUMN_DATE, sDateFormat.format(new Date(System.currentTimeMillis())));
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index 6fbca44..30ff0b8 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -31,7 +31,6 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.net.ConnectivityManager;
 import android.net.Uri;
-import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.text.TextUtils;
 import android.util.Log;
@@ -40,6 +39,8 @@
 import com.android.inputmethod.compat.DownloadManagerCompatUtils;
 import com.android.inputmethod.compat.NotificationCompatUtils;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
 
@@ -56,10 +57,11 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Set;
 import java.util.TreeSet;
 
+import javax.annotation.Nullable;
+
 /**
  * Handler for the update process.
  *
@@ -77,7 +79,8 @@
     // DownloadManager uses as an ID numbers returned out of an AUTOINCREMENT column
     // in SQLite, so it should never return anything < 0.
     public static final int NOT_AN_ID = -1;
-    public static final int MAXIMUM_SUPPORTED_FORMAT_VERSION = 2;
+    public static final int MAXIMUM_SUPPORTED_FORMAT_VERSION =
+            FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION;
 
     // Arbitrary. Probably good if it's a power of 2, and a couple thousand bytes long.
     private static final int FILE_COPY_BUFFER_SIZE = 8192;
@@ -252,12 +255,16 @@
                 res.getBoolean(R.bool.metadata_downloads_visible_in_download_UI));
 
         final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
-        cancelUpdateWithDownloadManager(context, metadataUri, manager);
+        if (maybeCancelUpdateAndReturnIfStillRunning(context, metadataUri, manager,
+                DictionaryService.NO_CANCEL_DOWNLOAD_PERIOD_MILLIS)) {
+            // We already have a recent download in progress. Don't register a new download.
+            return;
+        }
         final long downloadId;
         synchronized (sSharedIdProtector) {
             downloadId = manager.enqueue(metadataRequest);
             DebugLogUtils.l("Metadata download requested with id", downloadId);
-            // If there is already a download in progress, it's been there for a while and
+            // If there is still a download in progress, it's been there for a while and
             // there is probably something wrong with download manager. It's best to just
             // overwrite the id and request it again. If the old one happens to finish
             // anyway, we don't know about its ID any more, so the downloadFinished
@@ -268,21 +275,29 @@
     }
 
     /**
-     * Cancels downloading a file, if there is one for this URI.
+     * Cancels downloading a file if there is one for this URI and it's too long.
      *
      * If we are not currently downloading the file at this URI, this is a no-op.
      *
      * @param context the context to open the database on
      * @param metadataUri the URI to cancel
      * @param manager an wrapped instance of DownloadManager
+     * @param graceTime if there was a download started less than this many milliseconds, don't
+     *  cancel and return true
+     * @return whether the download is still active
      */
-    private static void cancelUpdateWithDownloadManager(final Context context,
-            final String metadataUri, final DownloadManagerWrapper manager) {
+    private static boolean maybeCancelUpdateAndReturnIfStillRunning(final Context context,
+            final String metadataUri, final DownloadManagerWrapper manager, final long graceTime) {
         synchronized (sSharedIdProtector) {
-            final long metadataDownloadId =
-                    MetadataDbHelper.getMetadataDownloadIdForURI(context, metadataUri);
-            if (NOT_AN_ID == metadataDownloadId) return;
-            manager.remove(metadataDownloadId);
+            final DownloadIdAndStartDate metadataDownloadIdAndStartDate =
+                    MetadataDbHelper.getMetadataDownloadIdAndStartDateForURI(context, metadataUri);
+            if (null == metadataDownloadIdAndStartDate) return false;
+            if (NOT_AN_ID == metadataDownloadIdAndStartDate.mId) return false;
+            if (metadataDownloadIdAndStartDate.mStartDate + graceTime
+                    > System.currentTimeMillis()) {
+                return true;
+            }
+            manager.remove(metadataDownloadIdAndStartDate.mId);
             writeMetadataDownloadId(context, metadataUri, NOT_AN_ID);
         }
         // Consider a cancellation as a failure. As such, inform listeners that the download
@@ -290,6 +305,7 @@
         for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
             listener.downloadedMetadata(false);
         }
+        return false;
     }
 
     /**
@@ -304,7 +320,7 @@
     public static void cancelUpdate(final Context context, final String clientId) {
         final DownloadManagerWrapper manager = new DownloadManagerWrapper(context);
         final String metadataUri = MetadataDbHelper.getMetadataUriAsString(context, clientId);
-        cancelUpdateWithDownloadManager(context, metadataUri, manager);
+        maybeCancelUpdateAndReturnIfStillRunning(context, metadataUri, manager, 0 /* graceTime */);
     }
 
     /**
@@ -388,7 +404,7 @@
             // If any of these is metadata, we should update the DB
             boolean hasMetadata = false;
             for (DownloadRecord record : downloadRecords) {
-                if (null == record.mAttributes) {
+                if (record.isMetadata()) {
                     hasMetadata = true;
                     break;
                 }
@@ -433,6 +449,8 @@
         // download, so we are pretty sure it's alive. It's theoretically possible that it's
         // disabled right inbetween the firing of the intent and the control reaching here.
 
+        boolean dictionaryDownloaded = false;
+
         for (final DownloadRecord record : recordList) {
             // downloadSuccessful is not final because we may still have exceptions from now on
             boolean downloadSuccessful = false;
@@ -447,9 +465,15 @@
                     final SQLiteDatabase db = MetadataDbHelper.getDb(context, record.mClientId);
                     publishUpdateWordListCompleted(context, downloadSuccessful, fileId,
                             db, record.mAttributes, record.mClientId);
+                    dictionaryDownloaded = true;
                 }
             }
         }
+
+        if (dictionaryDownloaded) {
+            // Disable the force download after downloading the dictionaries.
+            CommonPreferences.setForceDownloadDict(context, false);
+        }
         // Now that we're done using it, we can remove this download from DLManager
         manager.remove(fileId);
     }
@@ -738,19 +762,22 @@
      * @return an ordered list of runnables to be called to upgrade.
      */
     private static ActionBatch compareMetadataForUpgrade(final Context context,
-            final String clientId, List<WordListMetadata> from, List<WordListMetadata> to) {
+            final String clientId, @Nullable final List<WordListMetadata> from,
+            @Nullable final List<WordListMetadata> to) {
         final ActionBatch actions = new ActionBatch();
         // Upgrade existing word lists
         DebugLogUtils.l("Comparing dictionaries");
         final Set<String> wordListIds = new TreeSet<>();
         // TODO: Can these be null?
-        if (null == from) from = new ArrayList<>();
-        if (null == to) to = new ArrayList<>();
-        for (WordListMetadata wlData : from) wordListIds.add(wlData.mId);
-        for (WordListMetadata wlData : to) wordListIds.add(wlData.mId);
+        final List<WordListMetadata> fromList = (from == null) ? new ArrayList<WordListMetadata>()
+                : from;
+        final List<WordListMetadata> toList = (to == null) ? new ArrayList<WordListMetadata>()
+                : to;
+        for (WordListMetadata wlData : fromList) wordListIds.add(wlData.mId);
+        for (WordListMetadata wlData : toList) wordListIds.add(wlData.mId);
         for (String id : wordListIds) {
-            final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id);
-            final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id);
+            final WordListMetadata currentInfo = MetadataHandler.findWordListById(fromList, id);
+            final WordListMetadata metadataInfo = MetadataHandler.findWordListById(toList, id);
             // TODO: Remove the following unnecessary check, since we are now doing the filtering
             // inside findWordListById.
             final WordListMetadata newInfo = null == metadataInfo
@@ -785,6 +812,10 @@
             } else {
                 final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId);
                 if (newInfo.mVersion == currentInfo.mVersion) {
+                    if (TextUtils.equals(newInfo.mRemoteFilename, currentInfo.mRemoteFilename)) {
+                        // If the dictionary url hasn't changed, we should preserve the retryCount.
+                        newInfo.mRetryCount = currentInfo.mRetryCount;
+                    }
                     // If it's the same id/version, we update the DB with the new values.
                     // It doesn't matter too much if they didn't change.
                     actions.add(new ActionBatch.UpdateDataAction(clientId, newInfo));
@@ -797,7 +828,8 @@
                     actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo));
                     if (status == MetadataDbHelper.STATUS_INSTALLED
                             || status == MetadataDbHelper.STATUS_DISABLED) {
-                        actions.add(new ActionBatch.StartDownloadAction(clientId, newInfo, false));
+                        actions.add(new ActionBatch.StartDownloadAction(
+                                clientId, newInfo, CommonPreferences.isForceDownloadDict(context)));
                     } else {
                         // Pass true to ForgetAction: this is indeed an update to a non-installed
                         // word list, so activate status == AVAILABLE check
@@ -856,8 +888,8 @@
         // None of those are expected to happen, but just in case...
         if (null == notificationIntent || null == notificationManager) return;
 
-        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
-        final String language = (null == locale ? "" : locale.getDisplayLanguage());
+        final String language = (null == localeString) ? ""
+                : LocaleUtils.constructLocaleFromString(localeString).getDisplayLanguage();
         final String titleFormat = context.getString(R.string.dict_available_notification_title);
         final String notificationTitle = String.format(titleFormat, language);
         final Notification.Builder builder = new Notification.Builder(context)
@@ -950,8 +982,10 @@
         // change the shared preferences. So there is no way for a word list that has been
         // auto-installed once to get auto-installed again, and that's what we want.
         final ActionBatch actions = new ActionBatch();
-        actions.add(new ActionBatch.StartDownloadAction(clientId,
-                WordListMetadata.createFromContentValues(installCandidate), false));
+        actions.add(new ActionBatch.StartDownloadAction(
+                clientId,
+                WordListMetadata.createFromContentValues(installCandidate),
+                CommonPreferences.isForceDownloadDict(context)));
         final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN);
         // We are in a content provider: we can't do any UI at all. We have to defer the displaying
         // itself to the service. Also, we only display this when the user does not have a
@@ -987,17 +1021,19 @@
     public static void markAsUsed(final Context context, final String clientId,
             final String wordlistId, final int version,
             final int status, final boolean allowDownloadOnMeteredData) {
-        final List<WordListMetadata> currentMetadata =
-                MetadataHandler.getCurrentMetadata(context, clientId);
-        WordListMetadata wordList = MetadataHandler.findWordListById(currentMetadata, wordlistId);
-        if (null == wordList) return;
+        final WordListMetadata wordListMetaData = MetadataHandler.getCurrentMetadataForWordList(
+                context, clientId, wordlistId, version);
+
+        if (null == wordListMetaData) return;
+
         final ActionBatch actions = new ActionBatch();
         if (MetadataDbHelper.STATUS_DISABLED == status
                 || MetadataDbHelper.STATUS_DELETING == status) {
-            actions.add(new ActionBatch.EnableAction(clientId, wordList));
+            actions.add(new ActionBatch.EnableAction(clientId, wordListMetaData));
         } else if (MetadataDbHelper.STATUS_AVAILABLE == status) {
-            actions.add(new ActionBatch.StartDownloadAction(clientId, wordList,
-                    allowDownloadOnMeteredData));
+            boolean forceDownloadDict = CommonPreferences.isForceDownloadDict(context);
+            actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData,
+                    forceDownloadDict || allowDownloadOnMeteredData));
         } else {
             Log.e(TAG, "Unexpected state of the word list for markAsUsed : " + status);
         }
@@ -1022,13 +1058,13 @@
     // markAsUsed for consistency.
     public static void markAsUnused(final Context context, final String clientId,
             final String wordlistId, final int version, final int status) {
-        final List<WordListMetadata> currentMetadata =
-                MetadataHandler.getCurrentMetadata(context, clientId);
-        final WordListMetadata wordList =
-                MetadataHandler.findWordListById(currentMetadata, wordlistId);
-        if (null == wordList) return;
+
+        final WordListMetadata wordListMetaData = MetadataHandler.getCurrentMetadataForWordList(
+                context, clientId, wordlistId, version);
+
+        if (null == wordListMetaData) return;
         final ActionBatch actions = new ActionBatch();
-        actions.add(new ActionBatch.DisableAction(clientId, wordList));
+        actions.add(new ActionBatch.DisableAction(clientId, wordListMetaData));
         actions.execute(context, new LogProblemReporter(TAG));
         signalNewDictionaryState(context);
     }
@@ -1051,14 +1087,14 @@
      */
     public static void markAsDeleting(final Context context, final String clientId,
             final String wordlistId, final int version, final int status) {
-        final List<WordListMetadata> currentMetadata =
-                MetadataHandler.getCurrentMetadata(context, clientId);
-        final WordListMetadata wordList =
-                MetadataHandler.findWordListById(currentMetadata, wordlistId);
-        if (null == wordList) return;
+
+        final WordListMetadata wordListMetaData = MetadataHandler.getCurrentMetadataForWordList(
+                context, clientId, wordlistId, version);
+
+        if (null == wordListMetaData) return;
         final ActionBatch actions = new ActionBatch();
-        actions.add(new ActionBatch.DisableAction(clientId, wordList));
-        actions.add(new ActionBatch.StartDeleteAction(clientId, wordList));
+        actions.add(new ActionBatch.DisableAction(clientId, wordListMetaData));
+        actions.add(new ActionBatch.StartDeleteAction(clientId, wordListMetaData));
         actions.execute(context, new LogProblemReporter(TAG));
         signalNewDictionaryState(context);
     }
@@ -1076,33 +1112,48 @@
      */
     public static void markAsDeleted(final Context context, final String clientId,
             final String wordlistId, final int version, final int status) {
-        final List<WordListMetadata> currentMetadata =
-                MetadataHandler.getCurrentMetadata(context, clientId);
-        final WordListMetadata wordList =
-                MetadataHandler.findWordListById(currentMetadata, wordlistId);
-        if (null == wordList) return;
+        final WordListMetadata wordListMetaData = MetadataHandler.getCurrentMetadataForWordList(
+                        context, clientId, wordlistId, version);
+
+        if (null == wordListMetaData) return;
+
         final ActionBatch actions = new ActionBatch();
-        actions.add(new ActionBatch.FinishDeleteAction(clientId, wordList));
+        actions.add(new ActionBatch.FinishDeleteAction(clientId, wordListMetaData));
         actions.execute(context, new LogProblemReporter(TAG));
         signalNewDictionaryState(context);
     }
 
     /**
-     * Marks the word list with the passed id as broken.
-     *
-     * This effectively deletes the entry from the metadata. It doesn't prevent the same
-     * word list to be downloaded again at a later time if the same or a new version is
-     * available the next time we download the metadata.
+     * Checks whether the word list should be downloaded again; in which case an download &
+     * installation attempt is made. Otherwise the word list is marked broken.
      *
      * @param context the context to open the database on.
      * @param clientId the id of the client.
-     * @param wordlistId the id of the word list to mark as broken.
-     * @param version the version of the word list to mark as deleted.
+     * @param wordlistId the id of the word list which is broken.
+     * @param version the version of the broken word list.
      */
-    public static void markAsBroken(final Context context, final String clientId,
+    public static void markAsBrokenOrRetrying(final Context context, final String clientId,
             final String wordlistId, final int version) {
-        // TODO: do this on another thread to avoid blocking the UI.
-        MetadataDbHelper.deleteEntry(MetadataDbHelper.getDb(context, clientId),
-                wordlistId, version);
+        boolean isRetryPossible = MetadataDbHelper.maybeMarkEntryAsRetrying(
+                MetadataDbHelper.getDb(context, clientId), wordlistId, version);
+
+        if (isRetryPossible) {
+            if (DEBUG) {
+                Log.d(TAG, "Attempting to download & install the wordlist again.");
+            }
+            final WordListMetadata wordListMetaData = MetadataHandler.getCurrentMetadataForWordList(
+                    context, clientId, wordlistId, version);
+
+            final ActionBatch actions = new ActionBatch();
+            actions.add(new ActionBatch.StartDownloadAction(
+                    clientId, wordListMetaData, CommonPreferences.isForceDownloadDict(context)));
+            actions.execute(context, new LogProblemReporter(TAG));
+        } else {
+            if (DEBUG) {
+                Log.d(TAG, "Retries for wordlist exhausted, deleting the wordlist from table.");
+            }
+            MetadataDbHelper.deleteEntry(MetadataDbHelper.getDb(context, clientId),
+                    wordlistId, version);
+        }
     }
 }
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java b/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
index 9e510a6..59f75e4 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListMetadata.java
@@ -36,6 +36,7 @@
     public final String mRemoteFilename;
     public final int mVersion; // version of this word list
     public final int mFlags; // Always 0 in this version, reserved for future use
+    public int mRetryCount;
 
     // The locale is matched against the locale requested by the client. The matching algorithm
     // is a standard locale matching with fallback; it is implemented in
@@ -51,8 +52,9 @@
 
     public WordListMetadata(final String id, final int type,
             final String description, final long lastUpdate, final long fileSize,
-            final String rawChecksum, final String checksum, final String localFilename,
-            final String remoteFilename, final int version, final int formatVersion,
+            final String rawChecksum, final String checksum, final int retryCount,
+            final String localFilename, final String remoteFilename,
+            final int version, final int formatVersion,
             final int flags, final String locale) {
         mId = id;
         mType = type;
@@ -61,6 +63,7 @@
         mFileSize = fileSize;
         mRawChecksum = rawChecksum;
         mChecksum = checksum;
+        mRetryCount = retryCount;
         mLocalFilename = localFilename;
         mRemoteFilename = remoteFilename;
         mVersion = version;
@@ -82,6 +85,7 @@
         final Long fileSize = values.getAsLong(MetadataDbHelper.FILESIZE_COLUMN);
         final String rawChecksum = values.getAsString(MetadataDbHelper.RAW_CHECKSUM_COLUMN);
         final String checksum = values.getAsString(MetadataDbHelper.CHECKSUM_COLUMN);
+        final int retryCount = values.getAsInteger(MetadataDbHelper.RETRY_COUNT_COLUMN);
         final String localFilename = values.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
         final String remoteFilename = values.getAsString(MetadataDbHelper.REMOTE_FILENAME_COLUMN);
         final Integer version = values.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
@@ -103,7 +107,8 @@
             throw new IllegalArgumentException();
         }
         return new WordListMetadata(id, type, description, lastUpdate, fileSize, rawChecksum,
-                checksum, localFilename, remoteFilename, version, formatVersion, flags, locale);
+                checksum, retryCount, localFilename, remoteFilename, version, formatVersion,
+                flags, locale);
     }
 
     @Override
@@ -116,6 +121,7 @@
         sb.append("\nFileSize : ").append(mFileSize);
         sb.append("\nRawChecksum : ").append(mRawChecksum);
         sb.append("\nChecksum : ").append(mChecksum);
+        sb.append("\nRetryCount: ").append(mRetryCount);
         sb.append("\nLocalFilename : ").append(mLocalFilename);
         sb.append("\nRemoteFilename : ").append(mRemoteFilename);
         sb.append("\nVersion : ").append(mVersion);
diff --git a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
index aea16af..500e39e 100644
--- a/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
+++ b/java/src/com/android/inputmethod/dictionarypack/WordListPreference.java
@@ -38,45 +38,39 @@
  * enable or delete it as appropriate for the current state of the word list.
  */
 public final class WordListPreference extends Preference {
-    static final private String TAG = WordListPreference.class.getSimpleName();
+    private static final String TAG = WordListPreference.class.getSimpleName();
 
     // What to display in the "status" field when we receive unknown data as a status from
     // the content provider. Empty string sounds sensible.
-    static final private String NO_STATUS_MESSAGE = "";
+    private static final String NO_STATUS_MESSAGE = "";
 
     /// Actions
-    static final private int ACTION_UNKNOWN = 0;
-    static final private int ACTION_ENABLE_DICT = 1;
-    static final private int ACTION_DISABLE_DICT = 2;
-    static final private int ACTION_DELETE_DICT = 3;
+    private static final int ACTION_UNKNOWN = 0;
+    private static final int ACTION_ENABLE_DICT = 1;
+    private static final int ACTION_DISABLE_DICT = 2;
+    private static final int ACTION_DELETE_DICT = 3;
 
     // Members
-    // The context to get resources
-    final Context mContext;
-    // The id of the client for which this preference is.
-    final String mClientId;
     // The metadata word list id and version of this word list.
     public final String mWordlistId;
     public final int mVersion;
     public final Locale mLocale;
     public final String mDescription;
+
+    // The id of the client for which this preference is.
+    private final String mClientId;
     // The status
     private int mStatus;
     // The size of the dictionary file
     private final int mFilesize;
 
     private final DictionaryListInterfaceState mInterfaceState;
-    private final OnWordListPreferenceClick mPreferenceClickHandler =
-            new OnWordListPreferenceClick();
-    private final OnActionButtonClick mActionButtonClickHandler =
-            new OnActionButtonClick();
 
     public WordListPreference(final Context context,
             final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
             final String wordlistId, final int version, final Locale locale,
             final String description, final int status, final int filesize) {
         super(context, null);
-        mContext = context;
         mInterfaceState = dictionaryListInterfaceState;
         mClientId = clientId;
         mVersion = version;
@@ -116,22 +110,23 @@
     }
 
     private String getSummary(final int status) {
+        final Context context = getContext();
         switch (status) {
-            // If we are deleting the word list, for the user it's like it's already deleted.
-            // It should be reinstallable. Exposing to the user the whole complexity of
-            // the delayed deletion process between the dictionary pack and Android Keyboard
-            // would only be confusing.
-            case MetadataDbHelper.STATUS_DELETING:
-            case MetadataDbHelper.STATUS_AVAILABLE:
-                return mContext.getString(R.string.dictionary_available);
-            case MetadataDbHelper.STATUS_DOWNLOADING:
-                return mContext.getString(R.string.dictionary_downloading);
-            case MetadataDbHelper.STATUS_INSTALLED:
-                return mContext.getString(R.string.dictionary_installed);
-            case MetadataDbHelper.STATUS_DISABLED:
-                return mContext.getString(R.string.dictionary_disabled);
-            default:
-                return NO_STATUS_MESSAGE;
+        // If we are deleting the word list, for the user it's like it's already deleted.
+        // It should be reinstallable. Exposing to the user the whole complexity of
+        // the delayed deletion process between the dictionary pack and Android Keyboard
+        // would only be confusing.
+        case MetadataDbHelper.STATUS_DELETING:
+        case MetadataDbHelper.STATUS_AVAILABLE:
+            return context.getString(R.string.dictionary_available);
+        case MetadataDbHelper.STATUS_DOWNLOADING:
+            return context.getString(R.string.dictionary_downloading);
+        case MetadataDbHelper.STATUS_INSTALLED:
+            return context.getString(R.string.dictionary_installed);
+        case MetadataDbHelper.STATUS_DISABLED:
+            return context.getString(R.string.dictionary_disabled);
+        default:
+            return NO_STATUS_MESSAGE;
         }
     }
 
@@ -154,7 +149,7 @@
         { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
     };
 
-    private int getButtonSwitcherStatus(final int status) {
+    static int getButtonSwitcherStatus(final int status) {
         if (status >= sStatusActionList.length) {
             Log.e(TAG, "Unknown status " + status);
             return ButtonSwitcher.STATUS_NO_BUTTON;
@@ -162,7 +157,7 @@
         return sStatusActionList[status][0];
     }
 
-    private static int getActionIdFromStatusAndMenuEntry(final int status) {
+    static int getActionIdFromStatusAndMenuEntry(final int status) {
         if (status >= sStatusActionList.length) {
             Log.e(TAG, "Unknown status " + status);
             return ACTION_UNKNOWN;
@@ -171,9 +166,10 @@
     }
 
     private void disableDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.disable(prefs, mWordlistId);
-        UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus);
+        UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus);
         if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
             setStatus(MetadataDbHelper.STATUS_AVAILABLE);
         } else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) {
@@ -184,11 +180,13 @@
             Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus);
         }
     }
+
     private void enableDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.enable(prefs, mWordlistId);
         // Explicit enabling by the user : allow downloading on metered data connection.
-        UpdateHandler.markAsUsed(mContext, mClientId, mWordlistId, mVersion, mStatus, true);
+        UpdateHandler.markAsUsed(context, mClientId, mWordlistId, mVersion, mStatus, true);
         if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) {
             setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
         } else if (MetadataDbHelper.STATUS_DISABLED == mStatus
@@ -203,11 +201,13 @@
             Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus);
         }
     }
+
     private void deleteDict() {
-        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
+        final Context context = getContext();
+        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
         CommonPreferences.disable(prefs, mWordlistId);
         setStatus(MetadataDbHelper.STATUS_DELETING);
-        UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus);
+        UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus);
     }
 
     @Override
@@ -225,8 +225,8 @@
         status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
         progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);
 
-        final ButtonSwitcher buttonSwitcher =
-                (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
+        final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById(
+                R.id.wordlist_button_switcher);
         // We need to clear the state of the button switcher, because we reuse views; if we didn't
         // reset it would animate from whatever its old state was.
         buttonSwitcher.reset(mInterfaceState);
@@ -244,63 +244,67 @@
             // The button is closed.
             buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
         }
-        buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler);
-        view.setOnClickListener(mPreferenceClickHandler);
+        buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                onActionButtonClicked();
+            }
+        });
+        view.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                onWordListClicked(v);
+            }
+        });
     }
 
-    private class OnWordListPreferenceClick implements View.OnClickListener {
-        @Override
-        public void onClick(final View v) {
-            // Note : v is the preference view
-            final ViewParent parent = v.getParent();
-            // Just in case something changed in the framework, test for the concrete class
-            if (!(parent instanceof ListView)) return;
-            final ListView listView = (ListView)parent;
-            final int indexToOpen;
-            // Close all first, we'll open back any item that needs to be open.
-            final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
-            mInterfaceState.closeAll();
-            if (wasOpen) {
-                // This button being shown. Take note that we don't want to open any button in the
-                // loop below.
-                indexToOpen = -1;
+    void onWordListClicked(final View v) {
+        // Note : v is the preference view
+        final ViewParent parent = v.getParent();
+        // Just in case something changed in the framework, test for the concrete class
+        if (!(parent instanceof ListView)) return;
+        final ListView listView = (ListView)parent;
+        final int indexToOpen;
+        // Close all first, we'll open back any item that needs to be open.
+        final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
+        mInterfaceState.closeAll();
+        if (wasOpen) {
+            // This button being shown. Take note that we don't want to open any button in the
+            // loop below.
+            indexToOpen = -1;
+        } else {
+            // This button was not being shown. Open it, and remember the index of this
+            // child as the one to open in the following loop.
+            mInterfaceState.setOpen(mWordlistId, mStatus);
+            indexToOpen = listView.indexOfChild(v);
+        }
+        final int lastDisplayedIndex =
+                listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
+        // The "lastDisplayedIndex" is actually displayed, hence the <=
+        for (int i = 0; i <= lastDisplayedIndex; ++i) {
+            final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
+                    .findViewById(R.id.wordlist_button_switcher);
+            if (i == indexToOpen) {
+                buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
             } else {
-                // This button was not being shown. Open it, and remember the index of this
-                // child as the one to open in the following loop.
-                mInterfaceState.setOpen(mWordlistId, mStatus);
-                indexToOpen = listView.indexOfChild(v);
-            }
-            final int lastDisplayedIndex =
-                    listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
-            // The "lastDisplayedIndex" is actually displayed, hence the <=
-            for (int i = 0; i <= lastDisplayedIndex; ++i) {
-                final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
-                        .findViewById(R.id.wordlist_button_switcher);
-                if (i == indexToOpen) {
-                    buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
-                } else {
-                    buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
-                }
+                buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
             }
         }
     }
 
-    private class OnActionButtonClick implements View.OnClickListener {
-        @Override
-        public void onClick(final View v) {
-            switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
-            case ACTION_ENABLE_DICT:
-                enableDict();
-                break;
-            case ACTION_DISABLE_DICT:
-                disableDict();
-                break;
-            case ACTION_DELETE_DICT:
-                deleteDict();
-                break;
-            default:
-                Log.e(TAG, "Unknown menu item pressed");
-            }
+    void onActionButtonClicked() {
+        switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
+        case ACTION_ENABLE_DICT:
+            enableDict();
+            break;
+        case ACTION_DISABLE_DICT:
+            disableDict();
+            break;
+        case ACTION_DELETE_DICT:
+            deleteDict();
+            break;
+        default:
+            Log.e(TAG, "Unknown menu item pressed");
         }
     }
 }
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 2d2731f..d77ece8 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -19,10 +19,9 @@
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 
 import javax.annotation.Nonnull;
 
@@ -45,13 +44,6 @@
     private SpannableStringBuilder mStateFeedback;
     private final ArrayList<Combiner> mCombiners;
 
-    private static final HashMap<String, Class<? extends Combiner>> IMPLEMENTED_COMBINERS =
-            new HashMap<>();
-    static {
-        IMPLEMENTED_COMBINERS.put("MyanmarReordering", MyanmarReordering.class);
-    }
-    private static final String COMBINER_SPEC_SEPARATOR = ";";
-
     /**
      * Create an combiner chain.
      *
@@ -61,15 +53,11 @@
      * cursor: we'll start after this.
      *
      * @param initialText The text that has already been combined so far.
-     * @param combinerList A list of combiners to be applied in order.
      */
-    public CombinerChain(final String initialText, final Combiner... combinerList) {
+    public CombinerChain(final String initialText) {
         mCombiners = new ArrayList<>();
         // The dead key combiner is always active, and always first
         mCombiners.add(new DeadKeyCombiner());
-        for (final Combiner combiner : combinerList) {
-            mCombiners.add(combiner);
-        }
         mCombinedText = new StringBuilder(initialText);
         mStateFeedback = new SpannableStringBuilder();
     }
@@ -97,7 +85,8 @@
      *   new event. However it may never be null.
      */
     @Nonnull
-    public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
+    public Event processEvent(final ArrayList<Event> previousEvents,
+            @Nonnull final Event newEvent) {
         final ArrayList<Event> modifiablePreviousEvents = new ArrayList<>(previousEvents);
         Event event = newEvent;
         for (final Combiner combiner : mCombiners) {
@@ -145,30 +134,4 @@
         final SpannableStringBuilder s = new SpannableStringBuilder(mCombinedText);
         return s.append(mStateFeedback);
     }
-
-    public static Combiner[] createCombiners(final String spec) {
-        if (TextUtils.isEmpty(spec)) {
-            return new Combiner[0];
-        }
-        final String[] combinerDescriptors = spec.split(COMBINER_SPEC_SEPARATOR);
-        final Combiner[] combiners = new Combiner[combinerDescriptors.length];
-        int i = 0;
-        for (final String combinerDescriptor : combinerDescriptors) {
-            final Class<? extends Combiner> combinerClass =
-                    IMPLEMENTED_COMBINERS.get(combinerDescriptor);
-            if (null == combinerClass) {
-                throw new RuntimeException("Unknown combiner descriptor: " + combinerDescriptor);
-            }
-            try {
-                combiners[i++] = combinerClass.newInstance();
-            } catch (InstantiationException e) {
-                throw new RuntimeException("Unable to instantiate combiner: " + combinerDescriptor,
-                        e);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Unable to instantiate combiner: " + combinerDescriptor,
-                        e);
-            }
-        }
-        return combiners;
-    }
 }
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index 4f3f4d2..1a28bb1 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -17,10 +17,11 @@
 package com.android.inputmethod.event;
 
 import android.text.TextUtils;
-import android.view.KeyCharacterMap;
+import android.util.SparseIntArray;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
+import java.text.Normalizer;
 import java.util.ArrayList;
 
 import javax.annotation.Nonnull;
@@ -29,9 +30,208 @@
  * A combiner that handles dead keys.
  */
 public class DeadKeyCombiner implements Combiner {
+
+    private static class Data {
+        // This class data taken from KeyCharacterMap.java.
+
+        /* Characters used to display placeholders for dead keys. */
+        private static final int ACCENT_ACUTE = '\u00B4';
+        private static final int ACCENT_BREVE = '\u02D8';
+        private static final int ACCENT_CARON = '\u02C7';
+        private static final int ACCENT_CEDILLA = '\u00B8';
+        private static final int ACCENT_CIRCUMFLEX = '\u02C6';
+        private static final int ACCENT_COMMA_ABOVE = '\u1FBD';
+        private static final int ACCENT_COMMA_ABOVE_RIGHT = '\u02BC';
+        private static final int ACCENT_DOT_ABOVE = '\u02D9';
+        private static final int ACCENT_DOT_BELOW = Constants.CODE_PERIOD; // approximate
+        private static final int ACCENT_DOUBLE_ACUTE = '\u02DD';
+        private static final int ACCENT_GRAVE = '\u02CB';
+        private static final int ACCENT_HOOK_ABOVE = '\u02C0';
+        private static final int ACCENT_HORN = Constants.CODE_SINGLE_QUOTE; // approximate
+        private static final int ACCENT_MACRON = '\u00AF';
+        private static final int ACCENT_MACRON_BELOW = '\u02CD';
+        private static final int ACCENT_OGONEK = '\u02DB';
+        private static final int ACCENT_REVERSED_COMMA_ABOVE = '\u02BD';
+        private static final int ACCENT_RING_ABOVE = '\u02DA';
+        private static final int ACCENT_STROKE = Constants.CODE_DASH; // approximate
+        private static final int ACCENT_TILDE = '\u02DC';
+        private static final int ACCENT_TURNED_COMMA_ABOVE = '\u02BB';
+        private static final int ACCENT_UMLAUT = '\u00A8';
+        private static final int ACCENT_VERTICAL_LINE_ABOVE = '\u02C8';
+        private static final int ACCENT_VERTICAL_LINE_BELOW = '\u02CC';
+
+        /* Legacy dead key display characters used in previous versions of the API (before L)
+         * We still support these characters by mapping them to their non-legacy version. */
+        private static final int ACCENT_GRAVE_LEGACY = Constants.CODE_GRAVE_ACCENT;
+        private static final int ACCENT_CIRCUMFLEX_LEGACY = Constants.CODE_CIRCUMFLEX_ACCENT;
+        private static final int ACCENT_TILDE_LEGACY = Constants.CODE_TILDE;
+
+        /**
+         * Maps Unicode combining diacritical to display-form dead key.
+         */
+        static final SparseIntArray sCombiningToAccent = new SparseIntArray();
+        static final SparseIntArray sAccentToCombining = new SparseIntArray();
+        static {
+            // U+0300: COMBINING GRAVE ACCENT
+            addCombining('\u0300', ACCENT_GRAVE);
+            // U+0301: COMBINING ACUTE ACCENT
+            addCombining('\u0301', ACCENT_ACUTE);
+            // U+0302: COMBINING CIRCUMFLEX ACCENT
+            addCombining('\u0302', ACCENT_CIRCUMFLEX);
+            // U+0303: COMBINING TILDE
+            addCombining('\u0303', ACCENT_TILDE);
+            // U+0304: COMBINING MACRON
+            addCombining('\u0304', ACCENT_MACRON);
+            // U+0306: COMBINING BREVE
+            addCombining('\u0306', ACCENT_BREVE);
+            // U+0307: COMBINING DOT ABOVE
+            addCombining('\u0307', ACCENT_DOT_ABOVE);
+            // U+0308: COMBINING DIAERESIS
+            addCombining('\u0308', ACCENT_UMLAUT);
+            // U+0309: COMBINING HOOK ABOVE
+            addCombining('\u0309', ACCENT_HOOK_ABOVE);
+            // U+030A: COMBINING RING ABOVE
+            addCombining('\u030A', ACCENT_RING_ABOVE);
+            // U+030B: COMBINING DOUBLE ACUTE ACCENT
+            addCombining('\u030B', ACCENT_DOUBLE_ACUTE);
+            // U+030C: COMBINING CARON
+            addCombining('\u030C', ACCENT_CARON);
+            // U+030D: COMBINING VERTICAL LINE ABOVE
+            addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE);
+            // U+030E: COMBINING DOUBLE VERTICAL LINE ABOVE
+            //addCombining('\u030E', ACCENT_DOUBLE_VERTICAL_LINE_ABOVE);
+            // U+030F: COMBINING DOUBLE GRAVE ACCENT
+            //addCombining('\u030F', ACCENT_DOUBLE_GRAVE);
+            // U+0310: COMBINING CANDRABINDU
+            //addCombining('\u0310', ACCENT_CANDRABINDU);
+            // U+0311: COMBINING INVERTED BREVE
+            //addCombining('\u0311', ACCENT_INVERTED_BREVE);
+            // U+0312: COMBINING TURNED COMMA ABOVE
+            addCombining('\u0312', ACCENT_TURNED_COMMA_ABOVE);
+            // U+0313: COMBINING COMMA ABOVE
+            addCombining('\u0313', ACCENT_COMMA_ABOVE);
+            // U+0314: COMBINING REVERSED COMMA ABOVE
+            addCombining('\u0314', ACCENT_REVERSED_COMMA_ABOVE);
+            // U+0315: COMBINING COMMA ABOVE RIGHT
+            addCombining('\u0315', ACCENT_COMMA_ABOVE_RIGHT);
+            // U+031B: COMBINING HORN
+            addCombining('\u031B', ACCENT_HORN);
+            // U+0323: COMBINING DOT BELOW
+            addCombining('\u0323', ACCENT_DOT_BELOW);
+            // U+0326: COMBINING COMMA BELOW
+            //addCombining('\u0326', ACCENT_COMMA_BELOW);
+            // U+0327: COMBINING CEDILLA
+            addCombining('\u0327', ACCENT_CEDILLA);
+            // U+0328: COMBINING OGONEK
+            addCombining('\u0328', ACCENT_OGONEK);
+            // U+0329: COMBINING VERTICAL LINE BELOW
+            addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW);
+            // U+0331: COMBINING MACRON BELOW
+            addCombining('\u0331', ACCENT_MACRON_BELOW);
+            // U+0335: COMBINING SHORT STROKE OVERLAY
+            addCombining('\u0335', ACCENT_STROKE);
+            // U+0342: COMBINING GREEK PERISPOMENI
+            //addCombining('\u0342', ACCENT_PERISPOMENI);
+            // U+0344: COMBINING GREEK DIALYTIKA TONOS
+            //addCombining('\u0344', ACCENT_DIALYTIKA_TONOS);
+            // U+0345: COMBINING GREEK YPOGEGRAMMENI
+            //addCombining('\u0345', ACCENT_YPOGEGRAMMENI);
+
+            // One-way mappings to equivalent preferred accents.
+            // U+0340: COMBINING GRAVE TONE MARK
+            sCombiningToAccent.append('\u0340', ACCENT_GRAVE);
+            // U+0341: COMBINING ACUTE TONE MARK
+            sCombiningToAccent.append('\u0341', ACCENT_ACUTE);
+            // U+0343: COMBINING GREEK KORONIS
+            sCombiningToAccent.append('\u0343', ACCENT_COMMA_ABOVE);
+
+            // One-way legacy mappings to preserve compatibility with older applications.
+            // U+0300: COMBINING GRAVE ACCENT
+            sAccentToCombining.append(ACCENT_GRAVE_LEGACY, '\u0300');
+            // U+0302: COMBINING CIRCUMFLEX ACCENT
+            sAccentToCombining.append(ACCENT_CIRCUMFLEX_LEGACY, '\u0302');
+            // U+0303: COMBINING TILDE
+            sAccentToCombining.append(ACCENT_TILDE_LEGACY, '\u0303');
+        }
+
+        private static void addCombining(int combining, int accent) {
+            sCombiningToAccent.append(combining, accent);
+            sAccentToCombining.append(accent, combining);
+        }
+
+        // Caution! This may only contain chars, not supplementary code points. It's unlikely
+        // it will ever need to, but if it does we'll have to change this
+        private static final SparseIntArray sNonstandardDeadCombinations = new SparseIntArray();
+        static {
+            // Non-standard decompositions.
+            // Stroke modifier for Finnish multilingual keyboard and others.
+            // U+0110: LATIN CAPITAL LETTER D WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'D', '\u0110');
+            // U+01E4: LATIN CAPITAL LETTER G WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'G', '\u01e4');
+            // U+0126: LATIN CAPITAL LETTER H WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'H', '\u0126');
+            // U+0197: LATIN CAPITAL LETTER I WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'I', '\u0197');
+            // U+0141: LATIN CAPITAL LETTER L WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'L', '\u0141');
+            // U+00D8: LATIN CAPITAL LETTER O WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'O', '\u00d8');
+            // U+0166: LATIN CAPITAL LETTER T WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'T', '\u0166');
+            // U+0111: LATIN SMALL LETTER D WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'd', '\u0111');
+            // U+01E5: LATIN SMALL LETTER G WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'g', '\u01e5');
+            // U+0127: LATIN SMALL LETTER H WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'h', '\u0127');
+            // U+0268: LATIN SMALL LETTER I WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'i', '\u0268');
+            // U+0142: LATIN SMALL LETTER L WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'l', '\u0142');
+            // U+00F8: LATIN SMALL LETTER O WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 'o', '\u00f8');
+            // U+0167: LATIN SMALL LETTER T WITH STROKE
+            addNonStandardDeadCombination(ACCENT_STROKE, 't', '\u0167');
+        }
+
+        private static void addNonStandardDeadCombination(final int deadCodePoint,
+                final int spacingCodePoint, final int result) {
+            final int combination = (deadCodePoint << 16) | spacingCodePoint;
+            sNonstandardDeadCombinations.put(combination, result);
+        }
+
+        public static final int NOT_A_CHAR = 0;
+        public static final int BITS_TO_SHIFT_DEAD_CODE_POINT_FOR_NON_STANDARD_COMBINATION = 16;
+        // Get a non-standard combination
+        public static char getNonstandardCombination(final int deadCodePoint,
+                final int spacingCodePoint) {
+            final int combination = spacingCodePoint |
+                    (deadCodePoint << BITS_TO_SHIFT_DEAD_CODE_POINT_FOR_NON_STANDARD_COMBINATION);
+            return (char)sNonstandardDeadCombinations.get(combination, NOT_A_CHAR);
+        }
+    }
+
     // TODO: make this a list of events instead
     final StringBuilder mDeadSequence = new StringBuilder();
 
+    @Nonnull
+    private static Event createEventChainFromSequence(final @Nonnull CharSequence text,
+            @Nonnull final Event originalEvent) {
+        int index = text.length();
+        if (index <= 0) {
+            return originalEvent;
+        }
+        Event lastEvent = null;
+        do {
+            final int codePoint = Character.codePointBefore(text, index);
+            lastEvent = Event.createHardwareKeypressEvent(codePoint,
+                    originalEvent.mKeyCode, lastEvent, false /* isKeyRepeat */);
+            index -= Character.charCount(codePoint);
+        } while (index > 0);
+        return lastEvent;
+    }
+
     @Override
     @Nonnull
     public Event processEvent(final ArrayList<Event> previousEvents, final Event event) {
@@ -46,32 +246,49 @@
             // no dead keys at all in the current input, so this combiner has nothing to do and
             // simply returns the event as is. The majority of events will go through this path.
             return event;
-        } else {
-            // TODO: Allow combining for several dead chars rather than only the first one.
-            // The framework doesn't know how to do this now.
-            final int deadCodePoint = mDeadSequence.codePointAt(0);
-            mDeadSequence.setLength(0);
-            final int resultingCodePoint =
-                    KeyCharacterMap.getDeadChar(deadCodePoint, event.mCodePoint);
-            if (0 == resultingCodePoint) {
-                // We can't combine both characters. We need to commit the dead key as a separate
-                // character, and the next char too unless it's a space (because as a special case,
-                // dead key + space should result in only the dead key being committed - that's
-                // how dead keys work).
-                // If the event is a space, we should commit the dead char alone, but if it's
-                // not, we need to commit both.
-                // TODO: this is not necessarily triggered by hardware key events, so it's not
-                // a good idea to masquerade as one. This should be typed as a software
-                // composite event or something.
-                return Event.createHardwareKeypressEvent(deadCodePoint, event.mKeyCode,
-                        Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */,
-                        false /* isKeyRepeat */);
-            } else {
-                // We could combine the characters.
-                return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode,
-                        null /* next */, false /* isKeyRepeat */);
-            }
         }
+        if (Character.isWhitespace(event.mCodePoint)
+                || event.mCodePoint == mDeadSequence.codePointBefore(mDeadSequence.length())) {
+            // When whitespace or twice the same dead key, we should output the dead sequence as is.
+            final Event resultEvent = createEventChainFromSequence(mDeadSequence.toString(),
+                    event);
+            mDeadSequence.setLength(0);
+            return resultEvent;
+        }
+        if (event.isFunctionalKeyEvent()) {
+            if (Constants.CODE_DELETE == event.mKeyCode) {
+                // Remove the last code point
+                final int trimIndex = mDeadSequence.length() - Character.charCount(
+                        mDeadSequence.codePointBefore(mDeadSequence.length()));
+                mDeadSequence.setLength(trimIndex);
+                return Event.createConsumedEvent(event);
+            }
+            return event;
+        }
+        if (event.isDead()) {
+            mDeadSequence.appendCodePoint(event.mCodePoint);
+            return Event.createConsumedEvent(event);
+        }
+        // Combine normally.
+        final StringBuilder sb = new StringBuilder();
+        sb.appendCodePoint(event.mCodePoint);
+        int codePointIndex = 0;
+        while (codePointIndex < mDeadSequence.length()) {
+            final int deadCodePoint = mDeadSequence.codePointAt(codePointIndex);
+            final char replacementSpacingChar =
+                    Data.getNonstandardCombination(deadCodePoint, event.mCodePoint);
+            if (Data.NOT_A_CHAR != replacementSpacingChar) {
+                sb.setCharAt(0, replacementSpacingChar);
+            } else {
+                final int combining = Data.sAccentToCombining.get(deadCodePoint);
+                sb.appendCodePoint(0 == combining ? deadCodePoint : combining);
+            }
+            codePointIndex += Character.isSupplementaryCodePoint(deadCodePoint) ? 2 : 1;
+        }
+        final String normalizedString = Normalizer.normalize(sb, Normalizer.Form.NFC);
+        final Event resultEvent = createEventChainFromSequence(normalizedString, event);
+        mDeadSequence.setLength(0);
+        return resultEvent;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index ef5b047..e3b1afc 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -16,9 +16,12 @@
 
 package com.android.inputmethod.event;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
+
+import javax.annotation.Nonnull;
 
 /**
  * Class representing a generic input event as handled by Latin IME.
@@ -55,6 +58,8 @@
     final public static int EVENT_TYPE_SUGGESTION_PICKED = 5;
     // An event corresponding to a string generated by some software process.
     final public static int EVENT_TYPE_SOFTWARE_GENERATED_STRING = 6;
+    // An event corresponding to a cursor move
+    final public static int EVENT_TYPE_CURSOR_MOVE = 7;
 
     // 0 is a valid code point, so we use -1 here.
     final public static int NOT_A_CODE_POINT = -1;
@@ -133,12 +138,14 @@
         }
     }
 
+    @Nonnull
     public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
             final int x, final int y, final boolean isKeyRepeat) {
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
                 null /* suggestedWordInfo */, isKeyRepeat ? FLAG_REPEAT : FLAG_NONE, null);
     }
 
+    @Nonnull
     public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
             final Event next, final boolean isKeyRepeat) {
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
@@ -147,6 +154,8 @@
     }
 
     // This creates an input event for a dead character. @see {@link #FLAG_DEAD}
+    @ExternallyReferenced
+    @Nonnull
     public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
         // TODO: add an argument or something if we ever create a software layout with dead keys.
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
@@ -161,6 +170,7 @@
      * @param codePoint the code point.
      * @return an event for this code point.
      */
+    @Nonnull
     public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
         // TODO: should we have a different type of event for this? After all, it's not a key press.
         return new Event(EVENT_TYPE_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
@@ -176,6 +186,7 @@
      * @param y the Y coordinate.
      * @return an event for this code point and coordinates.
      */
+    @Nonnull
     public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
             final int x, final int y) {
         // TODO: should we have a different type of event for this? After all, it's not a key press.
@@ -187,6 +198,7 @@
      * Creates an input event representing the manual pick of a suggestion.
      * @return an event for this suggestion pick.
      */
+    @Nonnull
     public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
         return new Event(EVENT_TYPE_SUGGESTION_PICKED, suggestedWordInfo.mWord,
                 NOT_A_CODE_POINT, NOT_A_KEY_CODE,
@@ -202,6 +214,7 @@
      * @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
      * @return an event for this text.
      */
+    @Nonnull
     public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
         return new Event(EVENT_TYPE_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
                 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
@@ -212,6 +225,7 @@
      * Creates an input event representing the manual pick of a punctuation suggestion.
      * @return an event for this suggestion pick.
      */
+    @Nonnull
     public static Event createPunctuationSuggestionPickedEvent(
             final SuggestedWordInfo suggestedWordInfo) {
         final int primaryCode = suggestedWordInfo.mWord.charAt(0);
@@ -222,10 +236,23 @@
     }
 
     /**
+     * Creates an input event representing moving the cursor. The relative move amount is stored
+     * in mX.
+     * @param moveAmount the relative move amount.
+     * @return an event for this cursor move.
+     */
+    @Nonnull
+    public static Event createCursorMovedEvent(final int moveAmount) {
+        return new Event(EVENT_TYPE_CURSOR_MOVE, null, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
+                moveAmount, Constants.NOT_A_COORDINATE, null, FLAG_NONE, null);
+    }
+
+    /**
      * Creates an event identical to the passed event, but that has already been consumed.
      * @param source the event to copy the properties of.
      * @return an identical event marked as consumed.
      */
+    @Nonnull
     public static Event createConsumedEvent(final Event source) {
         // A consumed event should not input any text at all, so we pass the empty string as text.
         return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
@@ -233,6 +260,7 @@
                 source.mNextEvent);
     }
 
+    @Nonnull
     public static Event createNotHandledEvent() {
         return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
                 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
@@ -277,6 +305,7 @@
         case EVENT_TYPE_MODE_KEY:
         case EVENT_TYPE_NOT_HANDLED:
         case EVENT_TYPE_TOGGLE:
+        case EVENT_TYPE_CURSOR_MOVE:
             return "";
         case EVENT_TYPE_INPUT_KEYPRESS:
             return StringUtils.newSingleCodePointString(mCodePoint);
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index c61f45e..3a4097d 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -19,7 +19,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 /**
  * A hardware event decoder for a hardware qwerty-ish keyboard.
@@ -67,10 +67,9 @@
                 if (keyEvent.isShiftPressed()) {
                     return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
                             Constants.CODE_SHIFT_ENTER, null /* next */, isKeyRepeat);
-                } else {
-                    return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
-                            null /* next */, isKeyRepeat);
                 }
+                return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
+                        null /* next */, isKeyRepeat);
             }
             // If not Enter, then this is just a regular keypress event for a normal character
             // that can be committed right away, taking into account the current state.
diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java
deleted file mode 100644
index dcd06c8..0000000
--- a/java/src/com/android/inputmethod/event/MyanmarReordering.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2014 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.event;
-
-import com.android.inputmethod.latin.Constants;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import javax.annotation.Nonnull;
-
-/**
- * A combiner that reorders input for Myanmar.
- */
-public class MyanmarReordering implements Combiner {
-    // U+1031 MYANMAR VOWEL SIGN E
-    private final static int VOWEL_E = 0x1031; // Code point for vowel E that we need to reorder
-    // U+200C ZERO WIDTH NON-JOINER
-    // U+200B ZERO WIDTH SPACE
-    private final static int ZERO_WIDTH_NON_JOINER = 0x200B; // should be 0x200C
-
-    private final ArrayList<Event> mCurrentEvents = new ArrayList<>();
-
-    // List of consonants :
-    // U+1000 MYANMAR LETTER KA
-    // U+1001 MYANMAR LETTER KHA
-    // U+1002 MYANMAR LETTER GA
-    // U+1003 MYANMAR LETTER GHA
-    // U+1004 MYANMAR LETTER NGA
-    // U+1005 MYANMAR LETTER CA
-    // U+1006 MYANMAR LETTER CHA
-    // U+1007 MYANMAR LETTER JA
-    // U+1008 MYANMAR LETTER JHA
-    // U+1009 MYANMAR LETTER NYA
-    // U+100A MYANMAR LETTER NNYA
-    // U+100B MYANMAR LETTER TTA
-    // U+100C MYANMAR LETTER TTHA
-    // U+100D MYANMAR LETTER DDA
-    // U+100E MYANMAR LETTER DDHA
-    // U+100F MYANMAR LETTER NNA
-    // U+1010 MYANMAR LETTER TA
-    // U+1011 MYANMAR LETTER THA
-    // U+1012 MYANMAR LETTER DA
-    // U+1013 MYANMAR LETTER DHA
-    // U+1014 MYANMAR LETTER NA
-    // U+1015 MYANMAR LETTER PA
-    // U+1016 MYANMAR LETTER PHA
-    // U+1017 MYANMAR LETTER BA
-    // U+1018 MYANMAR LETTER BHA
-    // U+1019 MYANMAR LETTER MA
-    // U+101A MYANMAR LETTER YA
-    // U+101B MYANMAR LETTER RA
-    // U+101C MYANMAR LETTER LA
-    // U+101D MYANMAR LETTER WA
-    // U+101E MYANMAR LETTER SA
-    // U+101F MYANMAR LETTER HA
-    // U+1020 MYANMAR LETTER LLA
-    // U+103F MYANMAR LETTER GREAT SA
-    private static boolean isConsonant(final int codePoint) {
-        return (codePoint >= 0x1000 && codePoint <= 0x1020) || 0x103F == codePoint;
-    }
-
-    // List of medials :
-    // U+103B MYANMAR CONSONANT SIGN MEDIAL YA
-    // U+103C MYANMAR CONSONANT SIGN MEDIAL RA
-    // U+103D MYANMAR CONSONANT SIGN MEDIAL WA
-    // U+103E MYANMAR CONSONANT SIGN MEDIAL HA
-    // U+105E MYANMAR CONSONANT SIGN MON MEDIAL NA
-    // U+105F MYANMAR CONSONANT SIGN MON MEDIAL MA
-    // U+1060 MYANMAR CONSONANT SIGN MON MEDIAL LA
-    // U+1082 MYANMAR CONSONANT SIGN SHAN MEDIAL WA
-    private static int[] MEDIAL_LIST = { 0x103B, 0x103C, 0x103D, 0x103E,
-            0x105E, 0x105F, 0x1060, 0x1082};
-    private static boolean isMedial(final int codePoint) {
-        return Arrays.binarySearch(MEDIAL_LIST, codePoint) >= 0;
-    }
-
-    private static boolean isConsonantOrMedial(final int codePoint) {
-        return isConsonant(codePoint) || isMedial(codePoint);
-    }
-
-    private Event getLastEvent() {
-        final int size = mCurrentEvents.size();
-        if (size <= 0) {
-            return null;
-        }
-        return mCurrentEvents.get(size - 1);
-    }
-
-    private CharSequence getCharSequence() {
-        final StringBuilder s = new StringBuilder();
-        for (final Event e : mCurrentEvents) {
-            s.appendCodePoint(e.mCodePoint);
-        }
-        return s;
-    }
-
-    /**
-     * Clears the currently combining stream of events and returns the resulting software text
-     * event corresponding to the stream. Optionally adds a new event to the cleared stream.
-     * @param newEvent the new event to add to the stream. null if none.
-     * @return the resulting software text event. Never null.
-     */
-    private Event clearAndGetResultingEvent(final Event newEvent) {
-        final CharSequence combinedText;
-        if (mCurrentEvents.size() > 0) {
-            combinedText = getCharSequence();
-            mCurrentEvents.clear();
-        } else {
-            combinedText = null;
-        }
-        if (null != newEvent) {
-            mCurrentEvents.add(newEvent);
-        }
-        return null == combinedText ? Event.createConsumedEvent(newEvent)
-                : Event.createSoftwareTextEvent(combinedText, Event.NOT_A_KEY_CODE);
-    }
-
-    @Override
-    @Nonnull
-    public Event processEvent(ArrayList<Event> previousEvents, Event newEvent) {
-        final int codePoint = newEvent.mCodePoint;
-        if (VOWEL_E == codePoint) {
-            final Event lastEvent = getLastEvent();
-            if (null == lastEvent) {
-                mCurrentEvents.add(newEvent);
-                return Event.createConsumedEvent(newEvent);
-            } else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
-                final Event resultingEvent = clearAndGetResultingEvent(null);
-                mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
-                        Event.NOT_A_KEY_CODE,
-                        Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
-                        false /* isKeyRepeat */));
-                mCurrentEvents.add(newEvent);
-                return resultingEvent;
-            } else { // VOWEL_E == lastCodePoint. But if that was anything else this is correct too.
-                return clearAndGetResultingEvent(newEvent);
-            }
-        } if (isConsonant(codePoint)) {
-            final Event lastEvent = getLastEvent();
-            if (null == lastEvent) {
-                mCurrentEvents.add(newEvent);
-                return Event.createConsumedEvent(newEvent);
-            } else if (VOWEL_E == lastEvent.mCodePoint) {
-                final int eventSize = mCurrentEvents.size();
-                if (eventSize >= 2
-                        && mCurrentEvents.get(eventSize - 2).mCodePoint == ZERO_WIDTH_NON_JOINER) {
-                    // We have a ZWJN before a vowel E. We need to remove the ZWNJ and then
-                    // reorder the vowel with respect to the consonant.
-                    mCurrentEvents.remove(eventSize - 1);
-                    mCurrentEvents.remove(eventSize - 2);
-                    mCurrentEvents.add(newEvent);
-                    mCurrentEvents.add(lastEvent);
-                    return Event.createConsumedEvent(newEvent);
-                }
-                // If there is already a consonant, then we are starting a new syllable.
-                for (int i = eventSize - 2; i >= 0; --i) {
-                    if (isConsonant(mCurrentEvents.get(i).mCodePoint)) {
-                        return clearAndGetResultingEvent(newEvent);
-                    }
-                }
-                // If we come here, we didn't have a consonant so we reorder
-                mCurrentEvents.remove(eventSize - 1);
-                mCurrentEvents.add(newEvent);
-                mCurrentEvents.add(lastEvent);
-                return Event.createConsumedEvent(newEvent);
-            } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
-                return clearAndGetResultingEvent(newEvent);
-            }
-        } else if (isMedial(codePoint)) {
-            final Event lastEvent = getLastEvent();
-            if (null == lastEvent) {
-                mCurrentEvents.add(newEvent);
-                return Event.createConsumedEvent(newEvent);
-            } else if (VOWEL_E == lastEvent.mCodePoint) {
-                final int eventSize = mCurrentEvents.size();
-                // If there is already a consonant, then we are in the middle of a syllable, and we
-                // need to reorder.
-                boolean hasConsonant = false;
-                for (int i = eventSize - 2; i >= 0; --i) {
-                    if (isConsonant(mCurrentEvents.get(i).mCodePoint)) {
-                        hasConsonant = true;
-                        break;
-                    }
-                }
-                if (hasConsonant) {
-                    mCurrentEvents.remove(eventSize - 1);
-                    mCurrentEvents.add(newEvent);
-                    mCurrentEvents.add(lastEvent);
-                    return Event.createConsumedEvent(newEvent);
-                }
-                // Otherwise, we just commit everything.
-                return clearAndGetResultingEvent(null);
-            } else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
-                return clearAndGetResultingEvent(newEvent);
-            }
-        } else if (Constants.CODE_DELETE == newEvent.mKeyCode) {
-            final Event lastEvent = getLastEvent();
-            final int eventSize = mCurrentEvents.size();
-            if (null != lastEvent) {
-                if (VOWEL_E == lastEvent.mCodePoint) {
-                    // We have a VOWEL_E at the end. There are four cases.
-                    // - The vowel is the only code point in the buffer. Remove it.
-                    // - The vowel is preceded by a ZWNJ. Remove both vowel E and ZWNJ.
-                    // - The vowel is preceded by a consonant/medial, remove the consonant/medial.
-                    // - In all other cases, it's strange, so just remove the last code point.
-                    if (eventSize <= 1) {
-                        mCurrentEvents.clear();
-                    } else { // eventSize >= 2
-                        final int previousCodePoint = mCurrentEvents.get(eventSize - 2).mCodePoint;
-                        if (previousCodePoint == ZERO_WIDTH_NON_JOINER) {
-                            mCurrentEvents.remove(eventSize - 1);
-                            mCurrentEvents.remove(eventSize - 2);
-                        } else if (isConsonantOrMedial(previousCodePoint)) {
-                            mCurrentEvents.remove(eventSize - 2);
-                        } else {
-                            mCurrentEvents.remove(eventSize - 1);
-                        }
-                    }
-                    return Event.createConsumedEvent(newEvent);
-                } else if (eventSize > 0) {
-                    mCurrentEvents.remove(eventSize - 1);
-                    return Event.createConsumedEvent(newEvent);
-                }
-            }
-        }
-        // This character is not part of the combining scheme, so we should reset everything.
-        if (mCurrentEvents.size() > 0) {
-            // If we have events in flight, then add the new event and return the resulting event.
-            mCurrentEvents.add(newEvent);
-            return clearAndGetResultingEvent(null);
-        } else {
-            // If we don't have any events in flight, then just pass this one through.
-            return newEvent;
-        }
-    }
-
-    @Override
-    public CharSequence getCombiningStateFeedback() {
-        return getCharSequence();
-    }
-
-    @Override
-    public void reset() {
-        mCurrentEvents.clear();
-    }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 81ea90a..299d1b7 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -17,10 +17,10 @@
 package com.android.inputmethod.keyboard;
 
 import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
-import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT;
-import static com.android.inputmethod.latin.Constants.CODE_SHIFT;
-import static com.android.inputmethod.latin.Constants.CODE_SWITCH_ALPHA_SYMBOL;
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
+import static com.android.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
+import static com.android.inputmethod.latin.common.Constants.CODE_SHIFT;
+import static com.android.inputmethod.latin.common.Constants.CODE_SWITCH_ALPHA_SYMBOL;
+import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
 
 import android.content.res.TypedArray;
 import android.graphics.Rect;
@@ -36,13 +36,16 @@
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
 import com.android.inputmethod.keyboard.internal.KeyboardRow;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.Arrays;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * Class for describing the position and characteristics of a single key in the keyboard.
  */
@@ -94,18 +97,30 @@
     /** Icon to display instead of a label. Icon takes precedence over a label */
     private final int mIconId;
 
-    /** Width of the key, not including the gap */
+    /** Width of the key, excluding the gap */
     private final int mWidth;
-    /** Height of the key, not including the gap */
+    /** Height of the key, excluding the gap */
     private final int mHeight;
-    /** X coordinate of the key in the keyboard layout */
+    /**
+     * The combined width in pixels of the horizontal gaps belonging to this key, both to the left
+     * and to the right. I.e., mWidth + mHorizontalGap = total width belonging to the key.
+     */
+    private final int mHorizontalGap;
+    /**
+     * The combined height in pixels of the vertical gaps belonging to this key, both above and
+     * below. I.e., mHeight + mVerticalGap = total height belonging to the key.
+     */
+    private final int mVerticalGap;
+    /** X coordinate of the top-left corner of the key in the keyboard layout, excluding the gap. */
     private final int mX;
-    /** Y coordinate of the key in the keyboard layout */
+    /** Y coordinate of the top-left corner of the key in the keyboard layout, excluding the gap. */
     private final int mY;
     /** Hit bounding box of the key */
+    @Nonnull
     private final Rect mHitBox = new Rect();
 
     /** More keys. It is guaranteed that this is null or an array of one or more elements */
+    @Nullable
     private final MoreKeySpec[] mMoreKeys;
     /** More keys column number and flags */
     private final int mMoreKeysColumnAndFlags;
@@ -148,8 +163,9 @@
     private static final int ACTION_FLAGS_ALT_CODE_WHILE_TYPING = 0x04;
     private static final int ACTION_FLAGS_ENABLE_LONG_PRESS = 0x08;
 
+    @Nullable
     private final KeyVisualAttributes mKeyVisualAttributes;
-
+    @Nullable
     private final OptionalAttributes mOptionalAttributes;
 
     private static final class OptionalAttributes {
@@ -171,6 +187,7 @@
             mVisualInsetsRight = visualInsetsRight;
         }
 
+        @Nullable
         public static OptionalAttributes newInstance(final String outputText, final int altCode,
                 final int disabledIconId, final int visualInsetsLeft, final int visualInsetsRight) {
             if (outputText == null && altCode == CODE_UNSPECIFIED
@@ -194,12 +211,14 @@
      * Constructor for a key on <code>MoreKeyKeyboard</code>, on <code>MoreSuggestions</code>,
      * and in a <GridRows/>.
      */
-    public Key(final String label, final int iconId, final int code, final String outputText,
-            final String hintLabel, final int labelFlags, final int backgroundType, final int x,
-            final int y, final int width, final int height, final int horizontalGap,
-            final int verticalGap) {
-        mHeight = height - verticalGap;
+    public Key(@Nullable final String label, final int iconId, final int code,
+            @Nullable final String outputText, @Nullable final String hintLabel,
+            final int labelFlags, final int backgroundType, final int x, final int y,
+            final int width, final int height, final int horizontalGap, final int verticalGap) {
         mWidth = width - horizontalGap;
+        mHeight = height - verticalGap;
+        mHorizontalGap = horizontalGap;
+        mVerticalGap = verticalGap;
         mHintLabel = hintLabel;
         mLabelFlags = labelFlags;
         mBackgroundType = backgroundType;
@@ -214,7 +233,7 @@
         mEnabled = (code != CODE_UNSPECIFIED);
         mIconId = iconId;
         // Horizontal gap is divided equally to both sides of the key.
-        mX = x + horizontalGap / 2;
+        mX = x + mHorizontalGap / 2;
         mY = y;
         mHitBox.set(x, y, x + width + 1, y + height);
         mKeyVisualAttributes = null;
@@ -233,20 +252,24 @@
      * @param row the row that this key belongs to. row's x-coordinate will be the right edge of
      *        this key.
      */
-    public Key(final String keySpec, final TypedArray keyAttr, final KeyStyle style,
-            final KeyboardParams params, final KeyboardRow row) {
-        final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
+    public Key(@Nullable final String keySpec, @Nonnull final TypedArray keyAttr,
+            @Nonnull final KeyStyle style, @Nonnull final KeyboardParams params,
+            @Nonnull final KeyboardRow row) {
+        mHorizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
+        mVerticalGap = params.mVerticalGap;
+
+        final float horizontalGapFloat = mHorizontalGap;
         final int rowHeight = row.getRowHeight();
-        mHeight = rowHeight - params.mVerticalGap;
+        mHeight = rowHeight - mVerticalGap;
 
         final float keyXPos = row.getKeyX(keyAttr);
         final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
         final int keyYPos = row.getKeyY();
 
         // Horizontal gap is divided equally to both sides of the key.
-        mX = Math.round(keyXPos + horizontalGap / 2);
+        mX = Math.round(keyXPos + horizontalGapFloat / 2);
         mY = keyYPos;
-        mWidth = Math.round(keyWidth - horizontalGap);
+        mWidth = Math.round(keyWidth - horizontalGapFloat);
         mHitBox.set(Math.round(keyXPos), keyYPos, Math.round(keyXPos + keyWidth) + 1,
                 keyYPos + rowHeight);
         // Update row to have current x coordinate.
@@ -263,8 +286,8 @@
 
         mLabelFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
                 | row.getDefaultKeyLabelFlags();
-        final boolean needsToUpperCase = needsToUpperCase(mLabelFlags, params.mId.mElementId);
-        final Locale locale = params.mId.mLocale;
+        final boolean needsToUpcase = needsToUpcase(mLabelFlags, params.mId.mElementId);
+        final Locale localeForUpcasing = params.mId.getLocale();
         int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
         String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
 
@@ -306,7 +329,7 @@
             actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
             mMoreKeys = new MoreKeySpec[moreKeys.length];
             for (int i = 0; i < moreKeys.length; i++) {
-                mMoreKeys[i] = new MoreKeySpec(moreKeys[i], needsToUpperCase, locale);
+                mMoreKeys[i] = new MoreKeySpec(moreKeys[i], needsToUpcase, localeForUpcasing);
             }
         } else {
             mMoreKeys = null;
@@ -326,17 +349,24 @@
             // code point nor as a surrogate pair.
             mLabel = new StringBuilder().appendCodePoint(code).toString();
         } else {
-            mLabel = StringUtils.toUpperCaseOfStringForLocale(
-                    KeySpecParser.getLabel(keySpec), needsToUpperCase, locale);
+            final String label = KeySpecParser.getLabel(keySpec);
+            mLabel = needsToUpcase
+                    ? StringUtils.toTitleCaseOfKeyLabel(label, localeForUpcasing)
+                    : label;
         }
         if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
             mHintLabel = null;
         } else {
-            mHintLabel = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr,
-                    R.styleable.Keyboard_Key_keyHintLabel), needsToUpperCase, locale);
+            final String hintLabel = style.getString(
+                    keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
+            mHintLabel = needsToUpcase
+                    ? StringUtils.toTitleCaseOfKeyLabel(hintLabel, localeForUpcasing)
+                    : hintLabel;
         }
-        String outputText = StringUtils.toUpperCaseOfStringForLocale(
-                KeySpecParser.getOutputText(keySpec), needsToUpperCase, locale);
+        String outputText = KeySpecParser.getOutputText(keySpec);
+        if (needsToUpcase) {
+            outputText = StringUtils.toTitleCaseOfKeyLabel(outputText, localeForUpcasing);
+        }
         // Choose the first letter of the label as primary code if not specified.
         if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
                 && !TextUtils.isEmpty(mLabel)) {
@@ -362,12 +392,14 @@
                 mCode = CODE_OUTPUT_TEXT;
             }
         } else {
-            mCode = StringUtils.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale);
+            mCode = needsToUpcase ? StringUtils.toTitleCaseOfKeyCode(code, localeForUpcasing)
+                    : code;
         }
         final int altCodeInAttr = KeySpecParser.parseCode(
                 style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED);
-        final int altCode = StringUtils.toUpperCaseOfCodeForLocale(
-                altCodeInAttr, needsToUpperCase, locale);
+        final int altCode = needsToUpcase
+                ? StringUtils.toTitleCaseOfKeyCode(altCodeInAttr, localeForUpcasing)
+                : altCodeInAttr;
         mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode,
                 disabledIconId, visualInsetsLeft, visualInsetsRight);
         mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
@@ -379,7 +411,11 @@
      *
      * @param key the original key.
      */
-    protected Key(final Key key) {
+    protected Key(@Nonnull final Key key) {
+        this(key, key.mMoreKeys);
+    }
+
+    private Key(@Nonnull final Key key, @Nullable final MoreKeySpec[] moreKeys) {
         // Final attributes.
         mCode = key.mCode;
         mLabel = key.mLabel;
@@ -388,10 +424,12 @@
         mIconId = key.mIconId;
         mWidth = key.mWidth;
         mHeight = key.mHeight;
+        mHorizontalGap = key.mHorizontalGap;
+        mVerticalGap = key.mVerticalGap;
         mX = key.mX;
         mY = key.mY;
         mHitBox.set(key.mHitBox);
-        mMoreKeys = key.mMoreKeys;
+        mMoreKeys = moreKeys;
         mMoreKeysColumnAndFlags = key.mMoreKeysColumnAndFlags;
         mBackgroundType = key.mBackgroundType;
         mActionFlags = key.mActionFlags;
@@ -403,7 +441,16 @@
         mEnabled = key.mEnabled;
     }
 
-    private static boolean needsToUpperCase(final int labelFlags, final int keyboardElementId) {
+    @Nonnull
+    public static Key removeRedundantMoreKeys(@Nonnull final Key key,
+            @Nonnull final MoreKeySpec.LettersOnBaseLayout lettersOnBaseLayout) {
+        final MoreKeySpec[] moreKeys = key.getMoreKeys();
+        final MoreKeySpec[] filteredMoreKeys = MoreKeySpec.removeRedundantMoreKeys(
+                moreKeys, lettersOnBaseLayout);
+        return (filteredMoreKeys == moreKeys) ? key : new Key(key, filteredMoreKeys);
+    }
+
+    private static boolean needsToUpcase(final int labelFlags, final int keyboardElementId) {
         if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false;
         switch (keyboardElementId) {
         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
@@ -516,14 +563,17 @@
         return mCode;
     }
 
+    @Nullable
     public String getLabel() {
         return mLabel;
     }
 
+    @Nullable
     public String getHintLabel() {
         return mHintLabel;
     }
 
+    @Nullable
     public MoreKeySpec[] getMoreKeys() {
         return mMoreKeys;
     }
@@ -582,6 +632,7 @@
         return mKeyVisualAttributes;
     }
 
+    @Nonnull
     public final Typeface selectTypeface(final KeyDrawParams params) {
         switch (mLabelFlags & LABEL_FLAGS_FONT_MASK) {
         case LABEL_FLAGS_FONT_NORMAL:
@@ -658,6 +709,7 @@
         return params.mLetterSize;
     }
 
+    @Nonnull
     public Typeface selectPreviewTypeface(final KeyDrawParams params) {
         if (previewHasLetterSize()) {
             return selectTypeface(params);
@@ -742,6 +794,7 @@
         return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_NO_PANEL_AUTO_MORE_KEY) != 0;
     }
 
+    @Nullable
     public final String getOutputText() {
         final OptionalAttributes attrs = mOptionalAttributes;
         return (attrs != null) ? attrs.mOutputText : null;
@@ -756,6 +809,7 @@
         return mIconId;
     }
 
+    @Nullable
     public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) {
         final OptionalAttributes attrs = mOptionalAttributes;
         final int disabledIconId = (attrs != null) ? attrs.mDisabledIconId : ICON_UNDEFINED;
@@ -767,22 +821,57 @@
         return icon;
     }
 
+    @Nullable
     public Drawable getPreviewIcon(final KeyboardIconsSet iconSet) {
         return iconSet.getIconDrawable(getIconId());
     }
 
+    /**
+     * Gets the width of the key in pixels, excluding the gap.
+     * @return The width of the key in pixels, excluding the gap.
+     */
     public int getWidth() {
         return mWidth;
     }
 
+    /**
+     * Gets the height of the key in pixels, excluding the gap.
+     * @return The height of the key in pixels, excluding the gap.
+     */
     public int getHeight() {
         return mHeight;
     }
 
+    /**
+     * The combined width in pixels of the horizontal gaps belonging to this key, both above and
+     * below. I.e., getWidth() + getHorizontalGap() = total width belonging to the key.
+     * @return Horizontal gap belonging to this key.
+     */
+    public int getHorizontalGap() {
+        return mHorizontalGap;
+    }
+
+    /**
+     * The combined height in pixels of the vertical gaps belonging to this key, both above and
+     * below. I.e., getHeight() + getVerticalGap() = total height belonging to the key.
+     * @return Vertical gap belonging to this key.
+     */
+    public int getVerticalGap() {
+        return mVerticalGap;
+    }
+
+    /**
+     * Gets the x-coordinate of the top-left corner of the key in pixels, excluding the gap.
+     * @return The x-coordinate of the top-left corner of the key in pixels, excluding the gap.
+     */
     public int getX() {
         return mX;
     }
 
+    /**
+     * Gets the y-coordinate of the top-left corner of the key in pixels, excluding the gap.
+     * @return The y-coordinate of the top-left corner of the key in pixels, excluding the gap.
+     */
     public int getY() {
         return mY;
     }
@@ -825,6 +914,7 @@
         mEnabled = enabled;
     }
 
+    @Nonnull
     public Rect getHitBox() {
         return mHitBox;
     }
@@ -896,8 +986,10 @@
      * @return the background drawable of the key.
      * @see android.graphics.drawable.StateListDrawable#setState(int[])
      */
-    public final Drawable selectBackgroundDrawable(final Drawable keyBackground,
-            final Drawable functionalKeyBackground, final Drawable spacebarBackground) {
+    @Nonnull
+    public final Drawable selectBackgroundDrawable(@Nonnull final Drawable keyBackground,
+            @Nonnull final Drawable functionalKeyBackground,
+            @Nonnull final Drawable spacebarBackground) {
         final Drawable background;
         if (mBackgroundType == BACKGROUND_TYPE_FUNCTIONAL) {
             background = functionalKeyBackground;
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 85dfea4..7318d47 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -21,13 +21,16 @@
 import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
  * consists of rows of keys.
@@ -47,6 +50,7 @@
  * </pre>
  */
 public class Keyboard {
+    @Nonnull
     public final KeyboardId mId;
     public final int mThemeId;
 
@@ -78,17 +82,25 @@
     public final int mMaxMoreKeysKeyboardColumn;
 
     /** List of keys in this keyboard */
+    @Nonnull
     private final List<Key> mSortedKeys;
+    @Nonnull
     public final List<Key> mShiftKeys;
+    @Nonnull
     public final List<Key> mAltCodeKeysWhileTyping;
+    @Nonnull
     public final KeyboardIconsSet mIconsSet;
 
     private final SparseArray<Key> mKeyCache = new SparseArray<>();
 
+    @Nonnull
     private final ProximityInfo mProximityInfo;
+    @Nonnull
+    private final KeyboardLayout mKeyboardLayout;
+
     private final boolean mProximityCharsCorrectionEnabled;
 
-    public Keyboard(final KeyboardParams params) {
+    public Keyboard(@Nonnull final KeyboardParams params) {
         mId = params.mId;
         mThemeId = params.mThemeId;
         mOccupiedHeight = params.mOccupiedHeight;
@@ -108,14 +120,15 @@
         mAltCodeKeysWhileTyping = Collections.unmodifiableList(params.mAltCodeKeysWhileTyping);
         mIconsSet = params.mIconsSet;
 
-        mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(),
-                params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
-                mMostCommonKeyWidth, mMostCommonKeyHeight, mSortedKeys,
-                params.mTouchPositionCorrection);
+        mProximityInfo = new ProximityInfo(params.GRID_WIDTH, params.GRID_HEIGHT,
+                mOccupiedWidth, mOccupiedHeight, mMostCommonKeyWidth, mMostCommonKeyHeight,
+                mSortedKeys, params.mTouchPositionCorrection);
         mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;
+        mKeyboardLayout = KeyboardLayout.newKeyboardLayout(mSortedKeys, mMostCommonKeyWidth,
+                mMostCommonKeyHeight, mOccupiedWidth, mOccupiedHeight);
     }
 
-    protected Keyboard(final Keyboard keyboard) {
+    protected Keyboard(@Nonnull final Keyboard keyboard) {
         mId = keyboard.mId;
         mThemeId = keyboard.mThemeId;
         mOccupiedHeight = keyboard.mOccupiedHeight;
@@ -137,6 +150,7 @@
 
         mProximityInfo = keyboard.mProximityInfo;
         mProximityCharsCorrectionEnabled = keyboard.mProximityCharsCorrectionEnabled;
+        mKeyboardLayout = keyboard.mKeyboardLayout;
     }
 
     public boolean hasProximityCharsCorrection(final int code) {
@@ -151,20 +165,28 @@
         return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);
     }
 
+    @Nonnull
     public ProximityInfo getProximityInfo() {
         return mProximityInfo;
     }
 
+    @Nonnull
+    public KeyboardLayout getKeyboardLayout() {
+        return mKeyboardLayout;
+    }
+
     /**
      * Return the sorted list of keys of this keyboard.
      * The keys are sorted from top-left to bottom-right order.
      * The list may contain {@link Key.Spacer} object as well.
      * @return the sorted unmodifiable list of {@link Key}s of this keyboard.
      */
+    @Nonnull
     public List<Key> getSortedKeys() {
         return mSortedKeys;
     }
 
+    @Nullable
     public Key getKey(final int code) {
         if (code == Constants.CODE_UNSPECIFIED) {
             return null;
@@ -186,7 +208,7 @@
         }
     }
 
-    public boolean hasKey(final Key aKey) {
+    public boolean hasKey(@Nonnull final Key aKey) {
         if (mKeyCache.indexOfValue(aKey) >= 0) {
             return true;
         }
@@ -212,6 +234,7 @@
      * @return the list of the nearest keys to the given point. If the given
      * point is out of range, then an array of size zero is returned.
      */
+    @Nonnull
     public List<Key> getNearestKeys(final int x, final int y) {
         // Avoid dead pixels at edges of the keyboard
         final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
@@ -219,7 +242,8 @@
         return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
     }
 
-    public int[] getCoordinates(final int[] codePoints) {
+    @Nonnull
+    public int[] getCoordinates(@Nonnull final int[] codePoints) {
         final int length = codePoints.length;
         final int[] coordinates = CoordinateUtils.newCoordinateArray(length);
         for (int i = 0; i < length; ++i) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index c565866..cdd632b 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -16,8 +16,8 @@
 
 package com.android.inputmethod.keyboard;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.InputPointers;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
 
 public interface KeyboardActionListener {
     /**
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 3c11675..a1f7bf0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -16,16 +16,15 @@
 
 package com.android.inputmethod.keyboard;
 
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
 
 import android.text.InputType;
 import android.text.TextUtils;
 import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.compat.EditorInfoCompatUtils;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Arrays;
 import java.util.Locale;
@@ -62,8 +61,7 @@
     public static final int ELEMENT_EMOJI_CATEGORY5 = 15;
     public static final int ELEMENT_EMOJI_CATEGORY6 = 16;
 
-    public final InputMethodSubtype mSubtype;
-    public final Locale mLocale;
+    public final RichInputMethodSubtype mSubtype;
     public final int mWidth;
     public final int mHeight;
     public final int mMode;
@@ -73,12 +71,12 @@
     public final boolean mLanguageSwitchKeyEnabled;
     public final String mCustomActionLabel;
     public final boolean mHasShortcutKey;
+    public final boolean mIsSplitLayout;
 
     private final int mHashCode;
 
     public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) {
         mSubtype = params.mSubtype;
-        mLocale = SubtypeLocaleUtils.getSubtypeLocale(mSubtype);
         mWidth = params.mKeyboardWidth;
         mHeight = params.mKeyboardHeight;
         mMode = params.mMode;
@@ -89,6 +87,7 @@
         mCustomActionLabel = (mEditorInfo.actionLabel != null)
                 ? mEditorInfo.actionLabel.toString() : null;
         mHasShortcutKey = params.mVoiceInputKeyEnabled;
+        mIsSplitLayout = params.mIsSplitLayoutEnabled;
 
         mHashCode = computeHashCode(this);
     }
@@ -108,7 +107,8 @@
                 id.mCustomActionLabel,
                 id.navigateNext(),
                 id.navigatePrevious(),
-                id.mSubtype
+                id.mSubtype,
+                id.mIsSplitLayout
         });
     }
 
@@ -128,7 +128,8 @@
                 && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)
                 && other.navigateNext() == navigateNext()
                 && other.navigatePrevious() == navigatePrevious()
-                && other.mSubtype.equals(mSubtype);
+                && other.mSubtype.equals(mSubtype)
+                && other.mIsSplitLayout == mIsSplitLayout;
     }
 
     private static boolean isAlphabetKeyboard(final int elementId) {
@@ -163,6 +164,10 @@
         return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo);
     }
 
+    public Locale getLocale() {
+        return mSubtype.getLocale();
+    }
+
     @Override
     public boolean equals(final Object other) {
         return other instanceof KeyboardId && equals((KeyboardId) other);
@@ -175,9 +180,10 @@
 
     @Override
     public String toString() {
-        return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s]",
+        return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]",
                 elementIdToName(mElementId),
-                mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
+                mSubtype.getLocale(),
+                mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
                 mWidth, mHeight,
                 modeName(mMode),
                 actionName(imeAction()),
@@ -187,7 +193,8 @@
                 (passwordInput() ? " passwordInput" : ""),
                 (mHasShortcutKey ? " hasShortcutKey" : ""),
                 (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
-                (isMultiLine() ? " isMultiLine" : "")
+                (isMultiLine() ? " isMultiLine" : ""),
+                (mIsSplitLayout ? " isSplitLayout" : "")
         );
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayout.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayout.java
new file mode 100644
index 0000000..d0f3207
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayout.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015 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;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * KeyboardLayout maintains the keyboard layout information.
+ */
+public class KeyboardLayout {
+
+    private final int[] mKeyCodes;
+
+    private final int[] mKeyXCoordinates;
+    private final int[] mKeyYCoordinates;
+
+    private final int[] mKeyWidths;
+    private final int[] mKeyHeights;
+
+    public final int mMostCommonKeyWidth;
+    public final int mMostCommonKeyHeight;
+
+    public final int mKeyboardWidth;
+    public final int mKeyboardHeight;
+
+    public KeyboardLayout(ArrayList<Key> layoutKeys, int mostCommonKeyWidth,
+            int mostCommonKeyHeight, int keyboardWidth, int keyboardHeight) {
+        mMostCommonKeyWidth = mostCommonKeyWidth;
+        mMostCommonKeyHeight = mostCommonKeyHeight;
+        mKeyboardWidth = keyboardWidth;
+        mKeyboardHeight = keyboardHeight;
+
+        mKeyCodes = new int[layoutKeys.size()];
+        mKeyXCoordinates = new int[layoutKeys.size()];
+        mKeyYCoordinates = new int[layoutKeys.size()];
+        mKeyWidths = new int[layoutKeys.size()];
+        mKeyHeights = new int[layoutKeys.size()];
+
+        for (int i = 0; i < layoutKeys.size(); i++) {
+            Key key = layoutKeys.get(i);
+            mKeyCodes[i] = Character.toLowerCase(key.getCode());
+            mKeyXCoordinates[i] = key.getX();
+            mKeyYCoordinates[i] = key.getY();
+            mKeyWidths[i] = key.getWidth();
+            mKeyHeights[i] = key.getHeight();
+        }
+    }
+
+    @UsedForTesting
+    public int[] getKeyCodes() {
+        return mKeyCodes;
+    }
+
+    /**
+     * The x-coordinate for the top-left corner of the keys.
+     *
+     */
+    public int[] getKeyXCoordinates() {
+        return mKeyXCoordinates;
+    }
+
+    /**
+     * The y-coordinate for the top-left corner of the keys.
+     */
+    public int[] getKeyYCoordinates() {
+        return mKeyYCoordinates;
+    }
+
+    /**
+     * The widths of the keys which are smaller than the true hit-area due to the gaps
+     * between keys. The mostCommonKey(Width/Height) represents the true key width/height
+     * including the gaps.
+     */
+    public int[] getKeyWidths() {
+        return mKeyWidths;
+    }
+
+    /**
+     * The heights of the keys which are smaller than the true hit-area due to the gaps
+     * between keys. The mostCommonKey(Width/Height) represents the true key width/height
+     * including the gaps.
+     */
+    public int[] getKeyHeights() {
+        return mKeyHeights;
+    }
+
+    /**
+     * Factory method to create {@link KeyboardLayout} objects.
+     */
+    public static KeyboardLayout newKeyboardLayout(@Nonnull final List<Key> sortedKeys,
+            int mostCommonKeyWidth, int mostCommonKeyHeight,
+            int occupiedWidth, int occupiedHeight) {
+        final ArrayList<Key> layoutKeys = new ArrayList<Key>();
+        for (final Key key : sortedKeys) {
+            if (!ProximityInfo.needsProximityInfo(key)) {
+                continue;
+            }
+            if (key.getCode() != ',') {
+                layoutKeys.add(key);
+            }
+        }
+        return new KeyboardLayout(layoutKeys, mostCommonKeyWidth,
+                mostCommonKeyHeight, occupiedWidth, occupiedHeight);
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index feb79ef..47013fe 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -16,8 +16,8 @@
 
 package com.android.inputmethod.keyboard;
 
-import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_SETTINGS_KEY;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_SETTINGS_KEY;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -34,10 +34,10 @@
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
 import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
-import com.android.inputmethod.keyboard.internal.KeysCache;
+import com.android.inputmethod.keyboard.internal.UniqueKeysCache;
 import com.android.inputmethod.latin.InputAttributes;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
 import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
@@ -51,6 +51,9 @@
 import java.lang.ref.SoftReference;
 import java.util.HashMap;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * This class represents a set of keyboard layouts. Each of them represents a different keyboard
  * specific to a keyboard state, such as alphabet, symbols, and so on.  Layouts in the same
@@ -60,7 +63,7 @@
  */
 public final class KeyboardLayoutSet {
     private static final String TAG = KeyboardLayoutSet.class.getSimpleName();
-    private static final boolean DEBUG_CACHE = DebugFlags.DEBUG_ENABLED;
+    private static final boolean DEBUG_CACHE = false;
 
     private static final String TAG_KEYBOARD_SET = "KeyboardLayoutSet";
     private static final String TAG_ELEMENT = "Element";
@@ -69,6 +72,7 @@
     private static final String KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX = "keyboard_layout_set_";
 
     private final Context mContext;
+    @Nonnull
     private final Params mParams;
 
     // How many layouts we forcibly keep in cache. This only includes ALPHABET (default) and
@@ -81,7 +85,10 @@
     private static final Keyboard[] sForcibleKeyboardCache = new Keyboard[FORCIBLE_CACHE_SIZE];
     private static final HashMap<KeyboardId, SoftReference<Keyboard>> sKeyboardCache =
             new HashMap<>();
-    private static final KeysCache sKeysCache = new KeysCache();
+    @Nonnull
+    private static final UniqueKeysCache sUniqueKeysCache = UniqueKeysCache.newInstance();
+    private final static HashMap<InputMethodSubtype, Integer> sScriptIdsForSubtypes =
+            new HashMap<>();
 
     @SuppressWarnings("serial")
     public static final class KeyboardLayoutSetException extends RuntimeException {
@@ -96,6 +103,8 @@
     private static final class ElementParams {
         int mKeyboardXmlId;
         boolean mProximityCharsCorrectionEnabled;
+        boolean mSupportsSplitLayout;
+        boolean mAllowRedundantMoreKeys;
         public ElementParams() {}
     }
 
@@ -109,11 +118,17 @@
         boolean mVoiceInputKeyEnabled;
         boolean mNoSettingsKey;
         boolean mLanguageSwitchKeyEnabled;
-        InputMethodSubtype mSubtype;
+        RichInputMethodSubtype mSubtype;
         boolean mIsSpellChecker;
         int mKeyboardWidth;
         int mKeyboardHeight;
         int mScriptId = ScriptUtils.SCRIPT_LATIN;
+        // Indicates if the user has enabled the split-layout preference
+        // and the required ProductionFlags are enabled.
+        boolean mIsSplitLayoutEnabledByUser;
+        // Indicates if split layout is actually enabled, taking into account
+        // whether the user has enabled it, and the keyboard layout supports it.
+        boolean mIsSplitLayoutEnabled;
         // Sparse array of KeyboardLayoutSet element parameters indexed by element's id.
         final SparseArray<ElementParams> mKeyboardLayoutSetElementIdToParamsMap =
                 new SparseArray<>();
@@ -129,14 +144,26 @@
 
     private static void clearKeyboardCache() {
         sKeyboardCache.clear();
-        sKeysCache.clear();
+        sUniqueKeysCache.clear();
     }
 
-    KeyboardLayoutSet(final Context context, final Params params) {
+    public static int getScriptId(final Resources resources,
+            @Nonnull final InputMethodSubtype subtype) {
+        final Integer value = sScriptIdsForSubtypes.get(subtype);
+        if (null == value) {
+            final int scriptId = Builder.readScriptId(resources, subtype);
+            sScriptIdsForSubtypes.put(subtype, scriptId);
+            return scriptId;
+        }
+        return value;
+    }
+
+    KeyboardLayoutSet(final Context context, @Nonnull final Params params) {
         mContext = context;
         mParams = params;
     }
 
+    @Nonnull
     public Keyboard getKeyboard(final int baseKeyboardLayoutSetElementId) {
         final int keyboardLayoutSetElementId;
         switch (mParams.mMode) {
@@ -168,6 +195,9 @@
         // attribute in a keyboard_layout_set XML file.  Also each keyboard layout XML resource is
         // specified as an elementKeyboard attribute in the file.
         // The KeyboardId is an internal key for a Keyboard object.
+
+        mParams.mIsSplitLayoutEnabled = mParams.mIsSplitLayoutEnabledByUser
+                && elementParams.mSupportsSplitLayout;
         final KeyboardId id = new KeyboardId(keyboardLayoutSetElementId, mParams);
         try {
             return getKeyboard(elementParams, id);
@@ -177,6 +207,7 @@
         }
     }
 
+    @Nonnull
     private Keyboard getKeyboard(final ElementParams elementParams, final KeyboardId id) {
         final SoftReference<Keyboard> ref = sKeyboardCache.get(id);
         final Keyboard cachedKeyboard = (ref == null) ? null : ref.get();
@@ -188,10 +219,9 @@
         }
 
         final KeyboardBuilder<KeyboardParams> builder =
-                new KeyboardBuilder<>(mContext, new KeyboardParams());
-        if (id.isAlphabetKeyboard()) {
-            builder.setAutoGenerate(sKeysCache);
-        }
+                new KeyboardBuilder<>(mContext, new KeyboardParams(sUniqueKeysCache));
+        sUniqueKeysCache.setEnabled(id.isAlphabetKeyboard());
+        builder.setAllowRedundantMoreKes(elementParams.mAllowRedundantMoreKeys);
         final int keyboardXmlId = elementParams.mKeyboardXmlId;
         builder.load(keyboardXmlId, id);
         if (mParams.mDisableTouchPositionCorrectionDataForTest) {
@@ -232,7 +262,7 @@
 
         private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo();
 
-        public Builder(final Context context, final EditorInfo ei) {
+        public Builder(final Context context, @Nullable final EditorInfo ei) {
             mContext = context;
             mPackageName = context.getPackageName();
             mResources = context.getResources();
@@ -253,7 +283,7 @@
             return this;
         }
 
-        public Builder setSubtype(final InputMethodSubtype subtype) {
+        public Builder setSubtype(@Nonnull final RichInputMethodSubtype subtype) {
             final boolean asciiCapable = InputMethodSubtypeCompatUtils.isAsciiCapable(subtype);
             // TODO: Consolidate with {@link InputAttributes}.
             @SuppressWarnings("deprecation")
@@ -262,12 +292,12 @@
             final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
                     mParams.mEditorInfo.imeOptions)
                     || deprecatedForceAscii;
-            final InputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
-                    ? SubtypeSwitcher.getInstance().getNoLanguageSubtype()
+            final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
+                    ? RichInputMethodSubtype.getNoLanguageSubtype()
                     : subtype;
             mParams.mSubtype = keyboardSubtype;
             mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
-                    + SubtypeLocaleUtils.getKeyboardLayoutSetName(keyboardSubtype);
+                    + keyboardSubtype.getKeyboardLayoutSetName();
             return this;
         }
 
@@ -286,31 +316,75 @@
             return this;
         }
 
-        public void disableTouchPositionCorrectionData() {
+        public Builder disableTouchPositionCorrectionData() {
             mParams.mDisableTouchPositionCorrectionDataForTest = true;
+            return this;
         }
 
-        public void setScriptId(final int scriptId) {
-            mParams.mScriptId = scriptId;
+        public Builder setSplitLayoutEnabledByUser(final boolean enabled) {
+            mParams.mIsSplitLayoutEnabledByUser = enabled;
+            return this;
+        }
+
+        // Super redux version of reading the script ID for some subtype from Xml.
+        static int readScriptId(final Resources resources, final InputMethodSubtype subtype) {
+            final String layoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX
+                    + SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
+            final int xmlId = getXmlId(resources, layoutSetName);
+            final XmlResourceParser parser = resources.getXml(xmlId);
+            try {
+                while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                    // Bovinate through the XML stupidly searching for TAG_FEATURE, and read
+                    // the script Id from it.
+                    parser.next();
+                    final String tag = parser.getName();
+                    if (TAG_FEATURE.equals(tag)) {
+                        return readScriptIdFromTagFeature(resources, parser);
+                    }
+                }
+            } catch (final IOException | XmlPullParserException e) {
+                throw new RuntimeException(e.getMessage() + " in " + layoutSetName, e);
+            } finally {
+                parser.close();
+            }
+            // If the tag is not found, then the default script is Latin.
+            return ScriptUtils.SCRIPT_LATIN;
+        }
+
+        private static int readScriptIdFromTagFeature(final Resources resources,
+                final XmlPullParser parser) throws IOException, XmlPullParserException {
+            final TypedArray featureAttr = resources.obtainAttributes(Xml.asAttributeSet(parser),
+                    R.styleable.KeyboardLayoutSet_Feature);
+            try {
+                final int scriptId =
+                        featureAttr.getInt(R.styleable.KeyboardLayoutSet_Feature_supportedScript,
+                                ScriptUtils.SCRIPT_UNKNOWN);
+                XmlParseUtils.checkEndTag(TAG_FEATURE, parser);
+                return scriptId;
+            } finally {
+                featureAttr.recycle();
+            }
         }
 
         public KeyboardLayoutSet build() {
             if (mParams.mSubtype == null)
                 throw new RuntimeException("KeyboardLayoutSet subtype is not specified");
-            final String packageName = mResources.getResourcePackageName(
-                    R.xml.keyboard_layout_set_qwerty);
-            final String keyboardLayoutSetName = mParams.mKeyboardLayoutSetName;
-            final int xmlId = mResources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
+            final int xmlId = getXmlId(mResources, mParams.mKeyboardLayoutSetName);
             try {
                 parseKeyboardLayoutSet(mResources, xmlId);
-            } catch (final IOException e) {
-                throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
-            } catch (final XmlPullParserException e) {
-                throw new RuntimeException(e.getMessage() + " in " + keyboardLayoutSetName, e);
+            } catch (final IOException | XmlPullParserException e) {
+                throw new RuntimeException(e.getMessage() + " in " + mParams.mKeyboardLayoutSetName,
+                        e);
             }
             return new KeyboardLayoutSet(mContext, mParams);
         }
 
+        private static int getXmlId(final Resources resources, final String keyboardLayoutSetName) {
+            final String packageName = resources.getResourcePackageName(
+                    R.xml.keyboard_layout_set_qwerty);
+            return resources.getIdentifier(keyboardLayoutSetName, "xml", packageName);
+        }
+
         private void parseKeyboardLayoutSet(final Resources res, final int resId)
                 throws XmlPullParserException, IOException {
             final XmlResourceParser parser = res.getXml(resId);
@@ -340,7 +414,7 @@
                     if (TAG_ELEMENT.equals(tag)) {
                         parseKeyboardLayoutSetElement(parser);
                     } else if (TAG_FEATURE.equals(tag)) {
-                        parseKeyboardLayoutSetFeature(parser);
+                        mParams.mScriptId = readScriptIdFromTagFeature(mResources, parser);
                     } else {
                         throw new XmlParseUtils.IllegalStartTag(parser, tag, TAG_KEYBOARD_SET);
                     }
@@ -348,9 +422,8 @@
                     final String tag = parser.getName();
                     if (TAG_KEYBOARD_SET.equals(tag)) {
                         break;
-                    } else {
-                        throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
                     }
+                    throw new XmlParseUtils.IllegalEndTag(parser, tag, TAG_KEYBOARD_SET);
                 }
             }
         }
@@ -376,27 +449,16 @@
                 elementParams.mProximityCharsCorrectionEnabled = a.getBoolean(
                         R.styleable.KeyboardLayoutSet_Element_enableProximityCharsCorrection,
                         false);
+                elementParams.mSupportsSplitLayout = a.getBoolean(
+                        R.styleable.KeyboardLayoutSet_Element_supportsSplitLayout, false);
+                elementParams.mAllowRedundantMoreKeys = a.getBoolean(
+                        R.styleable.KeyboardLayoutSet_Element_allowRedundantMoreKeys, true);
                 mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams);
             } finally {
                 a.recycle();
             }
         }
 
-        private void parseKeyboardLayoutSetFeature(final XmlPullParser parser)
-                throws XmlPullParserException, IOException {
-            final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
-                    R.styleable.KeyboardLayoutSet_Feature);
-            try {
-                final int scriptId = a.getInt(
-                        R.styleable.KeyboardLayoutSet_Feature_supportedScript,
-                        ScriptUtils.SCRIPT_LATIN);
-                XmlParseUtils.checkEndTag(TAG_FEATURE, parser);
-                setScriptId(scriptId);
-            } finally {
-                a.recycle();
-            }
-        }
-
         private static int getKeyboardMode(final EditorInfo editorInfo) {
             final int inputType = editorInfo.inputType;
             final int variation = inputType & InputType.TYPE_MASK_VARIATION;
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 60665f8..92e5dfc 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -17,9 +17,7 @@
 package com.android.inputmethod.keyboard;
 
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.content.res.Resources;
-import android.preference.PreferenceManager;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -27,6 +25,7 @@
 import android.view.inputmethod.EditorInfo;
 
 import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
+import com.android.inputmethod.event.Event;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
 import com.android.inputmethod.keyboard.emoji.EmojiPalettesView;
 import com.android.inputmethod.keyboard.internal.KeyboardState;
@@ -35,24 +34,25 @@
 import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.SubtypeSwitcher;
 import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.define.ProductionFlags;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
+import com.android.inputmethod.latin.utils.CapsModeUtils;
+import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
+import com.android.inputmethod.latin.utils.RecapitalizeStatus;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
 
 public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
     private static final String TAG = KeyboardSwitcher.class.getSimpleName();
 
-    private SubtypeSwitcher mSubtypeSwitcher;
-    private SharedPreferences mPrefs;
-
     private InputView mCurrentInputView;
     private View mMainKeyboardFrame;
     private MainKeyboardView mKeyboardView;
     private EmojiPalettesView mEmojiPalettesView;
     private LatinIME mLatinIME;
+    private RichInputMethodManager mRichImm;
     private boolean mIsHardwareAcceleratedDrawingEnabled;
 
     private KeyboardState mState;
@@ -75,14 +75,12 @@
     }
 
     public static void init(final LatinIME latinIme) {
-        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(latinIme);
-        sInstance.initInternal(latinIme, prefs);
+        sInstance.initInternal(latinIme);
     }
 
-    private void initInternal(final LatinIME latinIme, final SharedPreferences prefs) {
+    private void initInternal(final LatinIME latinIme) {
         mLatinIME = latinIme;
-        mPrefs = prefs;
-        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+        mRichImm = RichInputMethodManager.getInstance();
         mState = new KeyboardState(this);
         mIsHardwareAcceleratedDrawingEnabled =
                 InputMethodServiceCompatUtils.enableHardwareAcceleration(mLatinIME);
@@ -90,7 +88,7 @@
 
     public void updateKeyboardTheme() {
         final boolean themeUpdated = updateKeyboardThemeAndContextThemeWrapper(
-                mLatinIME, KeyboardTheme.getKeyboardTheme(mPrefs));
+                mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
         if (themeUpdated && mKeyboardView != null) {
             mLatinIME.setInputView(onCreateInputView(mIsHardwareAcceleratedDrawingEnabled));
         }
@@ -113,18 +111,19 @@
                 mThemeContext, editorInfo);
         final Resources res = mThemeContext.getResources();
         final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
-        final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
+        final int keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues);
         builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
-        builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype());
+        builder.setSubtype(mRichImm.getCurrentSubtype());
         builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
         builder.setLanguageSwitchKeyEnabled(mLatinIME.shouldShowLanguageSwitchKey());
+        builder.setSplitLayoutEnabledByUser(ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED
+                && settingsValues.mIsSplitKeyboardEnabled);
         mKeyboardLayoutSet = builder.build();
         try {
             mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
-            mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale(), mThemeContext);
+            mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocale(), mThemeContext);
         } catch (KeyboardLayoutSetException e) {
             Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
-            return;
         }
     }
 
@@ -160,12 +159,12 @@
                 currentSettingsValues.mKeyPreviewDismissEndXScale,
                 currentSettingsValues.mKeyPreviewDismissEndYScale,
                 currentSettingsValues.mKeyPreviewDismissDuration);
-        keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
+        keyboardView.updateShortcutKey(mRichImm.isShortcutImeReady());
         final boolean subtypeChanged = (oldKeyboard == null)
-                || !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale);
-        final int languageOnSpacebarFormatType = mSubtypeSwitcher.getLanguageOnSpacebarFormatType(
-                keyboard.mId.mSubtype);
-        final boolean hasMultipleEnabledIMEsOrSubtypes = RichInputMethodManager.getInstance()
+                || !keyboard.mId.mSubtype.equals(oldKeyboard.mId.mSubtype);
+        final int languageOnSpacebarFormatType = LanguageOnSpacebarUtils
+                .getLanguageOnSpacebarFormatType(keyboard.mId.mSubtype);
+        final boolean hasMultipleEnabledIMEsOrSubtypes = mRichImm
                 .hasMultipleEnabledIMEsOrSubtypes(true /* shouldIncludeAuxiliarySubtypes */);
         keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, languageOnSpacebarFormatType,
                 hasMultipleEnabledIMEsOrSubtypes);
@@ -203,42 +202,64 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setAlphabetKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetManualShiftedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setAlphabetManualShiftedKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetAutomaticShiftedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setAlphabetAutomaticShiftedKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setAlphabetShiftLockedKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setAlphabetShiftLockShiftedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setAlphabetShiftLockShiftedKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED));
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setSymbolsKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
     }
 
     private void setMainKeyboardFrame(final SettingsValues settingsValues) {
-        mMainKeyboardFrame.setVisibility(
-                settingsValues.mHasHardwareKeyboard ? View.GONE : View.VISIBLE);
+        final int visibility = settingsValues.mHasHardwareKeyboard ? View.GONE : View.VISIBLE;
+        mKeyboardView.setVisibility(visibility);
+        // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
+        // @see #getVisibleKeyboardView() and
+        // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
+        mMainKeyboardFrame.setVisibility(visibility);
         mEmojiPalettesView.setVisibility(View.GONE);
         mEmojiPalettesView.stopEmojiPalettes();
     }
@@ -246,8 +267,15 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setEmojiKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setEmojiKeyboard");
+        }
         final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
         mMainKeyboardFrame.setVisibility(View.GONE);
+        // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
+        // @see #getVisibleKeyboardView() and
+        // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
+        mKeyboardView.setVisibility(View.GONE);
         mEmojiPalettesView.startEmojiPalettes(
                 mKeyboardTextsSet.getText(KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL),
                 mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet);
@@ -255,8 +283,9 @@
     }
 
     public void onToggleEmojiKeyboard() {
-        if (mKeyboardLayoutSet == null || !isShowingEmojiPalettes()) {
-            mLatinIME.startShowingInputView();
+        final boolean needsToLoadKeyboard = (mKeyboardLayoutSet == null);
+        if (needsToLoadKeyboard || !isShowingEmojiPalettes()) {
+            mLatinIME.startShowingInputView(needsToLoadKeyboard);
             setEmojiKeyboard();
         } else {
             mLatinIME.stopShowingInputView();
@@ -267,18 +296,29 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setSymbolsShiftedKeyboard() {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "setSymbolsShiftedKeyboard");
+        }
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED));
     }
 
     // Future method for requesting an updating to the shift state.
-    public void requestUpdatingShiftState(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
-        mState.onUpdateShiftState(currentAutoCapsState, currentRecapitalizeState);
+    @Override
+    public void requestUpdatingShiftState(final int autoCapsFlags, final int recapitalizeMode) {
+        if (DEBUG_ACTION) {
+            Log.d(TAG, "requestUpdatingShiftState: "
+                    + " autoCapsFlags=" + CapsModeUtils.flagsToString(autoCapsFlags)
+                    + " recapitalizeMode=" + RecapitalizeStatus.modeToString(recapitalizeMode));
+        }
+        mState.onUpdateShiftState(autoCapsFlags, recapitalizeMode);
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void startDoubleTapShiftKeyTimer() {
+        if (DEBUG_TIMER_ACTION) {
+            Log.d(TAG, "startDoubleTapShiftKeyTimer");
+        }
         final MainKeyboardView keyboardView = getMainKeyboardView();
         if (keyboardView != null) {
             keyboardView.startDoubleTapShiftKeyTimer();
@@ -288,6 +328,9 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void cancelDoubleTapShiftKeyTimer() {
+        if (DEBUG_TIMER_ACTION) {
+            Log.d(TAG, "setAlphabetKeyboard");
+        }
         final MainKeyboardView keyboardView = getMainKeyboardView();
         if (keyboardView != null) {
             keyboardView.cancelDoubleTapShiftKeyTimer();
@@ -297,6 +340,9 @@
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public boolean isInDoubleTapShiftKeyTimeout() {
+        if (DEBUG_TIMER_ACTION) {
+            Log.d(TAG, "isInDoubleTapShiftKeyTimeout");
+        }
         final MainKeyboardView keyboardView = getMainKeyboardView();
         return keyboardView != null && keyboardView.isInDoubleTapShiftKeyTimeout();
     }
@@ -304,9 +350,9 @@
     /**
      * Updates state machine to figure out when to automatically switch back to the previous mode.
      */
-    public void onCodeInput(final int code, final int currentAutoCapsState,
+    public void onEvent(final Event event, final int currentAutoCapsState,
             final int currentRecapitalizeState) {
-        mState.onCodeInput(code, currentAutoCapsState, currentRecapitalizeState);
+        mState.onEvent(event, currentAutoCapsState, currentRecapitalizeState);
     }
 
     public boolean isShowingEmojiPalettes() {
@@ -347,7 +393,7 @@
         }
 
         updateKeyboardThemeAndContextThemeWrapper(
-                mLatinIME, KeyboardTheme.getKeyboardTheme(mPrefs));
+                mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
         mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
                 R.layout.input_view, null);
         mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
@@ -363,12 +409,6 @@
         return mCurrentInputView;
     }
 
-    public void onNetworkStateChanged() {
-        if (mKeyboardView != null) {
-            mKeyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
-        }
-    }
-
     public int getKeyboardShiftMode() {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
index 7161d3f..006d086 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
@@ -16,14 +16,17 @@
 
 package com.android.inputmethod.keyboard;
 
+import android.content.Context;
 import android.content.SharedPreferences;
+import android.os.Build;
 import android.os.Build.VERSION_CODES;
+import android.preference.PreferenceManager;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.BuildCompatUtils;
 import com.android.inputmethod.latin.R;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 
 public final class KeyboardTheme implements Comparable<KeyboardTheme> {
@@ -40,7 +43,10 @@
     public static final int THEME_ID_LXX_DARK = 4;
     public static final int DEFAULT_THEME_ID = THEME_ID_KLP;
 
-    private static final KeyboardTheme[] KEYBOARD_THEMES = {
+    private static KeyboardTheme[] AVAILABLE_KEYBOARD_THEMES;
+
+    /* package private for testing */
+    static final KeyboardTheme[] KEYBOARD_THEMES = {
         new KeyboardTheme(THEME_ID_ICS, "ICS", R.style.KeyboardTheme_ICS,
                 // This has never been selected because we support ICS or later.
                 VERSION_CODES.BASE),
@@ -49,8 +55,9 @@
                 VERSION_CODES.ICE_CREAM_SANDWICH),
         new KeyboardTheme(THEME_ID_LXX_LIGHT, "LXXLight", R.style.KeyboardTheme_LXX_Light,
                 // Default theme for LXX.
-                BuildCompatUtils.VERSION_CODES_LXX),
+                Build.VERSION_CODES.LOLLIPOP),
         new KeyboardTheme(THEME_ID_LXX_DARK, "LXXDark", R.style.KeyboardTheme_LXX_Dark,
+                // This has never been selected as default theme.
                 VERSION_CODES.BASE),
     };
 
@@ -62,7 +69,7 @@
     public final int mThemeId;
     public final int mStyleId;
     public final String mThemeName;
-    private final int mMinApiVersion;
+    public final int mMinApiVersion;
 
     // Note: The themeId should be aligned with "themeId" attribute of Keyboard style
     // in values/themes-<style>.xml.
@@ -92,10 +99,11 @@
         return mThemeId;
     }
 
-    @UsedForTesting
-    static KeyboardTheme searchKeyboardThemeById(final int themeId) {
+    /* package private for testing */
+    static KeyboardTheme searchKeyboardThemeById(final int themeId,
+            final KeyboardTheme[] availableThemeIds) {
         // TODO: This search algorithm isn't optimal if there are many themes.
-        for (final KeyboardTheme theme : KEYBOARD_THEMES) {
+        for (final KeyboardTheme theme : availableThemeIds) {
             if (theme.mThemeId == themeId) {
                 return theme;
             }
@@ -103,15 +111,16 @@
         return null;
     }
 
-    @UsedForTesting
+    /* package private for testing */
     static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs,
-            final int sdkVersion) {
+            final int sdkVersion, final KeyboardTheme[] availableThemeArray) {
         final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null);
         if (klpThemeIdString != null) {
             if (sdkVersion <= VERSION_CODES.KITKAT) {
                 try {
                     final int themeId = Integer.parseInt(klpThemeIdString);
-                    final KeyboardTheme theme = searchKeyboardThemeById(themeId);
+                    final KeyboardTheme theme = searchKeyboardThemeById(themeId,
+                            availableThemeArray);
                     if (theme != null) {
                         return theme;
                     }
@@ -125,25 +134,24 @@
             prefs.edit().remove(KLP_KEYBOARD_THEME_KEY).apply();
         }
         // TODO: This search algorithm isn't optimal if there are many themes.
-        for (final KeyboardTheme theme : KEYBOARD_THEMES) {
+        for (final KeyboardTheme theme : availableThemeArray) {
             if (sdkVersion >= theme.mMinApiVersion) {
                 return theme;
             }
         }
-        return searchKeyboardThemeById(DEFAULT_THEME_ID);
+        return searchKeyboardThemeById(DEFAULT_THEME_ID, availableThemeArray);
     }
 
     public static String getKeyboardThemeName(final int themeId) {
-        final KeyboardTheme theme = searchKeyboardThemeById(themeId);
+        final KeyboardTheme theme = searchKeyboardThemeById(themeId, KEYBOARD_THEMES);
         return theme.mThemeName;
     }
 
-    public static void saveKeyboardThemeId(final String themeIdString,
-            final SharedPreferences prefs) {
-        saveKeyboardThemeId(themeIdString, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
+    public static void saveKeyboardThemeId(final int themeId, final SharedPreferences prefs) {
+        saveKeyboardThemeId(themeId, prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
     }
 
-    @UsedForTesting
+    /* package private for testing */
     static String getPreferenceKey(final int sdkVersion) {
         if (sdkVersion <= VERSION_CODES.KITKAT) {
             return KLP_KEYBOARD_THEME_KEY;
@@ -151,26 +159,48 @@
         return LXX_KEYBOARD_THEME_KEY;
     }
 
-    @UsedForTesting
-    static void saveKeyboardThemeId(final String themeIdString,
-            final SharedPreferences prefs, final int sdkVersion) {
+    /* package private for testing */
+    static void saveKeyboardThemeId(final int themeId, final SharedPreferences prefs,
+            final int sdkVersion) {
         final String prefKey = getPreferenceKey(sdkVersion);
-        prefs.edit().putString(prefKey, themeIdString).apply();
+        prefs.edit().putString(prefKey, Integer.toString(themeId)).apply();
     }
 
-    public static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs) {
-        return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT);
+    public static KeyboardTheme getKeyboardTheme(final Context context) {
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        final KeyboardTheme[] availableThemeArray = getAvailableThemeArray(context);
+        return getKeyboardTheme(prefs, BuildCompatUtils.EFFECTIVE_SDK_INT, availableThemeArray);
     }
 
-    @UsedForTesting
-    static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) {
+    /* package private for testing */
+    static KeyboardTheme[] getAvailableThemeArray(final Context context) {
+        if (AVAILABLE_KEYBOARD_THEMES == null) {
+            final int[] availableThemeIdStringArray = context.getResources().getIntArray(
+                    R.array.keyboard_theme_ids);
+            final ArrayList<KeyboardTheme> availableThemeList = new ArrayList<>();
+            for (final int id : availableThemeIdStringArray) {
+                final KeyboardTheme theme = searchKeyboardThemeById(id, KEYBOARD_THEMES);
+                if (theme != null) {
+                    availableThemeList.add(theme);
+                }
+            }
+            AVAILABLE_KEYBOARD_THEMES = availableThemeList.toArray(
+                    new KeyboardTheme[availableThemeList.size()]);
+            Arrays.sort(AVAILABLE_KEYBOARD_THEMES);
+        }
+        return AVAILABLE_KEYBOARD_THEMES;
+    }
+
+    /* package private for testing */
+    static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion,
+            final KeyboardTheme[] availableThemeArray) {
         final String lxxThemeIdString = prefs.getString(LXX_KEYBOARD_THEME_KEY, null);
         if (lxxThemeIdString == null) {
-            return getDefaultKeyboardTheme(prefs, sdkVersion);
+            return getDefaultKeyboardTheme(prefs, sdkVersion, availableThemeArray);
         }
         try {
             final int themeId = Integer.parseInt(lxxThemeIdString);
-            final KeyboardTheme theme = searchKeyboardThemeById(themeId);
+            final KeyboardTheme theme = searchKeyboardThemeById(themeId, availableThemeArray);
             if (theme != null) {
                 return theme;
             }
@@ -180,6 +210,6 @@
         }
         // Remove preference that contains unknown or illegal theme id.
         prefs.edit().remove(LXX_KEYBOARD_THEME_KEY).apply();
-        return getDefaultKeyboardTheme(prefs, sdkVersion);
+        return getDefaultKeyboardTheme(prefs, sdkVersion, availableThemeArray);
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 98cd1da..27e538c 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -25,7 +25,6 @@
 import android.graphics.Paint.Align;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
-import android.graphics.Region;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.NinePatchDrawable;
@@ -35,12 +34,15 @@
 
 import com.android.inputmethod.keyboard.internal.KeyDrawParams;
 import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 
 import java.util.HashSet;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * A view that renders a virtual {@link Keyboard}.
  *
@@ -98,24 +100,28 @@
     private static final float MAX_LABEL_RATIO = 0.90f;
 
     // Main keyboard
+    // TODO: Consider having a dummy keyboard object to make this @Nonnull
+    @Nullable
     private Keyboard mKeyboard;
-    protected final KeyDrawParams mKeyDrawParams = new KeyDrawParams();
+    @Nonnull
+    private final KeyDrawParams mKeyDrawParams = new KeyDrawParams();
 
     // Drawing
     /** True if all keys should be drawn */
     private boolean mInvalidateAllKeys;
     /** The keys that should be drawn */
     private final HashSet<Key> mInvalidatedKeys = new HashSet<>();
-    /** The working rectangle variable */
-    private final Rect mWorkingRect = new Rect();
+    /** The working rectangle for clipping */
+    private final Rect mClipRect = new Rect();
     /** The keyboard bitmap buffer for faster updates */
-    /** The clip region to draw keys */
-    private final Region mClipRegion = new Region();
     private Bitmap mOffscreenBuffer;
     /** The canvas for the above mutable keyboard bitmap */
+    @Nonnull
     private final Canvas mOffscreenCanvas = new Canvas();
+    @Nonnull
     private final Paint mPaint = new Paint();
     private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();
+
     public KeyboardView(final Context context, final AttributeSet attrs) {
         this(context, attrs, R.attr.keyboardViewStyle);
     }
@@ -159,11 +165,12 @@
         mPaint.setAntiAlias(true);
     }
 
+    @Nullable
     public KeyVisualAttributes getKeyVisualAttribute() {
         return mKeyVisualAttributes;
     }
 
-    private static void blendAlpha(final Paint paint, final int alpha) {
+    private static void blendAlpha(@Nonnull final Paint paint, final int alpha) {
         final int color = paint.getColor();
         paint.setARGB((paint.getAlpha() * alpha) / Constants.Color.ALPHA_OPAQUE,
                 Color.red(color), Color.green(color), Color.blue(color));
@@ -182,7 +189,7 @@
      * @see #getKeyboard()
      * @param keyboard the keyboard to display in this view
      */
-    public void setKeyboard(final Keyboard keyboard) {
+    public void setKeyboard(@Nonnull final Keyboard keyboard) {
         mKeyboard = keyboard;
         final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
@@ -196,6 +203,7 @@
      * @return the currently attached keyboard
      * @see #setKeyboard(Keyboard)
      */
+    @Nullable
     public Keyboard getKeyboard() {
         return mKeyboard;
     }
@@ -204,19 +212,25 @@
         return mVerticalCorrection;
     }
 
+    @Nonnull
+    protected KeyDrawParams getKeyDrawParams() {
+        return mKeyDrawParams;
+    }
+
     protected void updateKeyDrawParams(final int keyHeight) {
         mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
     }
 
     @Override
     protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
-        if (mKeyboard == null) {
+        final Keyboard keyboard = getKeyboard();
+        if (keyboard == null) {
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
             return;
         }
         // The main keyboard expands to the entire this {@link KeyboardView}.
-        final int width = mKeyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
-        final int height = mKeyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
+        final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
+        final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
         setMeasuredDimension(width, height);
     }
 
@@ -264,52 +278,45 @@
         }
     }
 
-    private void onDrawKeyboard(final Canvas canvas) {
-        if (mKeyboard == null) return;
+    private void onDrawKeyboard(@Nonnull final Canvas canvas) {
+        final Keyboard keyboard = getKeyboard();
+        if (keyboard == null) {
+            return;
+        }
 
-        final int width = getWidth();
-        final int height = getHeight();
         final Paint paint = mPaint;
-
+        final Drawable background = getBackground();
         // Calculate clip region and set.
         final boolean drawAllKeys = mInvalidateAllKeys || mInvalidatedKeys.isEmpty();
         final boolean isHardwareAccelerated = canvas.isHardwareAccelerated();
         // TODO: Confirm if it's really required to draw all keys when hardware acceleration is on.
         if (drawAllKeys || isHardwareAccelerated) {
-            mClipRegion.set(0, 0, width, height);
-        } else {
-            mClipRegion.setEmpty();
-            for (final Key key : mInvalidatedKeys) {
-                if (mKeyboard.hasKey(key)) {
-                    final int x = key.getX() + getPaddingLeft();
-                    final int y = key.getY() + getPaddingTop();
-                    mWorkingRect.set(x, y, x + key.getWidth(), y + key.getHeight());
-                    mClipRegion.union(mWorkingRect);
-                }
-            }
-        }
-        if (!isHardwareAccelerated) {
-            canvas.clipRegion(mClipRegion, Region.Op.REPLACE);
-            // Draw keyboard background.
-            canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
-            final Drawable background = getBackground();
-            if (background != null) {
+            if (!isHardwareAccelerated && background != null) {
+                // Need to draw keyboard background on {@link #mOffscreenBuffer}.
+                canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
                 background.draw(canvas);
             }
-        }
-
-        // TODO: Confirm if it's really required to draw all keys when hardware acceleration is on.
-        if (drawAllKeys || isHardwareAccelerated) {
             // Draw all keys.
-            for (final Key key : mKeyboard.getSortedKeys()) {
+            for (final Key key : keyboard.getSortedKeys()) {
                 onDrawKey(key, canvas, paint);
             }
         } else {
-            // Draw invalidated keys.
             for (final Key key : mInvalidatedKeys) {
-                if (mKeyboard.hasKey(key)) {
-                    onDrawKey(key, canvas, paint);
+                if (!keyboard.hasKey(key)) {
+                    continue;
                 }
+                if (background != null) {
+                    // Need to redraw key's background on {@link #mOffscreenBuffer}.
+                    final int x = key.getX() + getPaddingLeft();
+                    final int y = key.getY() + getPaddingTop();
+                    mClipRect.set(x, y, x + key.getWidth(), y + key.getHeight());
+                    canvas.save();
+                    canvas.clipRect(mClipRect);
+                    canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
+                    background.draw(canvas);
+                    canvas.restore();
+                }
+                onDrawKey(key, canvas, paint);
             }
         }
 
@@ -317,20 +324,22 @@
         mInvalidateAllKeys = false;
     }
 
-    private void onDrawKey(final Key key, final Canvas canvas, final Paint paint) {
+    private void onDrawKey(@Nonnull final Key key, @Nonnull final Canvas canvas,
+            @Nonnull final Paint paint) {
         final int keyDrawX = key.getDrawX() + getPaddingLeft();
         final int keyDrawY = key.getY() + getPaddingTop();
         canvas.translate(keyDrawX, keyDrawY);
 
-        final int keyHeight = mKeyboard.mMostCommonKeyHeight - mKeyboard.mVerticalGap;
         final KeyVisualAttributes attr = key.getVisualAttributes();
-        final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(keyHeight, attr);
+        final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(key.getHeight(), attr);
         params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;
 
         if (!key.isSpacer()) {
             final Drawable background = key.selectBackgroundDrawable(
                     mKeyBackground, mFunctionalKeyBackground, mSpacebarBackground);
-            onDrawKeyBackground(key, canvas, background);
+            if (background != null) {
+                onDrawKeyBackground(key, canvas, background);
+            }
         }
         onDrawKeyTopVisuals(key, canvas, paint, params);
 
@@ -338,8 +347,8 @@
     }
 
     // Draw key background.
-    protected void onDrawKeyBackground(final Key key, final Canvas canvas,
-            final Drawable background) {
+    protected void onDrawKeyBackground(@Nonnull final Key key, @Nonnull final Canvas canvas,
+            @Nonnull final Drawable background) {
         final int keyWidth = key.getDrawWidth();
         final int keyHeight = key.getHeight();
         final int bgWidth, bgHeight, bgX, bgY;
@@ -371,15 +380,17 @@
     }
 
     // Draw key top visuals.
-    protected void onDrawKeyTopVisuals(final Key key, final Canvas canvas, final Paint paint,
-            final KeyDrawParams params) {
+    protected void onDrawKeyTopVisuals(@Nonnull final Key key, @Nonnull final Canvas canvas,
+            @Nonnull final Paint paint, @Nonnull final KeyDrawParams params) {
         final int keyWidth = key.getDrawWidth();
         final int keyHeight = key.getHeight();
         final float centerX = keyWidth * 0.5f;
         final float centerY = keyHeight * 0.5f;
 
         // Draw key label.
-        final Drawable icon = key.getIcon(mKeyboard.mIconsSet, params.mAnimAlpha);
+        final Keyboard keyboard = getKeyboard();
+        final Drawable icon = (keyboard == null) ? null
+                : key.getIcon(keyboard.mIconsSet, params.mAnimAlpha);
         float labelX = centerX;
         float labelBaseline = centerY;
         final String label = key.getLabel();
@@ -498,8 +509,8 @@
     }
 
     // Draw popup hint "..." at the bottom right corner of the key.
-    protected void drawKeyPopupHint(final Key key, final Canvas canvas, final Paint paint,
-            final KeyDrawParams params) {
+    protected void drawKeyPopupHint(@Nonnull final Key key, @Nonnull final Canvas canvas,
+            @Nonnull final Paint paint, @Nonnull final KeyDrawParams params) {
         if (TextUtils.isEmpty(mKeyPopupHintLetter)) {
             return;
         }
@@ -516,15 +527,15 @@
         canvas.drawText(mKeyPopupHintLetter, hintX, hintY, paint);
     }
 
-    protected static void drawIcon(final Canvas canvas, final Drawable icon, final int x,
-            final int y, final int width, final int height) {
+    protected static void drawIcon(@Nonnull final Canvas canvas,@Nonnull final Drawable icon,
+            final int x, final int y, final int width, final int height) {
         canvas.translate(x, y);
         icon.setBounds(0, 0, width, height);
         icon.draw(canvas);
         canvas.translate(-x, -y);
     }
 
-    public Paint newLabelPaint(final Key key) {
+    public Paint newLabelPaint(@Nullable final Key key) {
         final Paint paint = new Paint();
         paint.setAntiAlias(true);
         if (key == null) {
@@ -557,9 +568,10 @@
      * @param key key in the attached {@link Keyboard}.
      * @see #invalidateAllKeys
      */
-    public void invalidateKey(final Key key) {
-        if (mInvalidateAllKeys) return;
-        if (key == null) return;
+    public void invalidateKey(@Nullable final Key key) {
+        if (mInvalidateAllKeys || key == null) {
+            return;
+        }
         mInvalidatedKeys.add(key);
         final int x = key.getX() + getPaddingLeft();
         final int y = key.getY() + getPaddingTop();
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 2b16785..00d4fa2 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -28,40 +28,44 @@
 import android.graphics.Paint.Align;
 import android.graphics.Typeface;
 import android.preference.PreferenceManager;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.accessibility.MainKeyboardAccessibilityDelegate;
 import com.android.inputmethod.annotations.ExternallyReferenced;
-import com.android.inputmethod.keyboard.internal.DrawingHandler;
 import com.android.inputmethod.keyboard.internal.DrawingPreviewPlacerView;
+import com.android.inputmethod.keyboard.internal.DrawingProxy;
 import com.android.inputmethod.keyboard.internal.GestureFloatingTextDrawingPreview;
 import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview;
 import com.android.inputmethod.keyboard.internal.KeyDrawParams;
 import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer;
 import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
 import com.android.inputmethod.keyboard.internal.KeyPreviewView;
-import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
 import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
 import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview;
 import com.android.inputmethod.keyboard.internal.TimerHandler;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
 import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 import com.android.inputmethod.latin.settings.DebugSettings;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.SpacebarLanguageUtils;
+import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 
+import java.util.Locale;
 import java.util.WeakHashMap;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * A view that is responsible for detecting key presses and touch movements.
  *
@@ -105,8 +109,8 @@
  * @attr ref R.styleable#MainKeyboardView_gestureRecognitionSpeedThreshold
  * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration
  */
-public final class MainKeyboardView extends KeyboardView implements PointerTracker.DrawingProxy,
-        MoreKeysPanel.Controller, DrawingHandler.Callbacks, TimerHandler.Callbacks {
+public final class MainKeyboardView extends KeyboardView implements DrawingProxy,
+        MoreKeysPanel.Controller {
     private static final String TAG = MainKeyboardView.class.getSimpleName();
 
     /** Listener for {@link KeyboardActionListener}. */
@@ -147,7 +151,6 @@
 
     // More keys keyboard
     private final Paint mBackgroundDimAlphaPaint = new Paint();
-    private boolean mNeedsToDimEntireKeyboard;
     private final View mMoreKeysKeyboardContainer;
     private final View mMoreKeysKeyboardForActionContainer;
     private final WeakHashMap<Key, Keyboard> mMoreKeysKeyboardCache = new WeakHashMap<>();
@@ -163,11 +166,9 @@
     private final KeyDetector mKeyDetector;
     private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper;
 
-    private final TimerHandler mKeyTimerHandler;
+    private final TimerHandler mTimerHandler;
     private final int mLanguageOnSpacebarHorizontalMargin;
 
-    private final DrawingHandler mDrawingHandler = new DrawingHandler(this);
-
     private MainKeyboardAccessibilityDelegate mAccessibilityDelegate;
 
     public MainKeyboardView(final Context context, final AttributeSet attrs) {
@@ -177,7 +178,8 @@
     public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) {
         super(context, attrs, defStyle);
 
-        mDrawingPreviewPlacerView = new DrawingPreviewPlacerView(context, attrs);
+        final DrawingPreviewPlacerView drawingPreviewPlacerView =
+                new DrawingPreviewPlacerView(context, attrs);
 
         final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes(
                 attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView);
@@ -185,7 +187,7 @@
                 R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0);
         final int gestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt(
                 R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0);
-        mKeyTimerHandler = new TimerHandler(
+        mTimerHandler = new TimerHandler(
                 this, ignoreAltCodeKeyTimeout, gestureRecognitionUpdateTime);
 
         final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension(
@@ -195,7 +197,7 @@
         mKeyDetector = new KeyDetector(
                 keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier);
 
-        PointerTracker.init(mainKeyboardViewAttr, mKeyTimerHandler, this /* DrawingProxy */);
+        PointerTracker.init(mainKeyboardViewAttr, mTimerHandler, this /* DrawingProxy */);
 
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
         final boolean forceNonDistinctMultitouch = prefs.getBoolean(
@@ -245,15 +247,17 @@
 
         mGestureFloatingTextDrawingPreview = new GestureFloatingTextDrawingPreview(
                 mainKeyboardViewAttr);
-        mGestureFloatingTextDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
+        mGestureFloatingTextDrawingPreview.setDrawingView(drawingPreviewPlacerView);
 
         mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview(mainKeyboardViewAttr);
-        mGestureTrailsDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
+        mGestureTrailsDrawingPreview.setDrawingView(drawingPreviewPlacerView);
 
         mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview(mainKeyboardViewAttr);
-        mSlidingKeyInputDrawingPreview.setDrawingView(mDrawingPreviewPlacerView);
+        mSlidingKeyInputDrawingPreview.setDrawingView(drawingPreviewPlacerView);
         mainKeyboardViewAttr.recycle();
 
+        mDrawingPreviewPlacerView = drawingPreviewPlacerView;
+
         final LayoutInflater inflater = LayoutInflater.from(getContext());
         mMoreKeysKeyboardContainer = inflater.inflate(moreKeysKeyboardLayoutId, null);
         mMoreKeysKeyboardForActionContainer = inflater.inflate(
@@ -306,17 +310,24 @@
         animatorToStart.setCurrentPlayTime(startTime);
     }
 
-    // Implements {@link TimerHander.Callbacks} method.
+    // Implements {@link DrawingProxy#startWhileTypingAnimation(int)}.
+    /**
+     * Called when a while-typing-animation should be started.
+     * @param fadeInOrOut {@link DrawingProxy#FADE_IN} starts while-typing-fade-in animation.
+     * {@link DrawingProxy#FADE_OUT} starts while-typing-fade-out animation.
+     */
     @Override
-    public void startWhileTypingFadeinAnimation() {
-        cancelAndStartAnimators(
-                mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator);
-    }
-
-    @Override
-    public void startWhileTypingFadeoutAnimation() {
-        cancelAndStartAnimators(
-                mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator);
+    public void startWhileTypingAnimation(final int fadeInOrOut) {
+        switch (fadeInOrOut) {
+        case DrawingProxy.FADE_IN:
+            cancelAndStartAnimators(
+                    mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator);
+            break;
+        case DrawingProxy.FADE_OUT:
+            cancelAndStartAnimators(
+                    mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator);
+            break;
+        }
     }
 
     @ExternallyReferenced
@@ -378,7 +389,7 @@
     @Override
     public void setKeyboard(final Keyboard keyboard) {
         // Remove any pending messages, except dismissing preview and key repeat.
-        mKeyTimerHandler.cancelLongPressTimers();
+        mTimerHandler.cancelLongPressTimers();
         super.setKeyboard(keyboard);
         mKeyDetector.setKeyboard(
                 keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection());
@@ -450,19 +461,17 @@
         windowContentView.addView(mDrawingPreviewPlacerView);
     }
 
-    // Implements {@link DrawingHandler.Callbacks} method.
+    // Implements {@link DrawingProxy#onKeyPressed(Key,boolean)}.
     @Override
-    public void dismissAllKeyPreviews() {
-        mKeyPreviewChoreographer.dismissAllKeyPreviews();
-        PointerTracker.setReleasedKeyGraphicsToAllKeys();
+    public void onKeyPressed(@Nonnull final Key key, final boolean withPreview) {
+        key.onPressed();
+        invalidateKey(key);
+        if (withPreview && !key.noKeyPreview()) {
+            showKeyPreview(key);
+        }
     }
 
-    @Override
-    public void showKeyPreview(final Key key) {
-        // If the key is invalid or has no key preview, we must not show key preview.
-        if (key == null || key.noKeyPreview()) {
-            return;
-        }
+    private void showKeyPreview(@Nonnull final Key key) {
         final Keyboard keyboard = getKeyboard();
         if (keyboard == null) {
             return;
@@ -475,26 +484,36 @@
 
         locatePreviewPlacerView();
         getLocationInWindow(mOriginCoords);
-        mKeyPreviewChoreographer.placeAndShowKeyPreview(key, keyboard.mIconsSet, mKeyDrawParams,
+        mKeyPreviewChoreographer.placeAndShowKeyPreview(key, keyboard.mIconsSet, getKeyDrawParams(),
                 getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
     }
 
-    // Implements {@link TimerHandler.Callbacks} method.
-    @Override
-    public void dismissKeyPreviewWithoutDelay(final Key key) {
+    private void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) {
         mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
-        // To redraw key top letter.
         invalidateKey(key);
     }
 
+    // Implements {@link DrawingProxy#onKeyReleased(Key,boolean)}.
     @Override
-    public void dismissKeyPreview(final Key key) {
-        if (!isHardwareAccelerated()) {
-            // TODO: Implement preference option to control key preview method and duration.
-            mDrawingHandler.dismissKeyPreview(mKeyPreviewDrawParams.getLingerTimeout(), key);
+    public void onKeyReleased(@Nonnull final Key key, final boolean withAnimation) {
+        key.onReleased();
+        invalidateKey(key);
+        if (!key.noKeyPreview()) {
+            if (withAnimation) {
+                dismissKeyPreview(key);
+            } else {
+                dismissKeyPreviewWithoutDelay(key);
+            }
+        }
+    }
+
+    private void dismissKeyPreview(@Nonnull final Key key) {
+        if (isHardwareAccelerated()) {
+            mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */);
             return;
         }
-        mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */);
+        // TODO: Implement preference option to control key preview method and duration.
+        mTimerHandler.postDismissKeyPreview(key, mKeyPreviewDrawParams.getLingerTimeout());
     }
 
     public void setSlidingKeyInputPreviewEnabled(final boolean enabled) {
@@ -502,14 +521,13 @@
     }
 
     @Override
-    public void showSlidingKeyInputPreview(final PointerTracker tracker) {
+    public void showSlidingKeyInputPreview(@Nullable final PointerTracker tracker) {
         locatePreviewPlacerView();
-        mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker);
-    }
-
-    @Override
-    public void dismissSlidingKeyInputPreview() {
-        mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview();
+        if (tracker != null) {
+            mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker);
+        } else {
+            mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview();
+        }
     }
 
     private void setGesturePreviewMode(final boolean isGestureTrailEnabled,
@@ -518,20 +536,26 @@
         mGestureTrailsDrawingPreview.setPreviewEnabled(isGestureTrailEnabled);
     }
 
-    // Implements {@link DrawingHandler.Callbacks} method.
-    @Override
-    public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) {
+    public void showGestureFloatingPreviewText(@Nonnull final SuggestedWords suggestedWords,
+            final boolean dismissDelayed) {
         locatePreviewPlacerView();
-        mGestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords);
+        final GestureFloatingTextDrawingPreview gestureFloatingTextDrawingPreview =
+                mGestureFloatingTextDrawingPreview;
+        gestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords);
+        if (dismissDelayed) {
+            mTimerHandler.postDismissGestureFloatingPreviewText(
+                    mGestureFloatingPreviewTextLingerTimeout);
+        }
     }
 
-    public void dismissGestureFloatingPreviewText() {
-        locatePreviewPlacerView();
-        mDrawingHandler.dismissGestureFloatingPreviewText(mGestureFloatingPreviewTextLingerTimeout);
+    // Implements {@link DrawingProxy#dismissGestureFloatingPreviewTextWithoutDelay()}.
+    @Override
+    public void dismissGestureFloatingPreviewTextWithoutDelay() {
+        mGestureFloatingTextDrawingPreview.dismissGestureFloatingPreviewText();
     }
 
     @Override
-    public void showGestureTrail(final PointerTracker tracker,
+    public void showGestureTrail(@Nonnull final PointerTracker tracker,
             final boolean showsFloatingPreviewText) {
         locatePreviewPlacerView();
         if (showsFloatingPreviewText) {
@@ -566,7 +590,11 @@
         mDrawingPreviewPlacerView.removeAllViews();
     }
 
-    private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
+    // Implements {@link DrawingProxy@showMoreKeysKeyboard(Key,PointerTracker)}.
+    @Override
+    @Nullable
+    public MoreKeysPanel showMoreKeysKeyboard(@Nonnull final Key key,
+            @Nonnull final PointerTracker tracker) {
         final MoreKeySpec[] moreKeys = key.getMoreKeys();
         if (moreKeys == null) {
             return null;
@@ -582,7 +610,7 @@
                     && !key.noKeyPreview() && moreKeys.length == 1
                     && mKeyPreviewDrawParams.getVisibleWidth() > 0;
             final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
-                    context, key, getKeyboard(), isSingleMoreKeyWithPreview,
+                    getContext(), key, getKeyboard(), isSingleMoreKeyWithPreview,
                     mKeyPreviewDrawParams.getVisibleWidth(),
                     mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
             moreKeysKeyboard = builder.build();
@@ -595,50 +623,6 @@
                 (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view);
         moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
         container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        return moreKeysKeyboardView;
-    }
-
-    // Implements {@link TimerHandler.Callbacks} method.
-    /**
-     * Called when a key is long pressed.
-     * @param tracker the pointer tracker which pressed the parent key
-     */
-    @Override
-    public void onLongPress(final PointerTracker tracker) {
-        if (isShowingMoreKeysPanel()) {
-            return;
-        }
-        final Key key = tracker.getKey();
-        if (key == null) {
-            return;
-        }
-        final KeyboardActionListener listener = mKeyboardActionListener;
-        if (key.hasNoPanelAutoMoreKey()) {
-            final int moreKeyCode = key.getMoreKeys()[0].mCode;
-            tracker.onLongPressed();
-            listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */);
-            listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
-                    Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
-            listener.onReleaseKey(moreKeyCode, false /* withSliding */);
-            return;
-        }
-        final int code = key.getCode();
-        if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
-            // Long pressing the space key invokes IME switcher dialog.
-            if (listener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
-                tracker.onLongPressed();
-                listener.onReleaseKey(code, false /* withSliding */);
-                return;
-            }
-        }
-        openMoreKeysPanel(key, tracker);
-    }
-
-    private void openMoreKeysPanel(final Key key, final PointerTracker tracker) {
-        final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext());
-        if (moreKeysPanel == null) {
-            return;
-        }
 
         final int[] lastCoords = CoordinateUtils.newInstance();
         tracker.getLastCoordinates(lastCoords);
@@ -656,10 +640,8 @@
         // {@code mPreviewVisibleOffset} has been set appropriately in
         // {@link KeyboardView#showKeyPreview(PointerTracker)}.
         final int pointY = key.getY() + mKeyPreviewDrawParams.getVisibleOffset();
-        moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
-        tracker.onShowMoreKeysPanel(moreKeysPanel);
-        // TODO: Implement zoom in animation of more keys panel.
-        dismissKeyPreviewWithoutDelay(key);
+        moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
+        return moreKeysKeyboardView;
     }
 
     public boolean isInDraggingFinger() {
@@ -672,9 +654,14 @@
     @Override
     public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
         locatePreviewPlacerView();
+        // Dismiss another {@link MoreKeysPanel} that may be being showed.
+        onDismissMoreKeysPanel();
+        // Dismiss all key previews that may be being showed.
+        PointerTracker.setReleasedKeyGraphicsToAllKeys();
+        // Dismiss sliding key input preview that may be being showed.
+        mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview();
         panel.showInParent(mDrawingPreviewPlacerView);
         mMoreKeysPanel = panel;
-        dimEntireKeyboard(true /* dimmed */);
     }
 
     public boolean isShowingMoreKeysPanel() {
@@ -688,7 +675,6 @@
 
     @Override
     public void onDismissMoreKeysPanel() {
-        dimEntireKeyboard(false /* dimmed */);
         if (isShowingMoreKeysPanel()) {
             mMoreKeysPanel.removeFromParent();
             mMoreKeysPanel = null;
@@ -696,37 +682,37 @@
     }
 
     public void startDoubleTapShiftKeyTimer() {
-        mKeyTimerHandler.startDoubleTapShiftKeyTimer();
+        mTimerHandler.startDoubleTapShiftKeyTimer();
     }
 
     public void cancelDoubleTapShiftKeyTimer() {
-        mKeyTimerHandler.cancelDoubleTapShiftKeyTimer();
+        mTimerHandler.cancelDoubleTapShiftKeyTimer();
     }
 
     public boolean isInDoubleTapShiftKeyTimeout() {
-        return mKeyTimerHandler.isInDoubleTapShiftKeyTimeout();
+        return mTimerHandler.isInDoubleTapShiftKeyTimeout();
     }
 
     @Override
-    public boolean onTouchEvent(final MotionEvent me) {
+    public boolean onTouchEvent(final MotionEvent event) {
         if (getKeyboard() == null) {
             return false;
         }
         if (mNonDistinctMultitouchHelper != null) {
-            if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) {
+            if (event.getPointerCount() > 1 && mTimerHandler.isInKeyRepeat()) {
                 // Key repeating timer will be canceled if 2 or more keys are in action.
-                mKeyTimerHandler.cancelKeyRepeatTimers();
+                mTimerHandler.cancelKeyRepeatTimers();
             }
             // Non distinct multitouch screen support
-            mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector);
+            mNonDistinctMultitouchHelper.processMotionEvent(event, mKeyDetector);
             return true;
         }
-        return processMotionEvent(me);
+        return processMotionEvent(event);
     }
 
-    public boolean processMotionEvent(final MotionEvent me) {
-        final int index = me.getActionIndex();
-        final int id = me.getPointerId(index);
+    public boolean processMotionEvent(final MotionEvent event) {
+        final int index = event.getActionIndex();
+        final int id = event.getPointerId(index);
         final PointerTracker tracker = PointerTracker.getPointerTracker(id);
         // When a more keys panel is showing, we should ignore other fingers' single touch events
         // other than the finger that is showing the more keys panel.
@@ -734,16 +720,15 @@
                 && PointerTracker.getActivePointerTrackerCount() == 1) {
             return true;
         }
-        tracker.processMotionEvent(me, mKeyDetector);
+        tracker.processMotionEvent(event, mKeyDetector);
         return true;
     }
 
     public void cancelAllOngoingEvents() {
-        mKeyTimerHandler.cancelAllMessages();
-        mDrawingHandler.cancelAllMessages();
-        dismissAllKeyPreviews();
-        dismissGestureFloatingPreviewText();
-        dismissSlidingKeyInputPreview();
+        mTimerHandler.cancelAllMessages();
+        PointerTracker.setReleasedKeyGraphicsToAllKeys();
+        mGestureFloatingTextDrawingPreview.dismissGestureFloatingPreviewText();
+        mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview();
         PointerTracker.dismissAllMoreKeysPanels();
         PointerTracker.cancelAllPointerTrackers();
     }
@@ -798,10 +783,10 @@
         mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes;
         final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator;
         if (animator == null) {
-            mLanguageOnSpacebarFormatType = LanguageOnSpacebarHelper.FORMAT_TYPE_NONE;
+            mLanguageOnSpacebarFormatType = LanguageOnSpacebarUtils.FORMAT_TYPE_NONE;
         } else {
             if (subtypeChanged
-                    && languageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) {
+                    && languageOnSpacebarFormatType != LanguageOnSpacebarUtils.FORMAT_TYPE_NONE) {
                 setLanguageOnSpacebarAnimAlpha(Constants.Color.ALPHA_OPAQUE);
                 if (animator.isStarted()) {
                     animator.cancel();
@@ -816,24 +801,6 @@
         invalidateKey(mSpaceKey);
     }
 
-    private void dimEntireKeyboard(final boolean dimmed) {
-        final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed;
-        mNeedsToDimEntireKeyboard = dimmed;
-        if (needsRedrawing) {
-            invalidateAllKeys();
-        }
-    }
-
-    @Override
-    protected void onDraw(final Canvas canvas) {
-        super.onDraw(canvas);
-
-        // Overlay a dark rectangle to dim.
-        if (mNeedsToDimEntireKeyboard) {
-            canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mBackgroundDimAlphaPaint);
-        }
-    }
-
     @Override
     protected void onDrawKeyTopVisuals(final Key key, final Canvas canvas, final Paint paint,
             final KeyDrawParams params) {
@@ -844,7 +811,7 @@
         final int code = key.getCode();
         if (code == Constants.CODE_SPACE) {
             // If input language are explicitly selected.
-            if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) {
+            if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarUtils.FORMAT_TYPE_NONE) {
                 drawLanguageOnSpacebar(key, canvas, paint);
             }
             // Whether space key needs to show the "..." popup hint for special purposes
@@ -875,16 +842,16 @@
 
     // Layout language name on spacebar.
     private String layoutLanguageOnSpacebar(final Paint paint,
-            final InputMethodSubtype subtype, final int width) {
+            final RichInputMethodSubtype subtype, final int width) {
         // Choose appropriate language name to fit into the width.
-        if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE) {
-            final String fullText = SpacebarLanguageUtils.getFullDisplayName(subtype);
+        if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE) {
+            final String fullText = subtype.getFullDisplayName();
             if (fitsTextIntoWidth(width, fullText, paint)) {
                 return fullText;
             }
         }
 
-        final String middleText = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
+        final String middleText = subtype.getMiddleDisplayName();
         if (fitsTextIntoWidth(width, middleText, paint)) {
             return middleText;
         }
@@ -893,13 +860,16 @@
     }
 
     private void drawLanguageOnSpacebar(final Key key, final Canvas canvas, final Paint paint) {
+        final Keyboard keyboard = getKeyboard();
+        if (keyboard == null) {
+            return;
+        }
         final int width = key.getWidth();
         final int height = key.getHeight();
         paint.setTextAlign(Align.CENTER);
         paint.setTypeface(Typeface.DEFAULT);
         paint.setTextSize(mLanguageOnSpacebarTextSize);
-        final InputMethodSubtype subtype = getKeyboard().mId.mSubtype;
-        final String language = layoutLanguageOnSpacebar(paint, subtype, width);
+        final String language = layoutLanguageOnSpacebar(paint, keyboard.mId.mSubtype, width);
         // Draw language text with shadow
         final float descent = paint.descent();
         final float textHeight = -paint.ascent() + descent;
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
index abcfff8..a021e5e 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java
@@ -24,9 +24,11 @@
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 
+import javax.annotation.Nonnull;
+
 public final class MoreKeysKeyboard extends Keyboard {
     private final int mDefaultKeyCoordX;
 
@@ -328,6 +330,7 @@
         }
 
         @Override
+        @Nonnull
         public MoreKeysKeyboard build() {
             final MoreKeysKeyboardParams params = mParams;
             final int moreKeyFlags = mParentKey.getMoreKeyLabelFlags();
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
index 841283b..3acc11b 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -29,9 +29,9 @@
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.accessibility.MoreKeysKeyboardAccessibilityDelegate;
 import com.android.inputmethod.keyboard.internal.KeyDrawParams;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 
 /**
  * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 49288ad..9764cb3 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -25,22 +25,27 @@
 import com.android.inputmethod.keyboard.internal.BatchInputArbiter;
 import com.android.inputmethod.keyboard.internal.BatchInputArbiter.BatchInputArbiterListener;
 import com.android.inputmethod.keyboard.internal.BogusMoveEventDetector;
+import com.android.inputmethod.keyboard.internal.DrawingProxy;
 import com.android.inputmethod.keyboard.internal.GestureEnabler;
 import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingParams;
 import com.android.inputmethod.keyboard.internal.GestureStrokeDrawingPoints;
 import com.android.inputmethod.keyboard.internal.GestureStrokeRecognitionParams;
 import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
+import com.android.inputmethod.keyboard.internal.TimerProxy;
 import com.android.inputmethod.keyboard.internal.TypingTimeRecorder;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.InputPointers;
 import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 
 import java.util.ArrayList;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public final class PointerTracker implements PointerTrackerQueue.Element,
         BatchInputArbiterListener {
     private static final String TAG = PointerTracker.class.getSimpleName();
@@ -49,60 +54,6 @@
     private static final boolean DEBUG_LISTENER = false;
     private static boolean DEBUG_MODE = DebugFlags.DEBUG_ENABLED || DEBUG_EVENT;
 
-    public interface DrawingProxy {
-        public void invalidateKey(Key key);
-        public void showKeyPreview(Key key);
-        public void dismissKeyPreview(Key key);
-        public void showSlidingKeyInputPreview(PointerTracker tracker);
-        public void dismissSlidingKeyInputPreview();
-        public void showGestureTrail(PointerTracker tracker, boolean showsFloatingPreviewText);
-    }
-
-    public interface TimerProxy {
-        public void startTypingStateTimer(Key typedKey);
-        public boolean isTypingState();
-        public void startKeyRepeatTimerOf(PointerTracker tracker, int repeatCount, int delay);
-        public void startLongPressTimerOf(PointerTracker tracker, int delay);
-        public void cancelLongPressTimerOf(PointerTracker tracker);
-        public void cancelLongPressShiftKeyTimers();
-        public void cancelKeyTimersOf(PointerTracker tracker);
-        public void startDoubleTapShiftKeyTimer();
-        public void cancelDoubleTapShiftKeyTimer();
-        public boolean isInDoubleTapShiftKeyTimeout();
-        public void startUpdateBatchInputTimer(PointerTracker tracker);
-        public void cancelUpdateBatchInputTimer(PointerTracker tracker);
-        public void cancelAllUpdateBatchInputTimers();
-
-        public static class Adapter implements TimerProxy {
-            @Override
-            public void startTypingStateTimer(Key typedKey) {}
-            @Override
-            public boolean isTypingState() { return false; }
-            @Override
-            public void startKeyRepeatTimerOf(PointerTracker tracker, int repeatCount, int delay) {}
-            @Override
-            public void startLongPressTimerOf(PointerTracker tracker, int delay) {}
-            @Override
-            public void cancelLongPressTimerOf(PointerTracker tracker) {}
-            @Override
-            public void cancelLongPressShiftKeyTimers() {}
-            @Override
-            public void cancelKeyTimersOf(PointerTracker tracker) {}
-            @Override
-            public void startDoubleTapShiftKeyTimer() {}
-            @Override
-            public void cancelDoubleTapShiftKeyTimer() {}
-            @Override
-            public boolean isInDoubleTapShiftKeyTimeout() { return false; }
-            @Override
-            public void startUpdateBatchInputTimer(PointerTracker tracker) {}
-            @Override
-            public void cancelUpdateBatchInputTimer(PointerTracker tracker) {}
-            @Override
-            public void cancelAllUpdateBatchInputTimers() {}
-        }
-    }
-
     static final class PointerTrackerParams {
         public final boolean mKeySelectionByDraggingFinger;
         public final int mTouchNoiseThresholdTime;
@@ -163,6 +114,7 @@
 
     // The position and time at which first down event occurred.
     private long mDownTime;
+    @Nonnull
     private int[] mDownCoordinates = CoordinateUtils.newInstance();
     private long mUpTime;
 
@@ -270,7 +222,7 @@
         final int trackersSize = sTrackers.size();
         for (int i = 0; i < trackersSize; ++i) {
             final PointerTracker tracker = sTrackers.get(i);
-            tracker.setReleasedKeyGraphics(tracker.getKey());
+            tracker.setReleasedKeyGraphics(tracker.getKey(), true /* withAnimation */);
         }
     }
 
@@ -416,6 +368,7 @@
         return mIsInDraggingFinger;
     }
 
+    @Nullable
     public Key getKey() {
         return mCurrentKey;
     }
@@ -429,19 +382,17 @@
         return mKeyDetector.detectHitKey(x, y);
     }
 
-    private void setReleasedKeyGraphics(final Key key) {
-        sDrawingProxy.dismissKeyPreview(key);
+    private void setReleasedKeyGraphics(@Nullable final Key key, final boolean withAnimation) {
         if (key == null) {
             return;
         }
 
-        // Even if the key is disabled, update the key release graphics just in case.
-        updateReleaseKeyGraphics(key);
+        sDrawingProxy.onKeyReleased(key, withAnimation);
 
         if (key.isShift()) {
             for (final Key shiftKey : mKeyboard.mShiftKeys) {
                 if (shiftKey != key) {
-                    updateReleaseKeyGraphics(shiftKey);
+                    sDrawingProxy.onKeyReleased(shiftKey, false /* withAnimation */);
                 }
             }
         }
@@ -450,11 +401,11 @@
             final int altCode = key.getAltCode();
             final Key altKey = mKeyboard.getKey(altCode);
             if (altKey != null) {
-                updateReleaseKeyGraphics(altKey);
+                sDrawingProxy.onKeyReleased(altKey, false /* withAnimation */);
             }
             for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
                 if (k != key && k.getAltCode() == altCode) {
-                    updateReleaseKeyGraphics(k);
+                    sDrawingProxy.onKeyReleased(k, false /* withAnimation */);
                 }
             }
         }
@@ -465,7 +416,7 @@
         return sTypingTimeRecorder.needsToSuppressKeyPreviewPopup(eventTime);
     }
 
-    private void setPressedKeyGraphics(final Key key, final long eventTime) {
+    private void setPressedKeyGraphics(@Nullable final Key key, final long eventTime) {
         if (key == null) {
             return;
         }
@@ -477,15 +428,13 @@
             return;
         }
 
-        if (!key.noKeyPreview() && !sInGesture && !needsToSuppressKeyPreviewPopup(eventTime)) {
-            sDrawingProxy.showKeyPreview(key);
-        }
-        updatePressKeyGraphics(key);
+        final boolean noKeyPreview = sInGesture || needsToSuppressKeyPreviewPopup(eventTime);
+        sDrawingProxy.onKeyPressed(key, !noKeyPreview);
 
         if (key.isShift()) {
             for (final Key shiftKey : mKeyboard.mShiftKeys) {
                 if (shiftKey != key) {
-                    updatePressKeyGraphics(shiftKey);
+                    sDrawingProxy.onKeyPressed(shiftKey, false /* withPreview */);
                 }
             }
         }
@@ -494,31 +443,21 @@
             final int altCode = key.getAltCode();
             final Key altKey = mKeyboard.getKey(altCode);
             if (altKey != null) {
-                updatePressKeyGraphics(altKey);
+                sDrawingProxy.onKeyPressed(altKey, false /* withPreview */);
             }
             for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
                 if (k != key && k.getAltCode() == altCode) {
-                    updatePressKeyGraphics(k);
+                    sDrawingProxy.onKeyPressed(k, false /* withPreview */);
                 }
             }
         }
     }
 
-    private static void updateReleaseKeyGraphics(final Key key) {
-        key.onReleased();
-        sDrawingProxy.invalidateKey(key);
-    }
-
-    private static void updatePressKeyGraphics(final Key key) {
-        key.onPressed();
-        sDrawingProxy.invalidateKey(key);
-    }
-
     public GestureStrokeDrawingPoints getGestureStrokeDrawingPoints() {
         return mGestureStrokeDrawingPoints;
     }
 
-    public void getLastCoordinates(final int[] outCoords) {
+    public void getLastCoordinates(@Nonnull final int[] outCoords) {
         CoordinateUtils.set(outCoords, mLastX, mLastY);
     }
 
@@ -526,7 +465,7 @@
         return mDownTime;
     }
 
-    public void getDownCoordinates(final int[] outCoords) {
+    public void getDownCoordinates(@Nonnull final int[] outCoords) {
         CoordinateUtils.copy(outCoords, mDownCoordinates);
     }
 
@@ -575,7 +514,7 @@
         }
         sListener.onStartBatchInput();
         dismissAllMoreKeysPanels();
-        sTimerProxy.cancelLongPressTimerOf(this);
+        sTimerProxy.cancelLongPressTimersOf(this);
     }
 
     private void showGestureTrail() {
@@ -765,7 +704,7 @@
     private void resetKeySelectionByDraggingFinger() {
         mIsInDraggingFinger = false;
         mIsInSlidingKeyInput = false;
-        sDrawingProxy.dismissSlidingKeyInputPreview();
+        sDrawingProxy.showSlidingKeyInputPreview(null /* tracker */);
     }
 
     private void onGestureMoveEvent(final int x, final int y, final long eventTime,
@@ -884,7 +823,7 @@
     }
 
     private void processDraggingFingerOutFromOldKey(final Key oldKey) {
-        setReleasedKeyGraphics(oldKey);
+        setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         callListenerOnRelease(oldKey, oldKey.getCode(), true /* withSliding */);
         startKeySelectionByDraggingFinger(oldKey);
         sTimerProxy.cancelKeyTimersOf(this);
@@ -927,12 +866,12 @@
             }
             onUpEvent(x, y, eventTime);
             cancelTrackingForAction();
-            setReleasedKeyGraphics(oldKey);
+            setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         } else {
             if (!mIsDetectingGesture) {
                 cancelTrackingForAction();
             }
-            setReleasedKeyGraphics(oldKey);
+            setReleasedKeyGraphics(oldKey, true /* withAnimation */);
         }
     }
 
@@ -960,7 +899,7 @@
             onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey);
             if (sInGesture) {
                 mCurrentKey = null;
-                setReleasedKeyGraphics(oldKey);
+                setReleasedKeyGraphics(oldKey, true /* withAnimation */);
                 return;
             }
         }
@@ -1025,7 +964,7 @@
         final int currentRepeatingKeyCode = mCurrentRepeatingKeyCode;
         mCurrentRepeatingKeyCode = Constants.NOT_A_CODE;
         // Release the last pressed key.
-        setReleasedKeyGraphics(currentKey);
+        setReleasedKeyGraphics(currentKey, true /* withAnimation */);
 
         if (isShowingMoreKeysPanel()) {
             if (!mIsTrackingForActionDisabled) {
@@ -1062,14 +1001,6 @@
         }
     }
 
-    public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
-        setReleasedKeyGraphics(mCurrentKey);
-        final int translatedX = panel.translateX(mLastX);
-        final int translatedY = panel.translateY(mLastY);
-        panel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
-        mMoreKeysPanel = panel;
-    }
-
     @Override
     public void cancelTrackingForAction() {
         if (isShowingMoreKeysPanel()) {
@@ -1082,14 +1013,49 @@
         return !mIsTrackingForActionDisabled;
     }
 
-    public void cancelLongPressTimer() {
-        sTimerProxy.cancelLongPressTimerOf(this);
+    public void onLongPressed() {
+        sTimerProxy.cancelLongPressTimersOf(this);
+        if (isShowingMoreKeysPanel()) {
+            return;
+        }
+        final Key key = getKey();
+        if (key == null) {
+            return;
+        }
+        if (key.hasNoPanelAutoMoreKey()) {
+            cancelKeyTracking();
+            final int moreKeyCode = key.getMoreKeys()[0].mCode;
+            sListener.onPressKey(moreKeyCode, 0 /* repeatCont */, true /* isSinglePointer */);
+            sListener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
+                    Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
+            sListener.onReleaseKey(moreKeyCode, false /* withSliding */);
+            return;
+        }
+        final int code = key.getCode();
+        if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
+            // Long pressing the space key invokes IME switcher dialog.
+            if (sListener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
+                cancelKeyTracking();
+                sListener.onReleaseKey(code, false /* withSliding */);
+                return;
+            }
+        }
+
+        setReleasedKeyGraphics(key, false /* withAnimation */);
+        final MoreKeysPanel moreKeysPanel = sDrawingProxy.showMoreKeysKeyboard(key, this);
+        if (moreKeysPanel == null) {
+            return;
+        }
+        final int translatedX = moreKeysPanel.translateX(mLastX);
+        final int translatedY = moreKeysPanel.translateY(mLastY);
+        moreKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
+        mMoreKeysPanel = moreKeysPanel;
     }
 
-    public void onLongPressed() {
+    private void cancelKeyTracking() {
         resetKeySelectionByDraggingFinger();
         cancelTrackingForAction();
-        setReleasedKeyGraphics(mCurrentKey);
+        setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
         sPointerTrackerQueue.remove(this);
     }
 
@@ -1106,7 +1072,7 @@
 
     private void onCancelEventInternal() {
         sTimerProxy.cancelKeyTimersOf(this);
-        setReleasedKeyGraphics(mCurrentKey);
+        setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
         resetKeySelectionByDraggingFinger();
         dismissMoreKeysPanel();
     }
@@ -1152,7 +1118,7 @@
     private void startLongPressTimer(final Key key) {
         // Note that we need to cancel all active long press shift key timers if any whenever we
         // start a new long press timer for both non-shift and shift keys.
-        sTimerProxy.cancelLongPressShiftKeyTimers();
+        sTimerProxy.cancelLongPressShiftKeyTimer();
         if (sInGesture) return;
         if (key == null) return;
         if (!key.isLongPressEnabled()) return;
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index c19cd67..b9a5eae 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -17,11 +17,10 @@
 package com.android.inputmethod.keyboard;
 
 import android.graphics.Rect;
-import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.inputmethod.keyboard.internal.TouchPositionCorrection;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.JniUtils;
 
 import java.util.ArrayList;
@@ -29,6 +28,8 @@
 import java.util.Collections;
 import java.util.List;
 
+import javax.annotation.Nonnull;
+
 public class ProximityInfo {
     private static final String TAG = ProximityInfo.class.getSimpleName();
     private static final boolean DEBUG = false;
@@ -37,6 +38,7 @@
     public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
     /** Number of key widths from current touch point to search for nearest keys. */
     private static final float SEARCH_DISTANCE = 1.2f;
+    @Nonnull
     private static final List<Key> EMPTY_KEY_LIST = Collections.emptyList();
     private static final float DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS = 0.15f;
 
@@ -50,20 +52,16 @@
     private final int mKeyboardHeight;
     private final int mMostCommonKeyWidth;
     private final int mMostCommonKeyHeight;
+    @Nonnull
     private final List<Key> mSortedKeys;
+    @Nonnull
     private final List<Key>[] mGridNeighbors;
-    private final String mLocaleStr;
 
     @SuppressWarnings("unchecked")
-    ProximityInfo(final String localeStr, final int gridWidth, final int gridHeight,
-            final int minWidth, final int height, final int mostCommonKeyWidth,
-            final int mostCommonKeyHeight, final List<Key> sortedKeys,
-            final TouchPositionCorrection touchPositionCorrection) {
-        if (TextUtils.isEmpty(localeStr)) {
-            mLocaleStr = "";
-        } else {
-            mLocaleStr = localeStr;
-        }
+    ProximityInfo(final int gridWidth, final int gridHeight, final int minWidth, final int height,
+            final int mostCommonKeyWidth, final int mostCommonKeyHeight,
+            @Nonnull final List<Key> sortedKeys,
+            @Nonnull final TouchPositionCorrection touchPositionCorrection) {
         mGridWidth = gridWidth;
         mGridHeight = gridHeight;
         mGridSize = mGridWidth * mGridHeight;
@@ -89,16 +87,15 @@
     }
 
     // TODO: Stop passing proximityCharsArray
-    private static native long setProximityInfoNative(String locale,
-            int displayWidth, int displayHeight, int gridWidth, int gridHeight,
-            int mostCommonKeyWidth, int mostCommonKeyHeight, int[] proximityCharsArray,
-            int keyCount, int[] keyXCoordinates, int[] keyYCoordinates, int[] keyWidths,
-            int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterXs,
+    private static native long setProximityInfoNative(int displayWidth, int displayHeight,
+            int gridWidth, int gridHeight, int mostCommonKeyWidth, int mostCommonKeyHeight,
+            int[] proximityCharsArray, int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
+            int[] keyWidths, int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterXs,
             float[] sweetSpotCenterYs, float[] sweetSpotRadii);
 
     private static native void releaseProximityInfoNative(long nativeProximityInfo);
 
-    private static boolean needsProximityInfo(final Key key) {
+    static boolean needsProximityInfo(final Key key) {
         // Don't include special keys into ProximityInfo.
         return key.getCode() >= Constants.CODE_SPACE;
     }
@@ -113,7 +110,8 @@
         return count;
     }
 
-    private long createNativeProximityInfo(final TouchPositionCorrection touchPositionCorrection) {
+    private long createNativeProximityInfo(
+            @Nonnull final TouchPositionCorrection touchPositionCorrection) {
         final List<Key>[] gridNeighborKeys = mGridNeighbors;
         final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
         Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE);
@@ -172,7 +170,7 @@
             infoIndex++;
         }
 
-        if (touchPositionCorrection != null && touchPositionCorrection.isValid()) {
+        if (touchPositionCorrection.isValid()) {
             if (DEBUG) {
                 Log.d(TAG, "touchPositionCorrection: ON");
             }
@@ -221,10 +219,10 @@
         }
 
         // TODO: Stop passing proximityCharsArray
-        return setProximityInfoNative(mLocaleStr, mKeyboardMinWidth, mKeyboardHeight,
-                mGridWidth, mGridHeight, mMostCommonKeyWidth, mMostCommonKeyHeight,
-                proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths,
-                keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
+        return setProximityInfoNative(mKeyboardMinWidth, mKeyboardHeight, mGridWidth, mGridHeight,
+                mMostCommonKeyWidth, mMostCommonKeyHeight, proximityCharsArray, keyCount,
+                keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes,
+                sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
     }
 
     public long getNativeProximityInfo() {
@@ -394,10 +392,8 @@
         }
     }
 
+    @Nonnull
     public List<Key> getNearestKeys(final int x, final int y) {
-        if (mGridNeighbors == null) {
-            return EMPTY_KEY_LIST;
-        }
         if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
             int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth);
             if (index < mGridSize) {
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java
deleted file mode 100644
index c22717f..0000000
--- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.graphics.Matrix;
-import android.graphics.RectF;
-import android.inputmethodservice.InputMethodService;
-import android.os.Message;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.inputmethod.CursorAnchorInfo;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
-import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
-
-import javax.annotation.Nonnull;
-
-/**
- * A controller class of the add-to-dictionary indicator (a.k.a. TextDecorator). This class
- * is designed to be independent of UI subsystems such as {@link View}. All the UI related
- * operations are delegated to {@link TextDecoratorUi} via {@link TextDecoratorUiOperator}.
- */
-public class TextDecorator {
-    private static final String TAG = TextDecorator.class.getSimpleName();
-    private static final boolean DEBUG = false;
-
-    private static final int INVALID_CURSOR_INDEX = -1;
-
-    private static final int MODE_MONITOR = 0;
-    private static final int MODE_WAITING_CURSOR_INDEX = 1;
-    private static final int MODE_SHOWING_INDICATOR = 2;
-
-    private int mMode = MODE_MONITOR;
-
-    private String mLastComposingText = null;
-    private boolean mHasRtlCharsInLastComposingText = false;
-    private RectF mComposingTextBoundsForLastComposingText = new RectF();
-
-    private boolean mIsFullScreenMode = false;
-    private String mWaitingWord = null;
-    private int mWaitingCursorStart = INVALID_CURSOR_INDEX;
-    private int mWaitingCursorEnd = INVALID_CURSOR_INDEX;
-    private CursorAnchorInfoCompatWrapper mCursorAnchorInfoWrapper = null;
-
-    @Nonnull
-    private final Listener mListener;
-
-    @Nonnull
-    private TextDecoratorUiOperator mUiOperator = EMPTY_UI_OPERATOR;
-
-    public interface Listener {
-        /**
-         * Called when the user clicks the indicator to add the word into the dictionary.
-         * @param word the word which the user clicked on.
-         */
-        void onClickComposingTextToAddToDictionary(final String word);
-    }
-
-    public TextDecorator(final Listener listener) {
-        mListener = (listener != null) ? listener : EMPTY_LISTENER;
-    }
-
-    /**
-     * Sets the UI operator for {@link TextDecorator}. Any user visible operations will be
-     * delegated to the associated UI operator.
-     * @param uiOperator the UI operator to be associated.
-     */
-    public void setUiOperator(final TextDecoratorUiOperator uiOperator) {
-        mUiOperator.disposeUi();
-        mUiOperator = uiOperator;
-        mUiOperator.setOnClickListener(getOnClickHandler());
-    }
-
-    private final Runnable mDefaultOnClickHandler = new Runnable() {
-        @Override
-        public void run() {
-            onClickIndicator();
-        }
-    };
-
-    @UsedForTesting
-    final Runnable getOnClickHandler() {
-        return mDefaultOnClickHandler;
-    }
-
-    /**
-     * Shows the "Add to dictionary" indicator and associates it with associating the given word.
-     *
-     * @param word the word which should be associated with the indicator. This object will be
-     * passed back in {@link Listener#onClickComposingTextToAddToDictionary(String)}.
-     * @param selectionStart the cursor index (inclusive) when the indicator should be displayed.
-     * @param selectionEnd the cursor index (exclusive) when the indicator should be displayed.
-     */
-    public void showAddToDictionaryIndicator(final String word, final int selectionStart,
-            final int selectionEnd) {
-        mWaitingWord = word;
-        mWaitingCursorStart = selectionStart;
-        mWaitingCursorEnd = selectionEnd;
-        mMode = MODE_WAITING_CURSOR_INDEX;
-        layoutLater();
-        return;
-    }
-
-    /**
-     * Must be called when the input method is about changing to for from the full screen mode.
-     * @param fullScreenMode {@code true} if the input method is entering the full screen mode.
-     * {@code false} is the input method is finishing the full screen mode.
-     */
-    public void notifyFullScreenMode(final boolean fullScreenMode) {
-        final boolean fullScreenModeChanged = (mIsFullScreenMode != fullScreenMode);
-        mIsFullScreenMode = fullScreenMode;
-        if (fullScreenModeChanged) {
-            layoutLater();
-        }
-    }
-
-    /**
-     * Resets previous requests and makes indicator invisible.
-     */
-    public void reset() {
-        mWaitingWord = null;
-        mMode = MODE_MONITOR;
-        mWaitingCursorStart = INVALID_CURSOR_INDEX;
-        mWaitingCursorEnd = INVALID_CURSOR_INDEX;
-        cancelLayoutInternalExpectedly("Resetting internal state.");
-    }
-
-    /**
-     * Must be called when the {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}
-     * is called.
-     *
-     * <p>CAVEAT: Currently the input method author is responsible for ignoring
-     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} called in full screen
-     * mode.</p>
-     * @param info the compatibility wrapper object for the received {@link CursorAnchorInfo}.
-     */
-    public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
-        mCursorAnchorInfoWrapper = info;
-        // Do not use layoutLater() to minimize the latency.
-        layoutImmediately();
-    }
-
-    private void cancelLayoutInternalUnexpectedly(final String message) {
-        mUiOperator.hideUi();
-        Log.d(TAG, message);
-    }
-
-    private void cancelLayoutInternalExpectedly(final String message) {
-        mUiOperator.hideUi();
-        if (DEBUG) {
-            Log.d(TAG, message);
-        }
-    }
-
-    private void layoutLater() {
-        mLayoutInvalidator.invalidateLayout();
-    }
-
-
-    private void layoutImmediately() {
-        // Clear pending layout requests.
-        mLayoutInvalidator.cancelInvalidateLayout();
-        layoutMain();
-    }
-
-    private void layoutMain() {
-        final CursorAnchorInfoCompatWrapper info = mCursorAnchorInfoWrapper;
-
-        if (info == null || !info.isAvailable()) {
-            cancelLayoutInternalExpectedly("CursorAnchorInfo isn't available.");
-            return;
-        }
-
-        final Matrix matrix = info.getMatrix();
-        if (matrix == null) {
-            cancelLayoutInternalUnexpectedly("Matrix is null");
-        }
-
-        final CharSequence composingText = info.getComposingText();
-        if (!TextUtils.isEmpty(composingText)) {
-            final int composingTextStart = info.getComposingTextStart();
-            final int lastCharRectIndex = composingTextStart + composingText.length() - 1;
-            final RectF lastCharRect = info.getCharacterBounds(lastCharRectIndex);
-            final int lastCharRectFlags = info.getCharacterBoundsFlags(lastCharRectIndex);
-            final boolean hasInvisibleRegionInLastCharRect =
-                    (lastCharRectFlags & CursorAnchorInfoCompatWrapper.FLAG_HAS_INVISIBLE_REGION)
-                            != 0;
-            if (lastCharRect == null || matrix == null || hasInvisibleRegionInLastCharRect) {
-                mUiOperator.hideUi();
-                return;
-            }
-
-            // Note that the following layout information is fragile, and must be invalidated
-            // even when surrounding text next to the composing text is changed because it can
-            // affect how the composing text is rendered.
-            // TODO: Investigate if we can change the input logic to make the target text
-            // composing state so that we can retrieve the character bounds reliably.
-            final String composingTextString = composingText.toString();
-            final float top = lastCharRect.top;
-            final float bottom = lastCharRect.bottom;
-            float left = lastCharRect.left;
-            float right = lastCharRect.right;
-            boolean useRtlLayout = false;
-            for (int i = composingText.length() - 1; i >= 0; --i) {
-                final int characterIndex = composingTextStart + i;
-                final RectF characterBounds = info.getCharacterBounds(characterIndex);
-                final int characterBoundsFlags = info.getCharacterBoundsFlags(characterIndex);
-                if (characterBounds == null) {
-                    break;
-                }
-                if (characterBounds.top != top) {
-                    break;
-                }
-                if (characterBounds.bottom != bottom) {
-                    break;
-                }
-                if ((characterBoundsFlags & CursorAnchorInfoCompatWrapper.FLAG_IS_RTL) != 0) {
-                    // This is for both RTL text and bi-directional text. RTL languages usually mix
-                    // RTL characters with LTR characters and in this case we should display the
-                    // indicator on the left, while in LTR languages that normally never happens.
-                    // TODO: Try to come up with a better algorithm.
-                    useRtlLayout = true;
-                }
-                left = Math.min(characterBounds.left, left);
-                right = Math.max(characterBounds.right, right);
-            }
-            mLastComposingText = composingTextString;
-            mHasRtlCharsInLastComposingText = useRtlLayout;
-            mComposingTextBoundsForLastComposingText.set(left, top, right, bottom);
-        }
-
-        final int selectionStart = info.getSelectionStart();
-        final int selectionEnd = info.getSelectionEnd();
-        switch (mMode) {
-            case MODE_MONITOR:
-                mUiOperator.hideUi();
-                return;
-            case MODE_WAITING_CURSOR_INDEX:
-                if (selectionStart != mWaitingCursorStart || selectionEnd != mWaitingCursorEnd) {
-                    mUiOperator.hideUi();
-                    return;
-                }
-                mMode = MODE_SHOWING_INDICATOR;
-                break;
-            case MODE_SHOWING_INDICATOR:
-                if (selectionStart != mWaitingCursorStart || selectionEnd != mWaitingCursorEnd) {
-                    mUiOperator.hideUi();
-                    mMode = MODE_MONITOR;
-                    mWaitingCursorStart = INVALID_CURSOR_INDEX;
-                    mWaitingCursorEnd = INVALID_CURSOR_INDEX;
-                    return;
-                }
-                break;
-            default:
-                cancelLayoutInternalUnexpectedly("Unexpected internal mode=" + mMode);
-                return;
-        }
-
-        if (!TextUtils.equals(mLastComposingText, mWaitingWord)) {
-            cancelLayoutInternalUnexpectedly("mLastComposingText doesn't match mWaitingWord");
-            return;
-        }
-
-        if ((info.getInsertionMarkerFlags() &
-                CursorAnchorInfoCompatWrapper.FLAG_HAS_INVISIBLE_REGION) != 0) {
-            mUiOperator.hideUi();
-            return;
-        }
-
-        mUiOperator.layoutUi(matrix, mComposingTextBoundsForLastComposingText,
-                mHasRtlCharsInLastComposingText);
-    }
-
-    private void onClickIndicator() {
-        if (mMode != MODE_SHOWING_INDICATOR) {
-            return;
-        }
-        mListener.onClickComposingTextToAddToDictionary(mWaitingWord);
-    }
-
-    private final LayoutInvalidator mLayoutInvalidator = new LayoutInvalidator(this);
-
-    /**
-     * Used for managing pending layout tasks for {@link TextDecorator#layoutLater()}.
-     */
-    private static final class LayoutInvalidator {
-        private final HandlerImpl mHandler;
-        public LayoutInvalidator(final TextDecorator ownerInstance) {
-            mHandler = new HandlerImpl(ownerInstance);
-        }
-
-        private static final int MSG_LAYOUT = 0;
-
-        private static final class HandlerImpl
-                extends LeakGuardHandlerWrapper<TextDecorator> {
-            public HandlerImpl(final TextDecorator ownerInstance) {
-                super(ownerInstance);
-            }
-
-            @Override
-            public void handleMessage(final Message msg) {
-                final TextDecorator owner = getOwnerInstance();
-                if (owner == null) {
-                    return;
-                }
-                switch (msg.what) {
-                    case MSG_LAYOUT:
-                        owner.layoutMain();
-                        break;
-                }
-            }
-        }
-
-        /**
-         * Puts a layout task into the scheduler. Does nothing if one or more layout tasks are
-         * already scheduled.
-         */
-        public void invalidateLayout() {
-            if (!mHandler.hasMessages(MSG_LAYOUT)) {
-                mHandler.obtainMessage(MSG_LAYOUT).sendToTarget();
-            }
-        }
-
-        /**
-         * Clears the pending layout tasks.
-         */
-        public void cancelInvalidateLayout() {
-            mHandler.removeMessages(MSG_LAYOUT);
-        }
-    }
-
-    private final static Listener EMPTY_LISTENER = new Listener() {
-        @Override
-        public void onClickComposingTextToAddToDictionary(final String word) {
-        }
-    };
-
-    private final static TextDecoratorUiOperator EMPTY_UI_OPERATOR = new TextDecoratorUiOperator() {
-        @Override
-        public void disposeUi() {
-        }
-        @Override
-        public void hideUi() {
-        }
-        @Override
-        public void setOnClickListener(Runnable listener) {
-        }
-        @Override
-        public void layoutUi(Matrix matrix, RectF composingTextBounds, boolean useRtlLayout) {
-        }
-    };
-}
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java
deleted file mode 100644
index d87dc1b..0000000
--- a/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.graphics.drawable.ColorDrawable;
-import android.inputmethodservice.InputMethodService;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewParent;
-import android.widget.PopupWindow;
-import android.widget.RelativeLayout;
-
-import com.android.inputmethod.latin.R;
-
-/**
- * Used as the UI component of {@link TextDecorator}.
- */
-public final class TextDecoratorUi implements TextDecoratorUiOperator {
-    private static final boolean VISUAL_DEBUG = false;
-    private static final int VISUAL_DEBUG_HIT_AREA_COLOR = 0x80ff8000;
-
-    private final RelativeLayout mLocalRootView;
-    private final AddToDictionaryIndicatorView mAddToDictionaryIndicatorView;
-    private final PopupWindow mTouchEventWindow;
-    private final View mTouchEventWindowClickListenerView;
-    private final float mHitAreaMarginInPixels;
-    private final RectF mDisplayRect;
-
-    /**
-     * This constructor is designed to be called from {@link InputMethodService#setInputView(View)}.
-     * Other usages are not supported.
-     *
-     * @param context the context of the input method.
-     * @param inputView the view that is passed to {@link InputMethodService#setInputView(View)}.
-     */
-    public TextDecoratorUi(final Context context, final View inputView) {
-        final Resources resources = context.getResources();
-        final int hitAreaMarginInDP = resources.getInteger(
-                R.integer.text_decorator_hit_area_margin_in_dp);
-        mHitAreaMarginInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                hitAreaMarginInDP, resources.getDisplayMetrics());
-        final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
-        mDisplayRect = new RectF(0.0f, 0.0f, displayMetrics.widthPixels,
-                displayMetrics.heightPixels);
-
-        mLocalRootView = new RelativeLayout(context);
-        mLocalRootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT));
-        // TODO: Use #setBackground(null) for API Level >= 16.
-        mLocalRootView.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
-
-        final ViewGroup contentView = getContentView(inputView);
-        mAddToDictionaryIndicatorView = new AddToDictionaryIndicatorView(context);
-        mLocalRootView.addView(mAddToDictionaryIndicatorView);
-        if (contentView != null) {
-            contentView.addView(mLocalRootView);
-        }
-
-        // This popup window is used to avoid the limitation that the input method is not able to
-        // observe the touch events happening outside of InputMethodService.Insets#touchableRegion.
-        // We don't use this popup window for rendering the UI for performance reasons though.
-        mTouchEventWindow = new PopupWindow(context);
-        if (VISUAL_DEBUG) {
-            mTouchEventWindow.setBackgroundDrawable(new ColorDrawable(VISUAL_DEBUG_HIT_AREA_COLOR));
-        } else {
-            mTouchEventWindow.setBackgroundDrawable(null);
-        }
-        mTouchEventWindowClickListenerView = new View(context);
-        mTouchEventWindow.setContentView(mTouchEventWindowClickListenerView);
-    }
-
-    @Override
-    public void disposeUi() {
-        if (mLocalRootView != null) {
-            final ViewParent parent = mLocalRootView.getParent();
-            if (parent != null && parent instanceof ViewGroup) {
-                ((ViewGroup) parent).removeView(mLocalRootView);
-            }
-            mLocalRootView.removeAllViews();
-        }
-        if (mTouchEventWindow != null) {
-            mTouchEventWindow.dismiss();
-        }
-    }
-
-    @Override
-    public void hideUi() {
-        mAddToDictionaryIndicatorView.setVisibility(View.GONE);
-        mTouchEventWindow.dismiss();
-    }
-
-    private static final RectF getIndicatorBoundsInScreenCoordinates(final Matrix matrix,
-            final RectF composingTextBounds, final boolean showAtLeftSide) {
-        final float indicatorSize = composingTextBounds.height();
-        final RectF indicatorBounds;
-        if (showAtLeftSide) {
-            indicatorBounds = new RectF(composingTextBounds.left - indicatorSize,
-                    composingTextBounds.top, composingTextBounds.left,
-                    composingTextBounds.top + indicatorSize);
-        } else {
-            indicatorBounds = new RectF(composingTextBounds.right, composingTextBounds.top,
-                    composingTextBounds.right + indicatorSize,
-                    composingTextBounds.top + indicatorSize);
-        }
-        matrix.mapRect(indicatorBounds);
-        return indicatorBounds;
-    }
-
-    @Override
-    public void layoutUi(final Matrix matrix, final RectF composingTextBounds,
-            final boolean useRtlLayout) {
-        RectF indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix,
-                composingTextBounds, useRtlLayout /* showAtLeftSide */);
-        if (indicatorBoundsInScreenCoordinates.left < mDisplayRect.left ||
-                mDisplayRect.right < indicatorBoundsInScreenCoordinates.right) {
-            // The indicator is clipped by the screen. Show the indicator at the opposite side.
-            indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix,
-                    composingTextBounds, !useRtlLayout /* showAtLeftSide */);
-        }
-
-        mAddToDictionaryIndicatorView.setBounds(indicatorBoundsInScreenCoordinates);
-
-        final RectF hitAreaBoundsInScreenCoordinates = new RectF();
-        matrix.mapRect(hitAreaBoundsInScreenCoordinates, composingTextBounds);
-        hitAreaBoundsInScreenCoordinates.union(indicatorBoundsInScreenCoordinates);
-        hitAreaBoundsInScreenCoordinates.inset(-mHitAreaMarginInPixels, -mHitAreaMarginInPixels);
-
-        final int[] originScreen = new int[2];
-        mLocalRootView.getLocationOnScreen(originScreen);
-        final int viewOriginX = originScreen[0];
-        final int viewOriginY = originScreen[1];
-        mAddToDictionaryIndicatorView.setX(indicatorBoundsInScreenCoordinates.left - viewOriginX);
-        mAddToDictionaryIndicatorView.setY(indicatorBoundsInScreenCoordinates.top - viewOriginY);
-        mAddToDictionaryIndicatorView.setVisibility(View.VISIBLE);
-
-        if (mTouchEventWindow.isShowing()) {
-            mTouchEventWindow.update((int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
-                    (int)hitAreaBoundsInScreenCoordinates.top - viewOriginY,
-                    (int)hitAreaBoundsInScreenCoordinates.width(),
-                    (int)hitAreaBoundsInScreenCoordinates.height());
-        } else {
-            mTouchEventWindow.setWidth((int)hitAreaBoundsInScreenCoordinates.width());
-            mTouchEventWindow.setHeight((int)hitAreaBoundsInScreenCoordinates.height());
-            mTouchEventWindow.showAtLocation(mLocalRootView, Gravity.NO_GRAVITY,
-                    (int)hitAreaBoundsInScreenCoordinates.left - viewOriginX,
-                    (int)hitAreaBoundsInScreenCoordinates.top - viewOriginY);
-        }
-    }
-
-    @Override
-    public void setOnClickListener(final Runnable listener) {
-        mTouchEventWindowClickListenerView.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(final View arg0) {
-                listener.run();
-            }
-        });
-    }
-
-    private static class IndicatorView extends View {
-        private final Path mPath;
-        private final Path mTmpPath = new Path();
-        private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        private final Matrix mMatrix = new Matrix();
-        private final int mBackgroundColor;
-        private final int mForegroundColor;
-        private final RectF mBounds = new RectF();
-        public IndicatorView(Context context, final int pathResourceId,
-                final int sizeResourceId, final int backgroundColorResourceId,
-                final int foregroundColroResourceId) {
-            super(context);
-            final Resources resources = context.getResources();
-            mPath = createPath(resources, pathResourceId, sizeResourceId);
-            mBackgroundColor = resources.getColor(backgroundColorResourceId);
-            mForegroundColor = resources.getColor(foregroundColroResourceId);
-        }
-
-        public void setBounds(final RectF rect) {
-            mBounds.set(rect);
-        }
-
-        @Override
-        protected void onDraw(Canvas canvas) {
-            mPaint.setColor(mBackgroundColor);
-            mPaint.setStyle(Paint.Style.FILL);
-            canvas.drawRect(0.0f, 0.0f, mBounds.width(), mBounds.height(), mPaint);
-
-            mMatrix.reset();
-            mMatrix.postScale(mBounds.width(), mBounds.height());
-            mPath.transform(mMatrix, mTmpPath);
-            mPaint.setColor(mForegroundColor);
-            canvas.drawPath(mTmpPath, mPaint);
-        }
-
-        private static Path createPath(final Resources resources, final int pathResourceId,
-                final int sizeResourceId) {
-            final int size = resources.getInteger(sizeResourceId);
-            final float normalizationFactor = 1.0f / size;
-            final int[] array = resources.getIntArray(pathResourceId);
-
-            final Path path = new Path();
-            for (int i = 0; i < array.length; i += 2) {
-                if (i == 0) {
-                    path.moveTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
-                } else {
-                    path.lineTo(array[i] * normalizationFactor, array[i + 1] * normalizationFactor);
-                }
-            }
-            path.close();
-            return path;
-        }
-    }
-
-    private static ViewGroup getContentView(final View view) {
-        final View rootView = view.getRootView();
-        if (rootView == null) {
-            return null;
-        }
-
-        final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content);
-        if (windowContentView == null) {
-            return null;
-        }
-        return windowContentView;
-    }
-
-    private static final class AddToDictionaryIndicatorView extends TextDecoratorUi.IndicatorView {
-        public AddToDictionaryIndicatorView(final Context context) {
-            super(context, R.array.text_decorator_add_to_dictionary_indicator_path,
-                    R.integer.text_decorator_add_to_dictionary_indicator_path_size,
-                    R.color.text_decorator_add_to_dictionary_indicator_background_color,
-                    R.color.text_decorator_add_to_dictionary_indicator_foreground_color);
-        }
-    }
-}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java
deleted file mode 100644
index 9e30e41..0000000
--- a/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.graphics.Matrix;
-import android.graphics.RectF;
-
-/**
- * This interface defines how UI operations required for {@link TextDecorator} are delegated to
- * the actual UI implementation class.
- */
-public interface TextDecoratorUiOperator {
-    /**
-     * Called to notify that the UI is ready to be disposed.
-     */
-    void disposeUi();
-
-    /**
-     * Called when the UI should become invisible.
-     */
-    void hideUi();
-
-    /**
-     * Called to set the new click handler.
-     * @param onClickListener the callback object whose {@link Runnable#run()} should be called when
-     * the indicator is clicked.
-     */
-    void setOnClickListener(final Runnable onClickListener);
-
-    /**
-     * Called when the layout should be updated.
-     * @param matrix The matrix that transforms the local coordinates into the screen coordinates.
-     * @param composingTextBounds The bounding box of the composing text, in local coordinates.
-     * @param useRtlLayout {@code true} if the indicator should be optimized for RTL layout.
-     */
-    void layoutUi(final Matrix matrix, final RectF composingTextBounds, final boolean useRtlLayout);
-}
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
index 0f9dc85..a9711ae 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java
@@ -29,7 +29,6 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.settings.Settings;
 
@@ -147,7 +146,7 @@
         mShownCategories.add(properties);
     }
 
-    public String getCategoryName(final int categoryId, final int categoryPageId) {
+    public static String getCategoryName(final int categoryId, final int categoryPageId) {
         return sCategoryName[categoryId] + "-" + categoryPageId;
     }
 
@@ -271,7 +270,7 @@
     }
 
     private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) {
-        return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id;
+        return (((long) categoryId) << Integer.SIZE) | id;
     }
 
     public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) {
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
index 925ec6b..09313f8 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java
@@ -138,6 +138,21 @@
         return mKeyDetector.detectHitKey(x, y);
     }
 
+    void callListenerOnReleaseKey(final Key releasedKey, final boolean withKeyRegistering) {
+        releasedKey.onReleased();
+        invalidateKey(releasedKey);
+        if (withKeyRegistering) {
+            mListener.onReleaseKey(releasedKey);
+        }
+    }
+
+    void callListenerOnPressKey(final Key pressedKey) {
+        mPendingKeyDown = null;
+        pressedKey.onPressed();
+        invalidateKey(pressedKey);
+        mListener.onPressKey(pressedKey);
+    }
+
     public void releaseCurrentKey(final boolean withKeyRegistering) {
         mHandler.removeCallbacks(mPendingKeyDown);
         mPendingKeyDown = null;
@@ -145,11 +160,7 @@
         if (currentKey == null) {
             return;
         }
-        currentKey.onReleased();
-        invalidateKey(currentKey);
-        if (withKeyRegistering) {
-            mListener.onReleaseKey(currentKey);
-        }
+        callListenerOnReleaseKey(currentKey, withKeyRegistering);
         mCurrentKey = null;
     }
 
@@ -165,10 +176,7 @@
         mPendingKeyDown = new Runnable() {
             @Override
             public void run() {
-                mPendingKeyDown = null;
-                key.onPressed();
-                invalidateKey(key);
-                mListener.onPressKey(key);
+                callListenerOnPressKey(key);
             }
         };
         mHandler.postDelayed(mPendingKeyDown, KEY_PRESS_DELAY_TIME);
@@ -195,15 +203,11 @@
             mHandler.postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    key.onReleased();
-                    invalidateKey(key);
-                    mListener.onReleaseKey(key);
+                    callListenerOnReleaseKey(key, true /* withRegistering */);
                 }
             }, KEY_RELEASE_DELAY_TIME);
         } else {
-            key.onReleased();
-            invalidateKey(key);
-            mListener.onReleaseKey(key);
+            callListenerOnReleaseKey(key, true /* withRegistering */);
         }
         return true;
     }
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
index e37cd23..a3b869d 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
@@ -16,13 +16,12 @@
 
 package com.android.inputmethod.keyboard.emoji;
 
-import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE;
+import static com.android.inputmethod.latin.common.Constants.NOT_A_COORDINATE;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Color;
-import android.os.CountDownTimer;
 import android.preference.PreferenceManager;
 import android.support.v4.view.ViewPager;
 import android.util.AttributeSet;
@@ -47,13 +46,11 @@
 import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * View class to implement Emoji palettes.
  * The Emoji keyboard consists of group of views layout/emoji_palettes_view.
@@ -75,9 +72,9 @@
     private final int mCategoryIndicatorBackgroundResId;
     private final int mCategoryPageIndicatorColor;
     private final int mCategoryPageIndicatorBackground;
-    private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener;
     private EmojiPalettesAdapter mEmojiPalettesAdapter;
     private final EmojiLayoutParams mEmojiLayoutParams;
+    private final DeleteKeyOnTouchListener mDeleteKeyOnTouchListener;
 
     private ImageButton mDeleteKey;
     private TextView mAlphabetKeyLeft;
@@ -113,7 +110,7 @@
                 context, null /* editorInfo */);
         final Resources res = context.getResources();
         mEmojiLayoutParams = new EmojiLayoutParams(res);
-        builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype());
+        builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
         builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
                 mEmojiLayoutParams.mEmojiKeyboardHeight);
         final KeyboardLayoutSet layoutSet = builder.build();
@@ -132,7 +129,7 @@
         mCategoryPageIndicatorBackground = emojiPalettesViewAttr.getColor(
                 R.styleable.EmojiPalettesView_categoryPageIndicatorBackground, 0);
         emojiPalettesViewAttr.recycle();
-        mDeleteKeyOnTouchListener = new DeleteKeyOnTouchListener(context);
+        mDeleteKeyOnTouchListener = new DeleteKeyOnTouchListener();
     }
 
     @Override
@@ -149,11 +146,14 @@
     }
 
     private void addTab(final TabHost host, final int categoryId) {
-        final String tabId = mEmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
+        final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
         final TabHost.TabSpec tspec = host.newTabSpec(tabId);
         tspec.setContent(R.id.emoji_keyboard_dummy);
         final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
                 R.layout.emoji_keyboard_tab_icon, null);
+        // TODO: Replace background color with its own setting rather than using the
+        //       category page indicator background as a workaround.
+        iconView.setBackgroundColor(mCategoryPageIndicatorBackground);
         iconView.setImageResource(mEmojiCategory.getCategoryTabIcon(categoryId));
         iconView.setContentDescription(mEmojiCategory.getAccessibilityDescription(categoryId));
         tspec.setIndicator(iconView);
@@ -265,7 +265,7 @@
 
     @Override
     public void onPageScrolled(final int position, final float positionOffset,
-            final int positionOffsetPixels) {
+                               final int positionOffsetPixels) {
         mEmojiPalettesAdapter.onPageScrolled();
         final Pair<Integer, Integer> newPos =
                 mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
@@ -364,7 +364,7 @@
     }
 
     private static void setupAlphabetKey(final TextView alphabetKey, final String label,
-            final KeyDrawParams params) {
+                                         final KeyDrawParams params) {
         alphabetKey.setText(label);
         alphabetKey.setTextColor(params.mFunctionalTextColor);
         alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize);
@@ -372,7 +372,8 @@
     }
 
     public void startEmojiPalettes(final String switchToAlphaLabel,
-            final KeyVisualAttributes keyVisualAttr, final KeyboardIconsSet iconSet) {
+                                   final KeyVisualAttributes keyVisualAttr,
+                                   final KeyboardIconsSet iconSet) {
         final int deleteIconResId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY);
         if (deleteIconResId != 0) {
             mDeleteKey.setImageResource(deleteIconResId);
@@ -398,7 +399,7 @@
 
     public void setKeyboardActionListener(final KeyboardActionListener listener) {
         mKeyboardActionListener = listener;
-        mDeleteKeyOnTouchListener.setKeyboardActionListener(mKeyboardActionListener);
+        mDeleteKeyOnTouchListener.setKeyboardActionListener(listener);
     }
 
     private void updateEmojiCategoryPageIdView() {
@@ -436,45 +437,9 @@
     }
 
     private static class DeleteKeyOnTouchListener implements OnTouchListener {
-        static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
-        final long mKeyRepeatStartTimeout;
-        final long mKeyRepeatInterval;
-
-        public DeleteKeyOnTouchListener(Context context) {
-            final Resources res = context.getResources();
-            mKeyRepeatStartTimeout = res.getInteger(R.integer.config_key_repeat_start_timeout);
-            mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
-            mTimer = new CountDownTimer(MAX_REPEAT_COUNT_TIME, mKeyRepeatInterval) {
-                @Override
-                public void onTick(long millisUntilFinished) {
-                    final long elapsed = MAX_REPEAT_COUNT_TIME - millisUntilFinished;
-                    if (elapsed < mKeyRepeatStartTimeout) {
-                        return;
-                    }
-                    onKeyRepeat();
-                }
-                @Override
-                public void onFinish() {
-                    onKeyRepeat();
-                }
-            };
-        }
-
-        /** Key-repeat state. */
-        private static final int KEY_REPEAT_STATE_INITIALIZED = 0;
-        // The key is touched but auto key-repeat is not started yet.
-        private static final int KEY_REPEAT_STATE_KEY_DOWN = 1;
-        // At least one key-repeat event has already been triggered and the key is not released.
-        private static final int KEY_REPEAT_STATE_KEY_REPEAT = 2;
-
         private KeyboardActionListener mKeyboardActionListener =
                 KeyboardActionListener.EMPTY_LISTENER;
 
-        // TODO: Do the same things done in PointerTracker
-        private final CountDownTimer mTimer;
-        private int mState = KEY_REPEAT_STATE_INITIALIZED;
-        private int mRepeatCount = 0;
-
         public void setKeyboardActionListener(final KeyboardActionListener listener) {
             mKeyboardActionListener = listener;
         }
@@ -482,79 +447,40 @@
         @Override
         public boolean onTouch(final View v, final MotionEvent event) {
             switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                onTouchDown(v);
-                return true;
-            case MotionEvent.ACTION_MOVE:
-                final float x = event.getX();
-                final float y = event.getY();
-                if (x < 0.0f || v.getWidth() < x || y < 0.0f || v.getHeight() < y) {
-                    // Stop generating key events once the finger moves away from the view area.
-                    onTouchCanceled(v);
-                }
-                return true;
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                onTouchUp(v);
-                return true;
+                case MotionEvent.ACTION_DOWN:
+                    onTouchDown(v);
+                    return true;
+                case MotionEvent.ACTION_MOVE:
+                    final float x = event.getX();
+                    final float y = event.getY();
+                    if (x < 0.0f || v.getWidth() < x || y < 0.0f || v.getHeight() < y) {
+                        // Stop generating key events once the finger moves away from the view area.
+                        onTouchCanceled(v);
+                    }
+                    return true;
+                case MotionEvent.ACTION_CANCEL:
+                case MotionEvent.ACTION_UP:
+                    onTouchUp(v);
+                    return true;
             }
             return false;
         }
 
-        private void handleKeyDown() {
-            mKeyboardActionListener.onPressKey(
-                    Constants.CODE_DELETE, mRepeatCount, true /* isSinglePointer */);
-        }
-
-        private void handleKeyUp() {
-            mKeyboardActionListener.onCodeInput(Constants.CODE_DELETE,
-                    NOT_A_COORDINATE, NOT_A_COORDINATE, false /* isKeyRepeat */);
-            mKeyboardActionListener.onReleaseKey(
-                    Constants.CODE_DELETE, false /* withSliding */);
-            ++mRepeatCount;
-        }
-
         private void onTouchDown(final View v) {
-            mTimer.cancel();
-            mRepeatCount = 0;
-            handleKeyDown();
+            mKeyboardActionListener.onPressKey(Constants.CODE_DELETE,
+                    0 /* repeatCount */, true /* isSinglePointer */);
             v.setPressed(true /* pressed */);
-            mState = KEY_REPEAT_STATE_KEY_DOWN;
-            mTimer.start();
         }
 
         private void onTouchUp(final View v) {
-            mTimer.cancel();
-            if (mState == KEY_REPEAT_STATE_KEY_DOWN) {
-                handleKeyUp();
-            }
+            mKeyboardActionListener.onCodeInput(Constants.CODE_DELETE,
+                    NOT_A_COORDINATE, NOT_A_COORDINATE, false /* isKeyRepeat */);
+            mKeyboardActionListener.onReleaseKey(Constants.CODE_DELETE, false /* withSliding */);
             v.setPressed(false /* pressed */);
-            mState = KEY_REPEAT_STATE_INITIALIZED;
         }
 
         private void onTouchCanceled(final View v) {
-            mTimer.cancel();
             v.setBackgroundColor(Color.TRANSPARENT);
-            mState = KEY_REPEAT_STATE_INITIALIZED;
-        }
-
-        // Called by {@link #mTimer} in the UI thread as an auto key-repeat signal.
-        void onKeyRepeat() {
-            switch (mState) {
-            case KEY_REPEAT_STATE_INITIALIZED:
-                // Basically this should not happen.
-                break;
-            case KEY_REPEAT_STATE_KEY_DOWN:
-                // Do not call {@link #handleKeyDown} here because it has already been called
-                // in {@link #onTouchDown}.
-                handleKeyUp();
-                mState = KEY_REPEAT_STATE_KEY_REPEAT;
-                break;
-            case KEY_REPEAT_STATE_KEY_REPEAT:
-                handleKeyDown();
-                handleKeyUp();
-                break;
-            }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
index a194f3d..c76a9ac 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/AbstractDrawingPreview.java
@@ -19,8 +19,11 @@
 import android.graphics.Canvas;
 import android.view.View;
 
+import com.android.inputmethod.keyboard.MainKeyboardView;
 import com.android.inputmethod.keyboard.PointerTracker;
 
+import javax.annotation.Nonnull;
+
 /**
  * Abstract base class for previews that are drawn on DrawingPreviewPlacerView, e.g.,
  * GestureFloatingTextDrawingPreview, GestureTrailsDrawingPreview, and
@@ -31,7 +34,7 @@
     private boolean mPreviewEnabled;
     private boolean mHasValidGeometry;
 
-    public void setDrawingView(final DrawingPreviewPlacerView drawingView) {
+    public void setDrawingView(@Nonnull final DrawingPreviewPlacerView drawingView) {
         mDrawingView = drawingView;
         drawingView.addPreview(this);
     }
@@ -51,16 +54,16 @@
     }
 
     /**
-     * Set {@link MainKeyboardView} geometry and position in the {@link SoftInputWindow}.
+     * Set {@link MainKeyboardView} geometry and position in the window of input method.
      * The class that is overriding this method must call this super implementation.
      *
      * @param originCoords the top-left coordinates of the {@link MainKeyboardView} in
-     *        {@link SoftInputWindow} coordinate-system. This is unused but has a point in an
+     *        the input method window coordinate-system. This is unused but has a point in an
      *        extended class, such as {@link GestureTrailsDrawingPreview}.
      * @param width the width of {@link MainKeyboardView}.
      * @param height the height of {@link MainKeyboardView}.
      */
-    public void setKeyboardViewGeometry(final int[] originCoords, final int width,
+    public void setKeyboardViewGeometry(@Nonnull final int[] originCoords, final int width,
             final int height) {
         mHasValidGeometry = (width > 0 && height > 0);
     }
@@ -71,11 +74,11 @@
      * Draws the preview
      * @param canvas The canvas where the preview is drawn.
      */
-    public abstract void drawPreview(final Canvas canvas);
+    public abstract void drawPreview(@Nonnull final Canvas canvas);
 
     /**
      * Set the position of the preview.
      * @param tracker The new location of the preview is based on the points in PointerTracker.
      */
-    public abstract void setPreviewPosition(final PointerTracker tracker);
+    public abstract void setPreviewPosition(@Nonnull final PointerTracker tracker);
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
index cd98759..77d0e7a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/BatchInputArbiter.java
@@ -16,8 +16,8 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.InputPointers;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
 
 /**
  * This class arbitrates batch input.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java
index 6420edd..4b355a4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java
@@ -20,8 +20,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.define.DebugFlags;
 
 // This hack is applied to certain classes of tablets.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
index dce7fc5..2e2ed52 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/CodesArrayParser.java
@@ -16,8 +16,8 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import android.text.TextUtils;
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java
deleted file mode 100644
index df82bec..0000000
--- a/java/src/com/android/inputmethod/keyboard/internal/DrawingHandler.java
+++ /dev/null
@@ -1,77 +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.keyboard.internal;
-
-import android.os.Message;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.internal.DrawingHandler.Callbacks;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
-
-// TODO: Separate this class into KeyPreviewHandler and BatchInputPreviewHandler or so.
-public class DrawingHandler extends LeakGuardHandlerWrapper<Callbacks> {
-    public interface Callbacks {
-        public void dismissKeyPreviewWithoutDelay(Key key);
-        public void dismissAllKeyPreviews();
-        public void showGestureFloatingPreviewText(SuggestedWords suggestedWords);
-    }
-
-    private static final int MSG_DISMISS_KEY_PREVIEW = 0;
-    private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
-
-    public DrawingHandler(final Callbacks ownerInstance) {
-        super(ownerInstance);
-    }
-
-    @Override
-    public void handleMessage(final Message msg) {
-        final Callbacks callbacks = getOwnerInstance();
-        if (callbacks == null) {
-            return;
-        }
-        switch (msg.what) {
-        case MSG_DISMISS_KEY_PREVIEW:
-            callbacks.dismissKeyPreviewWithoutDelay((Key)msg.obj);
-            break;
-        case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
-            callbacks.showGestureFloatingPreviewText(SuggestedWords.EMPTY);
-            break;
-        }
-    }
-
-    public void dismissKeyPreview(final long delay, final Key key) {
-        sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay);
-    }
-
-    private void cancelAllDismissKeyPreviews() {
-        removeMessages(MSG_DISMISS_KEY_PREVIEW);
-        final Callbacks callbacks = getOwnerInstance();
-        if (callbacks == null) {
-            return;
-        }
-        callbacks.dismissAllKeyPreviews();
-    }
-
-    public void dismissGestureFloatingPreviewText(final long delay) {
-        sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay);
-    }
-
-    public void cancelAllMessages() {
-        cancelAllDismissKeyPreviews();
-    }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
index a5d47ad..9c0d743 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingPreviewPlacerView.java
@@ -24,7 +24,7 @@
 import android.util.AttributeSet;
 import android.widget.RelativeLayout;
 
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 
 import java.util.ArrayList;
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java
new file mode 100644
index 0000000..06bdfc4
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/DrawingProxy.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.MoreKeysPanel;
+import com.android.inputmethod.keyboard.PointerTracker;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public interface DrawingProxy {
+    /**
+     * Called when a key is being pressed.
+     * @param key the {@link Key} that is being pressed.
+     * @param withPreview true if key popup preview should be displayed.
+     */
+    public void onKeyPressed(@Nonnull Key key, boolean withPreview);
+
+    /**
+     * Called when a key is being released.
+     * @param key the {@link Key} that is being released.
+     * @param withAnimation when true, key popup preview should be dismissed with animation.
+     */
+    public void onKeyReleased(@Nonnull Key key, boolean withAnimation);
+
+    /**
+     * Start showing more keys keyboard of a key that is being long pressed.
+     * @param key the {@link Key} that is being long pressed and showing more keys keyboard.
+     * @param tracker the {@link PointerTracker} that detects this long pressing.
+     * @return {@link MoreKeysPanel} that is being shown. null if there is no need to show more keys
+     *     keyboard.
+     */
+    @Nullable
+    public MoreKeysPanel showMoreKeysKeyboard(@Nonnull Key key, @Nonnull PointerTracker tracker);
+
+    /**
+     * Start a while-typing-animation.
+     * @param fadeInOrOut {@link #FADE_IN} starts while-typing-fade-in animation.
+     * {@link #FADE_OUT} starts while-typing-fade-out animation.
+     */
+    public void startWhileTypingAnimation(int fadeInOrOut);
+    public static final int FADE_IN = 0;
+    public static final int FADE_OUT = 1;
+
+    /**
+     * Show sliding-key input preview.
+     * @param tracker the {@link PointerTracker} that is currently doing the sliding-key input.
+     * null to dismiss the sliding-key input preview.
+     */
+    public void showSlidingKeyInputPreview(@Nullable PointerTracker tracker);
+
+    /**
+     * Show gesture trails.
+     * @param tracker the {@link PointerTracker} whose gesture trail will be shown.
+     * @param showsFloatingPreviewText when true, a gesture floating preview text will be shown
+     * with this <code>tracker</code>'s trail.
+     */
+    public void showGestureTrail(@Nonnull PointerTracker tracker, boolean showsFloatingPreviewText);
+
+    /**
+     * Dismiss a gesture floating preview text without delay.
+     */
+    public void dismissGestureFloatingPreviewTextWithoutDelay();
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
index fd84856..5443c2a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingTextDrawingPreview.java
@@ -27,7 +27,9 @@
 import com.android.inputmethod.keyboard.PointerTracker;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+
+import javax.annotation.Nonnull;
 
 /**
  * The class for single gesture preview text. The class for multiple gesture preview text will be
@@ -98,7 +100,7 @@
     private final RectF mGesturePreviewRectangle = new RectF();
     private int mPreviewTextX;
     private int mPreviewTextY;
-    private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+    private SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance();
     private final int[] mLastPointerCoords = CoordinateUtils.newInstance();
 
     public GestureFloatingTextDrawingPreview(final TypedArray mainKeyboardViewAttr) {
@@ -110,7 +112,11 @@
         // Nothing to do here.
     }
 
-    public void setSuggetedWords(final SuggestedWords suggestedWords) {
+    public void dismissGestureFloatingPreviewText() {
+        setSuggetedWords(SuggestedWords.getEmptyInstance());
+    }
+
+    public void setSuggetedWords(@Nonnull final SuggestedWords suggestedWords) {
         if (!isPreviewEnabled()) {
             return;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeDrawingPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeDrawingPoints.java
index 7d09e9d..07ef009 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeDrawingPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeDrawingPoints.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import com.android.inputmethod.latin.utils.ResizableIntArray;
+import com.android.inputmethod.latin.common.ResizableIntArray;
 
 /**
  * This class holds drawing points to represent a gesture stroke on the screen.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java
index e49e538..3e90111 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeRecognitionPoints.java
@@ -18,9 +18,9 @@
 
 import android.util.Log;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.InputPointers;
-import com.android.inputmethod.latin.utils.ResizableIntArray;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.ResizableIntArray;
 
 /**
  * This class holds event points to recognize a gesture stroke.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java
index bf4c4da..4d998e4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureTrailDrawingPoints.java
@@ -23,8 +23,8 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.ResizableIntArray;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.ResizableIntArray;
 
 /**
  * This class holds drawing points to represent a gesture trail. The gesture trail may contain
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
index df50efd..3ef9ea1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyDrawParams.java
@@ -20,8 +20,12 @@
 
 import com.android.inputmethod.latin.utils.ResourceUtils;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public final class KeyDrawParams {
-    public Typeface mTypeface;
+    @Nonnull
+    public Typeface mTypeface = Typeface.DEFAULT;
 
     public int mLetterSize;
     public int mLabelSize;
@@ -49,7 +53,7 @@
 
     public KeyDrawParams() {}
 
-    private KeyDrawParams(final KeyDrawParams copyFrom) {
+    private KeyDrawParams(@Nonnull final KeyDrawParams copyFrom) {
         mTypeface = copyFrom.mTypeface;
 
         mLetterSize = copyFrom.mLetterSize;
@@ -77,7 +81,7 @@
         mAnimAlpha = copyFrom.mAnimAlpha;
     }
 
-    public void updateParams(final int keyHeight, final KeyVisualAttributes attr) {
+    public void updateParams(final int keyHeight, @Nullable final KeyVisualAttributes attr) {
         if (attr == null) {
             return;
         }
@@ -117,8 +121,9 @@
                 attr.mHintLabelOffCenterRatio, mHintLabelOffCenterRatio);
     }
 
+    @Nonnull
     public KeyDrawParams mayCloneAndUpdateParams(final int keyHeight,
-            final KeyVisualAttributes attr) {
+            @Nullable final KeyVisualAttributes attr) {
         if (attr == null) {
             return this;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
index 5005b7d..448f1b4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java
@@ -23,12 +23,11 @@
 import android.view.ViewGroup;
 
 import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 
 import java.util.ArrayDeque;
 import java.util.HashMap;
-import java.util.HashSet;
 
 /**
  * This class controls pop up key previews. This class decides:
@@ -69,12 +68,6 @@
         return mShowingKeyPreviewViews.containsKey(key);
     }
 
-    public void dismissAllKeyPreviews() {
-        for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) {
-            dismissKeyPreview(key, false /* withAnimation */);
-        }
-    }
-
     public void dismissKeyPreview(final Key key, final boolean withAnimation) {
         if (key == null) {
             return;
@@ -148,7 +141,7 @@
         keyPreviewView.setPivotY(previewHeight);
     }
 
-    private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
+    void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
             final boolean withAnimation) {
         if (!withAnimation) {
             keyPreviewView.setVisibility(View.VISIBLE);
@@ -166,25 +159,25 @@
     }
 
     public Animator createShowUpAnimator(final Key key, final KeyPreviewView keyPreviewView) {
-        final Animator animator = mParams.createShowUpAnimator(keyPreviewView);
-        animator.addListener(new AnimatorListenerAdapter() {
+        final Animator showUpAnimator = mParams.createShowUpAnimator(keyPreviewView);
+        showUpAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(final Animator animator) {
                 showKeyPreview(key, keyPreviewView, false /* withAnimation */);
             }
         });
-        return animator;
+        return showUpAnimator;
     }
 
     private Animator createDismissAnimator(final Key key, final KeyPreviewView keyPreviewView) {
-        final Animator animator = mParams.createDismissAnimator(keyPreviewView);
-        animator.addListener(new AnimatorListenerAdapter() {
+        final Animator dismissAnimator = mParams.createDismissAnimator(keyPreviewView);
+        dismissAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(final Animator animator) {
                 dismissKeyPreview(key, false /* withAnimation */);
             }
         });
-        return animator;
+        return dismissAnimator;
     }
 
     private static class KeyPreviewAnimators extends AnimatorListenerAdapter {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
index 48ba8e0..3eb62e7 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java
@@ -16,11 +16,14 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT;
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
+import static com.android.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
+import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * The string parser of the key specification.
@@ -53,11 +56,11 @@
         // Intentional empty constructor for utility class.
     }
 
-    private static boolean hasIcon(final String keySpec) {
+    private static boolean hasIcon(@Nonnull final String keySpec) {
         return keySpec.startsWith(KeyboardIconsSet.PREFIX_ICON);
     }
 
-    private static boolean hasCode(final String keySpec, final int labelEnd) {
+    private static boolean hasCode(@Nonnull final String keySpec, final int labelEnd) {
         if (labelEnd <= 0 || labelEnd + 1 >= keySpec.length()) {
             return false;
         }
@@ -72,7 +75,8 @@
         return false;
     }
 
-    private static String parseEscape(final String text) {
+    @Nonnull
+    private static String parseEscape(@Nonnull final String text) {
         if (text.indexOf(BACKSLASH) < 0) {
             return text;
         }
@@ -91,7 +95,7 @@
         return sb.toString();
     }
 
-    private static int indexOfLabelEnd(final String keySpec) {
+    private static int indexOfLabelEnd(@Nonnull final String keySpec) {
         final int length = keySpec.length();
         if (keySpec.indexOf(BACKSLASH) < 0) {
             final int labelEnd = keySpec.indexOf(VERTICAL_BAR);
@@ -116,22 +120,25 @@
         return -1;
     }
 
-    private static String getBeforeLabelEnd(final String keySpec, final int labelEnd) {
+    @Nonnull
+    private static String getBeforeLabelEnd(@Nonnull final String keySpec, final int labelEnd) {
         return (labelEnd < 0) ? keySpec : keySpec.substring(0, labelEnd);
     }
 
-    private static String getAfterLabelEnd(final String keySpec, final int labelEnd) {
+    @Nonnull
+    private static String getAfterLabelEnd(@Nonnull final String keySpec, final int labelEnd) {
         return keySpec.substring(labelEnd + /* VERTICAL_BAR */1);
     }
 
-    private static void checkDoubleLabelEnd(final String keySpec, final int labelEnd) {
+    private static void checkDoubleLabelEnd(@Nonnull final String keySpec, final int labelEnd) {
         if (indexOfLabelEnd(getAfterLabelEnd(keySpec, labelEnd)) < 0) {
             return;
         }
         throw new KeySpecParserError("Multiple " + VERTICAL_BAR + ": " + keySpec);
     }
 
-    public static String getLabel(final String keySpec) {
+    @Nullable
+    public static String getLabel(@Nullable final String keySpec) {
         if (keySpec == null) {
             // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory.
             return null;
@@ -147,7 +154,8 @@
         return label;
     }
 
-    private static String getOutputTextInternal(final String keySpec, final int labelEnd) {
+    @Nullable
+    private static String getOutputTextInternal(@Nonnull final String keySpec, final int labelEnd) {
         if (labelEnd <= 0) {
             return null;
         }
@@ -155,7 +163,8 @@
         return parseEscape(getAfterLabelEnd(keySpec, labelEnd));
     }
 
-    public static String getOutputText(final String keySpec) {
+    @Nullable
+    public static String getOutputText(@Nullable final String keySpec) {
         if (keySpec == null) {
             // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory.
             return null;
@@ -184,7 +193,7 @@
         return (StringUtils.codePointCount(label) == 1) ? null : label;
     }
 
-    public static int getCode(final String keySpec) {
+    public static int getCode(@Nullable final String keySpec) {
         if (keySpec == null) {
             // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory.
             return CODE_UNSPECIFIED;
@@ -211,7 +220,7 @@
         return (StringUtils.codePointCount(label) == 1) ? label.codePointAt(0) : CODE_OUTPUT_TEXT;
     }
 
-    public static int parseCode(final String text, final int defaultCode) {
+    public static int parseCode(@Nullable final String text, final int defaultCode) {
         if (text == null) {
             return defaultCode;
         }
@@ -226,7 +235,7 @@
         return defaultCode;
     }
 
-    public static int getIconId(final String keySpec) {
+    public static int getIconId(@Nullable final String keySpec) {
         if (keySpec == null) {
             // TODO: Throw {@link KeySpecParserError} once Key.keyLabel attribute becomes mandatory.
             return KeyboardIconsSet.ICON_UNDEFINED;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
index 7941ddd..28aa22c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyle.java
@@ -18,18 +18,22 @@
 
 import android.content.res.TypedArray;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public abstract class KeyStyle {
     private final KeyboardTextsSet mTextsSet;
 
-    public abstract String[] getStringArray(TypedArray a, int index);
-    public abstract String getString(TypedArray a, int index);
+    public abstract @Nullable String[] getStringArray(TypedArray a, int index);
+    public abstract @Nullable String getString(TypedArray a, int index);
     public abstract int getInt(TypedArray a, int index, int defaultValue);
     public abstract int getFlags(TypedArray a, int index);
 
-    protected KeyStyle(final KeyboardTextsSet textsSet) {
+    protected KeyStyle(@Nonnull final KeyboardTextsSet textsSet) {
         mTextsSet = textsSet;
     }
 
+    @Nullable
     protected String parseString(final TypedArray a, final int index) {
         if (a.hasValue(index)) {
             return mTextsSet.resolveTextReference(a.getString(index));
@@ -37,6 +41,7 @@
         return null;
     }
 
+    @Nullable
     protected String[] parseStringArray(final TypedArray a, final int index) {
         if (a.hasValue(index)) {
             final String text = mTextsSet.resolveTextReference(a.getString(index));
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java
index 5cbb341..61f98c8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java
@@ -29,33 +29,42 @@
 import java.util.Arrays;
 import java.util.HashMap;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public final class KeyStylesSet {
     private static final String TAG = KeyStylesSet.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    @Nonnull
     private final HashMap<String, KeyStyle> mStyles = new HashMap<>();
 
+    @Nonnull
     private final KeyboardTextsSet mTextsSet;
+    @Nonnull
     private final KeyStyle mEmptyKeyStyle;
+    @Nonnull
     private static final String EMPTY_STYLE_NAME = "<empty>";
 
-    public KeyStylesSet(final KeyboardTextsSet textsSet) {
+    public KeyStylesSet(@Nonnull final KeyboardTextsSet textsSet) {
         mTextsSet = textsSet;
         mEmptyKeyStyle = new EmptyKeyStyle(textsSet);
         mStyles.put(EMPTY_STYLE_NAME, mEmptyKeyStyle);
     }
 
     private static final class EmptyKeyStyle extends KeyStyle {
-        EmptyKeyStyle(final KeyboardTextsSet textsSet) {
+        EmptyKeyStyle(@Nonnull final KeyboardTextsSet textsSet) {
             super(textsSet);
         }
 
         @Override
+        @Nullable
         public String[] getStringArray(final TypedArray a, final int index) {
             return parseStringArray(a, index);
         }
 
         @Override
+        @Nullable
         public String getString(final TypedArray a, final int index) {
             return parseString(a, index);
         }
@@ -76,14 +85,16 @@
         private final String mParentStyleName;
         private final SparseArray<Object> mStyleAttributes = new SparseArray<>();
 
-        public DeclaredKeyStyle(final String parentStyleName, final KeyboardTextsSet textsSet,
-                final HashMap<String, KeyStyle> styles) {
+        public DeclaredKeyStyle(@Nonnull final String parentStyleName,
+                @Nonnull final KeyboardTextsSet textsSet,
+                @Nonnull final HashMap<String, KeyStyle> styles) {
             super(textsSet);
             mParentStyleName = parentStyleName;
             mStyles = styles;
         }
 
         @Override
+        @Nullable
         public String[] getStringArray(final TypedArray a, final int index) {
             if (a.hasValue(index)) {
                 return parseStringArray(a, index);
@@ -98,6 +109,7 @@
         }
 
         @Override
+        @Nullable
         public String getString(final TypedArray a, final int index) {
             if (a.hasValue(index)) {
                 return parseString(a, index);
@@ -176,37 +188,43 @@
     public void parseKeyStyleAttributes(final TypedArray keyStyleAttr, final TypedArray keyAttrs,
             final XmlPullParser parser) throws XmlPullParserException {
         final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
+        if (styleName == null) {
+            throw new XmlParseUtils.ParseException(
+                    KeyboardBuilder.TAG_KEY_STYLE + " has no styleName attribute", parser);
+        }
         if (DEBUG) {
             Log.d(TAG, String.format("<%s styleName=%s />",
                     KeyboardBuilder.TAG_KEY_STYLE, styleName));
             if (mStyles.containsKey(styleName)) {
-                Log.d(TAG, "key-style " + styleName + " is overridden at "
+                Log.d(TAG, KeyboardBuilder.TAG_KEY_STYLE + " " + styleName + " is overridden at "
                         + parser.getPositionDescription());
             }
         }
 
-        String parentStyleName = EMPTY_STYLE_NAME;
-        if (keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
-            parentStyleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_parentStyle);
-            if (!mStyles.containsKey(parentStyleName)) {
-                throw new XmlParseUtils.ParseException(
-                        "Unknown parentStyle " + parentStyleName, parser);
-            }
+        final String parentStyleInAttr = keyStyleAttr.getString(
+                R.styleable.Keyboard_KeyStyle_parentStyle);
+        if (parentStyleInAttr != null && !mStyles.containsKey(parentStyleInAttr)) {
+            throw new XmlParseUtils.ParseException(
+                    "Unknown parentStyle " + parentStyleInAttr, parser);
         }
+        final String parentStyleName = (parentStyleInAttr == null) ? EMPTY_STYLE_NAME
+                : parentStyleInAttr;
         final DeclaredKeyStyle style = new DeclaredKeyStyle(parentStyleName, mTextsSet, mStyles);
         style.readKeyAttributes(keyAttrs);
         mStyles.put(styleName, style);
     }
 
+    @Nonnull
     public KeyStyle getKeyStyle(final TypedArray keyAttr, final XmlPullParser parser)
             throws XmlParseUtils.ParseException {
-        if (!keyAttr.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
+        final String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
+        if (styleName == null) {
             return mEmptyKeyStyle;
         }
-        final String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
-        if (!mStyles.containsKey(styleName)) {
+        final KeyStyle style = mStyles.get(styleName);
+        if (style == null) {
             throw new XmlParseUtils.ParseException("Unknown key style: " + styleName, parser);
         }
-        return mStyles.get(styleName);
+        return style;
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
index c60d587..6f000d2 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyVisualAttributes.java
@@ -23,7 +23,11 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public final class KeyVisualAttributes {
+    @Nullable
     public final Typeface mTypeface;
 
     public final float mLetterRatio;
@@ -81,7 +85,8 @@
         }
     }
 
-    public static KeyVisualAttributes newInstance(final TypedArray keyAttr) {
+    @Nullable
+    public static KeyVisualAttributes newInstance(@Nonnull final TypedArray keyAttr) {
         final int indexCount = keyAttr.getIndexCount();
         for (int i = 0; i < indexCount; i++) {
             final int attrId = keyAttr.getIndex(i);
@@ -93,7 +98,7 @@
         return null;
     }
 
-    private KeyVisualAttributes(final TypedArray keyAttr) {
+    private KeyVisualAttributes(@Nonnull final TypedArray keyAttr) {
         if (keyAttr.hasValue(R.styleable.Keyboard_Key_keyTypeface)) {
             mTypeface = Typeface.defaultFromStyle(
                     keyAttr.getInt(R.styleable.Keyboard_Key_keyTypeface, Typeface.NORMAL));
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index fa41927..0eabf6c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -32,11 +32,10 @@
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardTheme;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethod.latin.utils.XmlParseUtils;
 import com.android.inputmethod.latin.utils.XmlParseUtils.ParseException;
 
@@ -45,6 +44,9 @@
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
 
 /**
  * Keyboard Building helper.
@@ -137,6 +139,7 @@
     private static final int DEFAULT_KEYBOARD_COLUMNS = 10;
     private static final int DEFAULT_KEYBOARD_ROWS = 4;
 
+    @Nonnull
     protected final KP mParams;
     protected final Context mContext;
     protected final Resources mResources;
@@ -147,7 +150,7 @@
     private boolean mTopEdge;
     private Key mRightEdgeKey = null;
 
-    public KeyboardBuilder(final Context context, final KP params) {
+    public KeyboardBuilder(final Context context, @Nonnull final KP params) {
         mContext = context;
         final Resources res = context.getResources();
         mResources = res;
@@ -158,8 +161,8 @@
         params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
     }
 
-    public void setAutoGenerate(final KeysCache keysCache) {
-        mParams.mKeysCache = keysCache;
+    public void setAllowRedundantMoreKes(final boolean enabled) {
+        mParams.mAllowRedundantMoreKeys = enabled;
     }
 
     public KeyboardBuilder<KP> load(final int xmlId, final KeyboardId id) {
@@ -188,6 +191,7 @@
         mParams.mProximityCharsCorrectionEnabled = enabled;
     }
 
+    @Nonnull
     public Keyboard build() {
         return new Keyboard(mParams);
     }
@@ -277,7 +281,7 @@
 
             params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
             params.mIconsSet.loadIcons(keyboardAttr);
-            params.mTextsSet.setLocale(params.mId.mLocale, mContext);
+            params.mTextsSet.setLocale(params.mId.getLocale(), mContext);
 
             final int resourceId = keyboardAttr.getResourceId(
                     R.styleable.Keyboard_touchPositionCorrectionData, 0);
@@ -640,7 +644,7 @@
         try {
             final boolean keyboardLayoutSetMatched = matchString(caseAttr,
                     R.styleable.Keyboard_Case_keyboardLayoutSet,
-                    SubtypeLocaleUtils.getKeyboardLayoutSetName(id.mSubtype));
+                    id.mSubtype.getKeyboardLayoutSetName());
             final boolean keyboardLayoutSetElementMatched = matchTypedValue(caseAttr,
                     R.styleable.Keyboard_Case_keyboardLayoutSetElement, id.mElementId,
                     KeyboardId.elementIdToName(id.mElementId));
@@ -668,21 +672,22 @@
                     R.styleable.Keyboard_Case_imeAction, id.imeAction());
             final boolean isIconDefinedMatched = isIconDefined(caseAttr,
                     R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
-            final boolean localeCodeMatched = matchString(caseAttr,
-                    R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
-            final boolean languageCodeMatched = matchString(caseAttr,
-                    R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage());
-            final boolean countryCodeMatched = matchString(caseAttr,
-                    R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
+            final Locale locale = id.getLocale();
+            final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locale);
+            final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locale);
+            final boolean countryCodeMatched = matchCountryCodes(caseAttr, locale);
+            final boolean splitLayoutMatched = matchBoolean(caseAttr,
+                    R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout);
             final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
                     && keyboardThemeMacthed && modeMatched && navigateNextMatched
                     && navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched
                     && hasShortcutKeyMatched  && languageSwitchKeyEnabledMatched
                     && isMultiLineMatched && imeActionMatched && isIconDefinedMatched
-                    && localeCodeMatched && languageCodeMatched && countryCodeMatched;
+                    && localeCodeMatched && languageCodeMatched && countryCodeMatched
+                    && splitLayoutMatched;
 
             if (DEBUG) {
-                startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
+                startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
                         textAttr(caseAttr.getString(
                                 R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"),
                         textAttr(caseAttr.getString(
@@ -707,6 +712,8 @@
                                 "languageSwitchKeyEnabled"),
                         booleanAttr(caseAttr, R.styleable.Keyboard_Case_isMultiLine,
                                 "isMultiLine"),
+                        booleanAttr(caseAttr, R.styleable.Keyboard_Case_isSplitLayout,
+                                "splitLayout"),
                         textAttr(caseAttr.getString(R.styleable.Keyboard_Case_isIconDefined),
                                 "isIconDefined"),
                         textAttr(caseAttr.getString(R.styleable.Keyboard_Case_localeCode),
@@ -724,6 +731,18 @@
         }
     }
 
+    private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale locale) {
+        return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locale.toString());
+    }
+
+    private static boolean matchLanguageCodes(TypedArray caseAttr, Locale locale) {
+        return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode, locale.getLanguage());
+    }
+
+    private static boolean matchCountryCodes(TypedArray caseAttr, Locale locale) {
+        return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode, locale.getCountry());
+    }
+
     private static boolean matchInteger(final TypedArray a, final int index, final int value) {
         // If <case> does not have "index" attribute, that means this <case> is wild-card for
         // the attribute.
@@ -833,7 +852,7 @@
         mTopEdge = false;
     }
 
-    private void endKey(final Key key) {
+    private void endKey(@Nonnull final Key key) {
         mParams.onAddKey(key);
         if (mLeftEdge) {
             key.markAsLeftEdge(mParams);
@@ -846,6 +865,7 @@
     }
 
     private void endKeyboard() {
+        mParams.removeRedundantMoreKeys();
         // {@link #parseGridRows(XmlPullParser,boolean)} may populate keyboard rows higher than
         // previously expected.
         final int actualHeight = mCurrentY - mParams.mVerticalGap + mParams.mBottomPadding;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index 62b69dc..05b4c74 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.HashMap;
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index e1f302c..15a5bd4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -26,6 +26,9 @@
 
 import java.util.HashMap;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public final class KeyboardIconsSet {
     private static final String TAG = KeyboardIconsSet.class.getSimpleName();
 
@@ -127,6 +130,7 @@
         return iconId >= 0 && iconId < ICON_NAMES.length;
     }
 
+    @Nonnull
     public static String getIconName(final int iconId) {
         return isValidIconId(iconId) ? ICON_NAMES[iconId] : "unknown<" + iconId + ">";
     }
@@ -147,6 +151,7 @@
         throw new RuntimeException("unknown icon name: " + name);
     }
 
+    @Nullable
     public Drawable getIconDrawable(final int iconId) {
         if (isValidIconId(iconId)) {
             return mIcons[iconId];
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
index 5df9d3e..738d6a4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java
@@ -20,13 +20,16 @@
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public class KeyboardParams {
     public KeyboardId mId;
     public int mThemeId;
@@ -46,6 +49,7 @@
     public int mLeftPadding;
     public int mRightPadding;
 
+    @Nullable
     public KeyVisualAttributes mKeyVisualAttributes;
 
     public int mDefaultRowHeight;
@@ -60,20 +64,29 @@
     public int GRID_HEIGHT;
 
     // Keys are sorted from top-left to bottom-right order.
+    @Nonnull
     public final SortedSet<Key> mSortedKeys = new TreeSet<>(ROW_COLUMN_COMPARATOR);
+    @Nonnull
     public final ArrayList<Key> mShiftKeys = new ArrayList<>();
+    @Nonnull
     public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<>();
+    @Nonnull
     public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
+    @Nonnull
     public final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
+    @Nonnull
     public final KeyStylesSet mKeyStyles = new KeyStylesSet(mTextsSet);
 
-    public KeysCache mKeysCache;
+    @Nonnull
+    private final UniqueKeysCache mUniqueKeysCache;
+    public boolean mAllowRedundantMoreKeys;
 
     public int mMostCommonKeyHeight = 0;
     public int mMostCommonKeyWidth = 0;
 
     public boolean mProximityCharsCorrectionEnabled;
 
+    @Nonnull
     public final TouchPositionCorrection mTouchPositionCorrection =
             new TouchPositionCorrection();
 
@@ -89,14 +102,22 @@
         }
     };
 
+    public KeyboardParams() {
+        this(UniqueKeysCache.NO_CACHE);
+    }
+
+    public KeyboardParams(@Nonnull final UniqueKeysCache keysCache) {
+        mUniqueKeysCache = keysCache;
+    }
+
     protected void clearKeys() {
         mSortedKeys.clear();
         mShiftKeys.clear();
         clearHistogram();
     }
 
-    public void onAddKey(final Key newKey) {
-        final Key key = (mKeysCache != null) ? mKeysCache.get(newKey) : newKey;
+    public void onAddKey(@Nonnull final Key newKey) {
+        final Key key = mUniqueKeysCache.getUniqueKey(newKey);
         final boolean isSpacer = key.isSpacer();
         if (isSpacer && key.getWidth() == 0) {
             // Ignore zero width {@link Spacer}.
@@ -115,6 +136,23 @@
         }
     }
 
+    public void removeRedundantMoreKeys() {
+        if (mAllowRedundantMoreKeys) {
+            return;
+        }
+        final MoreKeySpec.LettersOnBaseLayout lettersOnBaseLayout =
+                new MoreKeySpec.LettersOnBaseLayout();
+        for (final Key key : mSortedKeys) {
+            lettersOnBaseLayout.addLetter(key);
+        }
+        final ArrayList<Key> allKeys = new ArrayList<>(mSortedKeys);
+        mSortedKeys.clear();
+        for (final Key key : allKeys) {
+            final Key filteredKey = Key.removeRedundantMoreKeys(key, lettersOnBaseLayout);
+            mSortedKeys.add(mUniqueKeysCache.getUniqueKey(filteredKey));
+        }
+    }
+
     private int mMaxHeightCount = 0;
     private int mMaxWidthCount = 0;
     private final SparseIntArray mHeightHistogram = new SparseIntArray();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index b98ced9..973e956 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -19,7 +19,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.utils.CapsModeUtils;
 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
 
 /**
@@ -29,7 +31,7 @@
  *
  * The input events are {@link #onLoadKeyboard(int, int)}, {@link #onSaveKeyboardState()},
  * {@link #onPressKey(int,boolean,int,int)}, {@link #onReleaseKey(int,boolean,int,int)},
- * {@link #onCodeInput(int,int,int)}, {@link #onFinishSlidingInput(int,int)},
+ * {@link #onEvent(Event,int,int)}, {@link #onFinishSlidingInput(int,int)},
  * {@link #onUpdateShiftState(int,int)}, {@link #onResetKeyboardStateToAlphabet(int,int)}.
  *
  * The actions are {@link SwitchActions}'s methods.
@@ -37,9 +39,11 @@
 public final class KeyboardState {
     private static final String TAG = KeyboardState.class.getSimpleName();
     private static final boolean DEBUG_EVENT = false;
-    private static final boolean DEBUG_ACTION = false;
+    private static final boolean DEBUG_INTERNAL_ACTION = false;
 
     public interface SwitchActions {
+        public static final boolean DEBUG_ACTION = false;
+
         public void setAlphabetKeyboard();
         public void setAlphabetManualShiftedKeyboard();
         public void setAlphabetAutomaticShiftedKeyboard();
@@ -52,8 +56,9 @@
         /**
          * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}.
          */
-        public void requestUpdatingShiftState(final int currentAutoCapsState,
-                final int currentRecapitalizeState);
+        public void requestUpdatingShiftState(final int autoCapsFlags, final int recapitalizeMode);
+
+        public static final boolean DEBUG_TIMER_ACTION = false;
 
         public void startDoubleTapShiftKeyTimer();
         public boolean isInDoubleTapShiftKeyTimeout();
@@ -101,15 +106,17 @@
 
         @Override
         public String toString() {
-            if (!mIsValid) return "INVALID";
-            if (mIsAlphabetMode) {
-                if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED";
-                return "ALPHABET_" + shiftModeToString(mShiftMode);
-            } else if (mIsEmojiMode) {
-                return "EMOJI";
-            } else {
-                return "SYMBOLS_" + shiftModeToString(mShiftMode);
+            if (!mIsValid) {
+                return "INVALID";
             }
+            if (mIsAlphabetMode) {
+                return mIsAlphabetShiftLocked ? "ALPHABET_SHIFT_LOCKED"
+                        : "ALPHABET_" + shiftModeToString(mShiftMode);
+            }
+            if (mIsEmojiMode) {
+                return "EMOJI";
+            }
+            return "SYMBOLS_" + shiftModeToString(mShiftMode);
         }
     }
 
@@ -118,10 +125,9 @@
         mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
     }
 
-    public void onLoadKeyboard(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    public void onLoadKeyboard(final int autoCapsFlags, final int recapitalizeMode) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onLoadKeyboard: " + this);
+            Log.d(TAG, "onLoadKeyboard: " + stateToString(autoCapsFlags, recapitalizeMode));
         }
         // Reset alphabet shift state.
         mAlphabetShiftState.setShiftLocked(false);
@@ -129,9 +135,16 @@
         mPrevSymbolsKeyboardWasShifted = false;
         mShiftKeyState.onRelease();
         mSymbolKeyState.onRelease();
-        onRestoreKeyboardState(currentAutoCapsState, currentRecapitalizeState);
+        if (mSavedKeyboardState.mIsValid) {
+            onRestoreKeyboardState(autoCapsFlags, recapitalizeMode);
+            mSavedKeyboardState.mIsValid = false;
+        } else {
+            // Reset keyboard to alphabet mode.
+            setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
+        }
     }
 
+    // Constants for {@link SavedKeyboardState#mShiftMode} and {@link #setShifted(int)}.
     private static final int UNSHIFT = 0;
     private static final int MANUAL_SHIFT = 1;
     private static final int AUTOMATIC_SHIFT = 2;
@@ -155,39 +168,35 @@
         }
     }
 
-    private void onRestoreKeyboardState(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    private void onRestoreKeyboardState(final int autoCapsFlags, final int recapitalizeMode) {
         final SavedKeyboardState state = mSavedKeyboardState;
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this);
+            Log.d(TAG, "onRestoreKeyboardState: saved=" + state
+                    + " " + stateToString(autoCapsFlags, recapitalizeMode));
         }
-        if (!state.mIsValid || state.mIsAlphabetMode) {
-            setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState);
-        } else if (state.mIsEmojiMode) {
-            setEmojiKeyboard();
-        } else {
-            if (state.mShiftMode == MANUAL_SHIFT) {
-                setSymbolsShiftedKeyboard();
-            } else {
-                setSymbolsKeyboard();
-            }
-        }
-
-        if (!state.mIsValid) return;
-        state.mIsValid = false;
-
+        mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked;
         if (state.mIsAlphabetMode) {
+            setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
             setShiftLocked(state.mIsAlphabetShiftLocked);
             if (!state.mIsAlphabetShiftLocked) {
                 setShifted(state.mShiftMode);
             }
+            return;
+        }
+        if (state.mIsEmojiMode) {
+            setEmojiKeyboard();
+            return;
+        }
+        // Symbol mode
+        if (state.mShiftMode == MANUAL_SHIFT) {
+            setSymbolsShiftedKeyboard();
         } else {
-            mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked;
+            setSymbolsKeyboard();
         }
     }
 
     private void setShifted(final int shiftMode) {
-        if (DEBUG_ACTION) {
+        if (DEBUG_INTERNAL_ACTION) {
             Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this);
         }
         if (!mIsAlphabetMode) return;
@@ -226,7 +235,7 @@
     }
 
     private void setShiftLocked(final boolean shiftLocked) {
-        if (DEBUG_ACTION) {
+        if (DEBUG_INTERNAL_ACTION) {
             Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this);
         }
         if (!mIsAlphabetMode) return;
@@ -240,10 +249,10 @@
         mAlphabetShiftState.setShiftLocked(shiftLocked);
     }
 
-    private void toggleAlphabetAndSymbols(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
-        if (DEBUG_ACTION) {
-            Log.d(TAG, "toggleAlphabetAndSymbols: " + this);
+    private void toggleAlphabetAndSymbols(final int autoCapsFlags, final int recapitalizeMode) {
+        if (DEBUG_INTERNAL_ACTION) {
+            Log.d(TAG, "toggleAlphabetAndSymbols: "
+                    + stateToString(autoCapsFlags, recapitalizeMode));
         }
         if (mIsAlphabetMode) {
             mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked();
@@ -255,7 +264,7 @@
             mPrevSymbolsKeyboardWasShifted = false;
         } else {
             mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
-            setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState);
+            setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
             if (mPrevMainKeyboardWasShiftLocked) {
                 setShiftLocked(true);
             }
@@ -265,15 +274,15 @@
 
     // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout
     // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal().
-    private void resetKeyboardStateToAlphabet(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
-        if (DEBUG_ACTION) {
-            Log.d(TAG, "resetKeyboardStateToAlphabet: " + this);
+    private void resetKeyboardStateToAlphabet(final int autoCapsFlags, final int recapitalizeMode) {
+        if (DEBUG_INTERNAL_ACTION) {
+            Log.d(TAG, "resetKeyboardStateToAlphabet: "
+                    + stateToString(autoCapsFlags, recapitalizeMode));
         }
         if (mIsAlphabetMode) return;
 
         mPrevSymbolsKeyboardWasShifted = mIsSymbolShifted;
-        setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState);
+        setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
         if (mPrevMainKeyboardWasShiftLocked) {
             setShiftLocked(true);
         }
@@ -288,10 +297,9 @@
         }
     }
 
-    private void setAlphabetKeyboard(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
-        if (DEBUG_ACTION) {
-            Log.d(TAG, "setAlphabetKeyboard");
+    private void setAlphabetKeyboard(final int autoCapsFlags, final int recapitalizeMode) {
+        if (DEBUG_INTERNAL_ACTION) {
+            Log.d(TAG, "setAlphabetKeyboard: " + stateToString(autoCapsFlags, recapitalizeMode));
         }
 
         mSwitchActions.setAlphabetKeyboard();
@@ -300,11 +308,11 @@
         mIsSymbolShifted = false;
         mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
         mSwitchState = SWITCH_STATE_ALPHA;
-        mSwitchActions.requestUpdatingShiftState(currentAutoCapsState, currentRecapitalizeState);
+        mSwitchActions.requestUpdatingShiftState(autoCapsFlags, recapitalizeMode);
     }
 
     private void setSymbolsKeyboard() {
-        if (DEBUG_ACTION) {
+        if (DEBUG_INTERNAL_ACTION) {
             Log.d(TAG, "setSymbolsKeyboard");
         }
         mSwitchActions.setSymbolsKeyboard();
@@ -317,7 +325,7 @@
     }
 
     private void setSymbolsShiftedKeyboard() {
-        if (DEBUG_ACTION) {
+        if (DEBUG_INTERNAL_ACTION) {
             Log.d(TAG, "setSymbolsShiftedKeyboard");
         }
         mSwitchActions.setSymbolsShiftedKeyboard();
@@ -330,7 +338,7 @@
     }
 
     private void setEmojiKeyboard() {
-        if (DEBUG_ACTION) {
+        if (DEBUG_INTERNAL_ACTION) {
             Log.d(TAG, "setEmojiKeyboard");
         }
         mIsAlphabetMode = false;
@@ -342,11 +350,12 @@
         mSwitchActions.setEmojiKeyboard();
     }
 
-    public void onPressKey(final int code, final boolean isSinglePointer,
-            final int currentAutoCapsState, final int currentRecapitalizeState) {
+    public void onPressKey(final int code, final boolean isSinglePointer, final int autoCapsFlags,
+            final int recapitalizeMode) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code) + " single="
-                    + isSinglePointer + " autoCaps=" + currentAutoCapsState + " " + this);
+            Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code)
+                    + " single=" + isSinglePointer
+                    + " " + stateToString(autoCapsFlags, recapitalizeMode));
         }
         if (code != Constants.CODE_SHIFT) {
             // Because the double tap shift key timer is to detect two consecutive shift key press,
@@ -358,7 +367,7 @@
         } else if (code == Constants.CODE_CAPSLOCK) {
             // Nothing to do here. See {@link #onReleaseKey(int,boolean)}.
         } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
-            onPressSymbol(currentAutoCapsState, currentRecapitalizeState);
+            onPressSymbol(autoCapsFlags, recapitalizeMode);
         } else {
             mShiftKeyState.onOtherKeyPressed();
             mSymbolKeyState.onOtherKeyPressed();
@@ -371,7 +380,7 @@
             // off because, for example, we may be in the #1 state within the manual temporary
             // shifted mode.
             if (!isSinglePointer && mIsAlphabetMode
-                    && currentAutoCapsState != TextUtils.CAP_MODE_CHARACTERS) {
+                    && autoCapsFlags != TextUtils.CAP_MODE_CHARACTERS) {
                 final boolean needsToResetAutoCaps = mAlphabetShiftState.isAutomaticShifted()
                         || (mAlphabetShiftState.isManualShifted() && mShiftKeyState.isReleasing());
                 if (needsToResetAutoCaps) {
@@ -381,34 +390,35 @@
         }
     }
 
-    public void onReleaseKey(final int code, final boolean withSliding,
-            final int currentAutoCapsState, final int currentRecapitalizeState) {
+    public void onReleaseKey(final int code, final boolean withSliding, final int autoCapsFlags,
+            final int recapitalizeMode) {
         if (DEBUG_EVENT) {
             Log.d(TAG, "onReleaseKey: code=" + Constants.printableCode(code)
-                    + " sliding=" + withSliding + " " + this);
+                    + " sliding=" + withSliding
+                    + " " + stateToString(autoCapsFlags, recapitalizeMode));
         }
         if (code == Constants.CODE_SHIFT) {
-            onReleaseShift(withSliding, currentAutoCapsState, currentRecapitalizeState);
+            onReleaseShift(withSliding, autoCapsFlags, recapitalizeMode);
         } else if (code == Constants.CODE_CAPSLOCK) {
             setShiftLocked(!mAlphabetShiftState.isShiftLocked());
         } else if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
-            onReleaseSymbol(withSliding, currentAutoCapsState, currentRecapitalizeState);
+            onReleaseSymbol(withSliding, autoCapsFlags, recapitalizeMode);
         }
     }
 
-    private void onPressSymbol(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
-        toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState);
+    private void onPressSymbol(final int autoCapsFlags,
+            final int recapitalizeMode) {
+        toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode);
         mSymbolKeyState.onPress();
         mSwitchState = SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL;
     }
 
-    private void onReleaseSymbol(final boolean withSliding, final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    private void onReleaseSymbol(final boolean withSliding, final int autoCapsFlags,
+            final int recapitalizeMode) {
         if (mSymbolKeyState.isChording()) {
             // Switch back to the previous keyboard mode if the user chords the mode change key and
             // another key, then releases the mode change key.
-            toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState);
+            toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode);
         } else if (!withSliding) {
             // If the mode change key is being released without sliding, we should forget the
             // previous symbols keyboard shift state and simply switch back to symbols layout
@@ -418,23 +428,23 @@
         mSymbolKeyState.onRelease();
     }
 
-    public void onUpdateShiftState(final int autoCaps, final int recapitalizeMode) {
+    public void onUpdateShiftState(final int autoCapsFlags, final int recapitalizeMode) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + ", recapitalizeMode="
-                    + recapitalizeMode + " " + this);
+            Log.d(TAG, "onUpdateShiftState: " + stateToString(autoCapsFlags, recapitalizeMode));
         }
         mRecapitalizeMode = recapitalizeMode;
-        updateAlphabetShiftState(autoCaps, recapitalizeMode);
+        updateAlphabetShiftState(autoCapsFlags, recapitalizeMode);
     }
 
     // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout
     // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal().
-    public void onResetKeyboardStateToAlphabet(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    public void onResetKeyboardStateToAlphabet(final int autoCapsFlags,
+            final int recapitalizeMode) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onResetKeyboardStateToAlphabet: " + this);
+            Log.d(TAG, "onResetKeyboardStateToAlphabet: "
+                    + stateToString(autoCapsFlags, recapitalizeMode));
         }
-        resetKeyboardStateToAlphabet(currentAutoCapsState, currentRecapitalizeState);
+        resetKeyboardStateToAlphabet(autoCapsFlags, recapitalizeMode);
     }
 
     private void updateShiftStateForRecapitalize(final int recapitalizeMode) {
@@ -452,7 +462,7 @@
         }
     }
 
-    private void updateAlphabetShiftState(final int autoCaps, final int recapitalizeMode) {
+    private void updateAlphabetShiftState(final int autoCapsFlags, final int recapitalizeMode) {
         if (!mIsAlphabetMode) return;
         if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != recapitalizeMode) {
             // We are recapitalizing. Match the keyboard to the current recapitalize state.
@@ -465,7 +475,7 @@
             return;
         }
         if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
-            if (mShiftKeyState.isReleasing() && autoCaps != Constants.TextUtils.CAP_MODE_OFF) {
+            if (mShiftKeyState.isReleasing() && autoCapsFlags != Constants.TextUtils.CAP_MODE_OFF) {
                 // Only when shift key is releasing, automatic temporary upper case will be set.
                 setShifted(AUTOMATIC_SHIFT);
             } else {
@@ -525,8 +535,8 @@
         }
     }
 
-    private void onReleaseShift(final boolean withSliding, final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    private void onReleaseShift(final boolean withSliding, final int autoCapsFlags,
+            final int recapitalizeMode) {
         if (RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE != mRecapitalizeMode) {
             // We are recapitalizing. We should match the keyboard state to the recapitalize
             // state in priority.
@@ -549,8 +559,7 @@
                 // After chording input, automatic shift state may have been changed depending on
                 // what characters were input.
                 mShiftKeyState.onRelease();
-                mSwitchActions.requestUpdatingShiftState(currentAutoCapsState,
-                        currentRecapitalizeState);
+                mSwitchActions.requestUpdatingShiftState(autoCapsFlags, recapitalizeMode);
                 return;
             } else if (mAlphabetShiftState.isShiftLockShifted() && withSliding) {
                 // In shift locked state, shift has been pressed and slid out to other key.
@@ -587,21 +596,20 @@
         mShiftKeyState.onRelease();
     }
 
-    public void onFinishSlidingInput(final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    public void onFinishSlidingInput(final int autoCapsFlags, final int recapitalizeMode) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onFinishSlidingInput: " + this);
+            Log.d(TAG, "onFinishSlidingInput: " + stateToString(autoCapsFlags, recapitalizeMode));
         }
         // Switch back to the previous keyboard mode if the user cancels sliding input.
         switch (mSwitchState) {
         case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL:
-            toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState);
+            toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode);
             break;
         case SWITCH_STATE_MOMENTARY_SYMBOL_AND_MORE:
             toggleShiftInSymbols();
             break;
         case SWITCH_STATE_MOMENTARY_ALPHA_SHIFT:
-            setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState);
+            setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
             break;
         }
     }
@@ -610,11 +618,11 @@
         return c == Constants.CODE_SPACE || c == Constants.CODE_ENTER;
     }
 
-    public void onCodeInput(final int code, final int currentAutoCapsState,
-            final int currentRecapitalizeState) {
+    public void onEvent(final Event event, final int autoCapsFlags, final int recapitalizeMode) {
+        final int code = event.isFunctionalKeyEvent() ? event.mKeyCode : event.mCodePoint;
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onCodeInput: code=" + Constants.printableCode(code)
-                    + " autoCaps=" + currentAutoCapsState + " " + this);
+            Log.d(TAG, "onEvent: code=" + Constants.printableCode(code)
+                    + " " + stateToString(autoCapsFlags, recapitalizeMode));
         }
 
         switch (mSwitchState) {
@@ -650,7 +658,7 @@
             // Switch back to alpha keyboard mode if user types one or more non-space/enter
             // characters followed by a space/enter.
             if (isSpaceOrEnter(code)) {
-                toggleAlphabetAndSymbols(currentAutoCapsState, currentRecapitalizeState);
+                toggleAlphabetAndSymbols(autoCapsFlags, recapitalizeMode);
                 mPrevSymbolsKeyboardWasShifted = false;
             }
             break;
@@ -658,11 +666,11 @@
 
         // If the code is a letter, update keyboard shift state.
         if (Constants.isLetterCode(code)) {
-            updateAlphabetShiftState(currentAutoCapsState, currentRecapitalizeState);
+            updateAlphabetShiftState(autoCapsFlags, recapitalizeMode);
         } else if (code == Constants.CODE_EMOJI) {
             setEmojiKeyboard();
         } else if (code == Constants.CODE_ALPHA_FROM_EMOJI) {
-            setAlphabetKeyboard(currentAutoCapsState, currentRecapitalizeState);
+            setAlphabetKeyboard(autoCapsFlags, recapitalizeMode);
         }
     }
 
@@ -695,4 +703,9 @@
                 + " symbol=" + mSymbolKeyState
                 + " switch=" + switchStateToString(mSwitchState) + "]";
     }
+
+    private String stateToString(final int autoCapsFlags, final int recapitalizeMode) {
+        return this + " autoCapsFlags=" + CapsModeUtils.flagsToString(autoCapsFlags)
+                + " recapitalizeMode=" + RecapitalizeStatus.modeToString(recapitalizeMode);
+    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index cd6abee..0aaf6b4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -21,53 +21,46 @@
 import android.text.TextUtils;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.RunInLocale;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
-import java.util.HashMap;
 import java.util.Locale;
 
+// TODO: Make this an immutable class.
 public final class KeyboardTextsSet {
     public static final String PREFIX_TEXT = "!text/";
+    private static final String PREFIX_RESOURCE = "!string/";
     public static final String SWITCH_TO_ALPHA_KEY_LABEL = "keylabel_to_alpha";
 
     private static final char BACKSLASH = Constants.CODE_BACKSLASH;
-    private static final int MAX_STRING_REFERENCE_INDIRECTION = 10;
+    private static final int MAX_REFERENCE_INDIRECTION = 10;
 
+    private Resources mResources;
+    private Locale mResourceLocale;
+    private String mResourcePackageName;
     private String[] mTextsTable;
-    // Resource name to text map.
-    private HashMap<String, String> mResourceNameToTextsMap = new HashMap<>();
 
     public void setLocale(final Locale locale, final Context context) {
-        mTextsTable = KeyboardTextsTable.getTextsTable(locale);
         final Resources res = context.getResources();
-        final int referenceId = context.getApplicationInfo().labelRes;
-        final String resourcePackageName = res.getResourcePackageName(referenceId);
-        final RunInLocale<Void> job = new RunInLocale<Void>() {
-            @Override
-            protected Void job(final Resources resource) {
-                loadStringResourcesInternal(res, RESOURCE_NAMES, resourcePackageName);
-                return null;
-            }
-        };
         // Null means the current system locale.
-        job.runInLocale(res,
-                SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale);
+        final String resourcePackageName = res.getResourcePackageName(
+                context.getApplicationInfo().labelRes);
+        setLocale(locale, res, resourcePackageName);
     }
 
     @UsedForTesting
-    void loadStringResourcesInternal(final Resources res, final String[] resourceNames,
+    public void setLocale(final Locale locale, final Resources res,
             final String resourcePackageName) {
-        for (final String resName : resourceNames) {
-            final int resId = res.getIdentifier(resName, "string", resourcePackageName);
-            mResourceNameToTextsMap.put(resName, res.getString(resId));
-        }
+        mResources = res;
+        // Null means the current system locale.
+        mResourceLocale = SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale;
+        mResourcePackageName = resourcePackageName;
+        mTextsTable = KeyboardTextsTable.getTextsTable(locale);
     }
 
     public String getText(final String name) {
-        final String text = mResourceNameToTextsMap.get(name);
-        return (text != null) ? text : KeyboardTextsTable.getText(name, mTextsTable);
+        return KeyboardTextsTable.getText(name, mTextsTable);
     }
 
     private static int searchTextNameEnd(final String text, final int start) {
@@ -93,13 +86,14 @@
         StringBuilder sb;
         do {
             level++;
-            if (level >= MAX_STRING_REFERENCE_INDIRECTION) {
-                throw new RuntimeException("Too many " + PREFIX_TEXT + "name indirection: " + text);
+            if (level >= MAX_REFERENCE_INDIRECTION) {
+                throw new RuntimeException("Too many " + PREFIX_TEXT + " or " + PREFIX_RESOURCE +
+                        " reference indirection: " + text);
             }
 
-            final int prefixLen = PREFIX_TEXT.length();
+            final int prefixLength = PREFIX_TEXT.length();
             final int size = text.length();
-            if (size < prefixLen) {
+            if (size < prefixLength) {
                 break;
             }
 
@@ -110,10 +104,12 @@
                     if (sb == null) {
                         sb = new StringBuilder(text.substring(0, pos));
                     }
-                    final int end = searchTextNameEnd(text, pos + prefixLen);
-                    final String name = text.substring(pos + prefixLen, end);
-                    sb.append(getText(name));
-                    pos = end - 1;
+                    pos = expandReference(text, pos, PREFIX_TEXT, sb);
+                } else if (text.startsWith(PREFIX_RESOURCE, pos)) {
+                    if (sb == null) {
+                        sb = new StringBuilder(text.substring(0, pos));
+                    }
+                    pos = expandReference(text, pos, PREFIX_RESOURCE, sb);
                 } else if (c == BACKSLASH) {
                     if (sb != null) {
                         // Append both escape character and escaped character.
@@ -132,18 +128,24 @@
         return TextUtils.isEmpty(text) ? null : text;
     }
 
-    // These texts' name should be aligned with the @string/<name> in
-    // values*/strings-action-keys.xml.
-    static final String[] RESOURCE_NAMES = {
-        // Labels for action.
-        "label_go_key",
-        "label_send_key",
-        "label_next_key",
-        "label_done_key",
-        "label_search_key",
-        "label_previous_key",
-        // Other labels.
-        "label_pause_key",
-        "label_wait_key",
-    };
+    private int expandReference(final String text, final int pos, final String prefix,
+            final StringBuilder sb) {
+        final int prefixLength = prefix.length();
+        final int end = searchTextNameEnd(text, pos + prefixLength);
+        final String name = text.substring(pos + prefixLength, end);
+        if (prefix.equals(PREFIX_TEXT)) {
+            sb.append(getText(name));
+        } else { // PREFIX_RESOURCE
+            final String resourcePackageName = mResourcePackageName;
+            final RunInLocale<String> getTextJob = new RunInLocale<String>() {
+                @Override
+                protected String job(final Resources res) {
+                    final int resId = res.getIdentifier(name, "string", resourcePackageName);
+                    return res.getString(resId);
+                }
+            };
+            sb.append(getTextJob.runInLocale(mResources, mResourceLocale));
+        }
+        return end - 1;
+    }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
index 31bc549..b50c0a8 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsTable.java
@@ -83,24 +83,24 @@
 
     private static final String[] NAMES = {
     //  /* index:histogram */ "name",
-        /*   0:32 */ "morekeys_a",
-        /*   1:32 */ "morekeys_o",
-        /*   2:30 */ "morekeys_u",
-        /*   3:30 */ "keylabel_to_alpha",
-        /*   4:29 */ "morekeys_e",
-        /*   5:28 */ "morekeys_i",
-        /*   6:23 */ "morekeys_c",
-        /*   7:23 */ "double_quotes",
-        /*   8:22 */ "morekeys_n",
-        /*   9:22 */ "single_quotes",
-        /*  10:20 */ "morekeys_s",
-        /*  11:17 */ "keyspec_currency",
-        /*  12:14 */ "morekeys_y",
-        /*  13:13 */ "morekeys_d",
-        /*  14:12 */ "morekeys_z",
+        /*   0:33 */ "morekeys_a",
+        /*   1:33 */ "morekeys_o",
+        /*   2:32 */ "morekeys_e",
+        /*   3:31 */ "morekeys_u",
+        /*   4:31 */ "keylabel_to_alpha",
+        /*   5:30 */ "morekeys_i",
+        /*   6:25 */ "morekeys_n",
+        /*   7:25 */ "morekeys_c",
+        /*   8:23 */ "double_quotes",
+        /*   9:22 */ "morekeys_s",
+        /*  10:22 */ "single_quotes",
+        /*  11:19 */ "keyspec_currency",
+        /*  12:17 */ "morekeys_y",
+        /*  13:16 */ "morekeys_z",
+        /*  14:14 */ "morekeys_d",
         /*  15:10 */ "morekeys_t",
         /*  16:10 */ "morekeys_l",
-        /*  17: 9 */ "morekeys_g",
+        /*  17:10 */ "morekeys_g",
         /*  18: 9 */ "single_angle_quotes",
         /*  19: 9 */ "double_angle_quotes",
         /*  20: 8 */ "morekeys_r",
@@ -136,121 +136,129 @@
         /*  50: 5 */ "additional_morekeys_symbols_8",
         /*  51: 5 */ "additional_morekeys_symbols_9",
         /*  52: 5 */ "additional_morekeys_symbols_0",
-        /*  53: 4 */ "morekeys_nordic_row2_11",
-        /*  54: 4 */ "morekeys_punctuation",
-        /*  55: 4 */ "keyspec_tablet_comma",
-        /*  56: 3 */ "keyspec_swiss_row1_11",
-        /*  57: 3 */ "keyspec_swiss_row2_10",
-        /*  58: 3 */ "keyspec_swiss_row2_11",
-        /*  59: 3 */ "morekeys_swiss_row1_11",
-        /*  60: 3 */ "morekeys_swiss_row2_10",
-        /*  61: 3 */ "morekeys_swiss_row2_11",
-        /*  62: 3 */ "morekeys_star",
-        /*  63: 3 */ "keyspec_left_parenthesis",
-        /*  64: 3 */ "keyspec_right_parenthesis",
-        /*  65: 3 */ "keyspec_left_square_bracket",
-        /*  66: 3 */ "keyspec_right_square_bracket",
-        /*  67: 3 */ "keyspec_left_curly_bracket",
-        /*  68: 3 */ "keyspec_right_curly_bracket",
-        /*  69: 3 */ "keyspec_less_than",
-        /*  70: 3 */ "keyspec_greater_than",
-        /*  71: 3 */ "keyspec_less_than_equal",
-        /*  72: 3 */ "keyspec_greater_than_equal",
-        /*  73: 3 */ "keyspec_left_double_angle_quote",
-        /*  74: 3 */ "keyspec_right_double_angle_quote",
-        /*  75: 3 */ "keyspec_left_single_angle_quote",
-        /*  76: 3 */ "keyspec_right_single_angle_quote",
-        /*  77: 3 */ "keyspec_comma",
-        /*  78: 3 */ "morekeys_tablet_comma",
-        /*  79: 3 */ "keyhintlabel_period",
-        /*  80: 3 */ "morekeys_tablet_period",
-        /*  81: 3 */ "morekeys_question",
-        /*  82: 2 */ "morekeys_h",
-        /*  83: 2 */ "morekeys_w",
-        /*  84: 2 */ "morekeys_east_slavic_row2_2",
-        /*  85: 2 */ "morekeys_cyrillic_u",
-        /*  86: 2 */ "morekeys_cyrillic_en",
-        /*  87: 2 */ "morekeys_cyrillic_ghe",
-        /*  88: 2 */ "morekeys_cyrillic_o",
-        /*  89: 2 */ "morekeys_cyrillic_i",
-        /*  90: 2 */ "keyspec_south_slavic_row1_6",
-        /*  91: 2 */ "keyspec_south_slavic_row2_11",
-        /*  92: 2 */ "keyspec_south_slavic_row3_1",
-        /*  93: 2 */ "keyspec_south_slavic_row3_8",
-        /*  94: 2 */ "morekeys_tablet_punctuation",
-        /*  95: 2 */ "keyspec_spanish_row2_10",
-        /*  96: 2 */ "morekeys_bullet",
-        /*  97: 2 */ "morekeys_left_parenthesis",
-        /*  98: 2 */ "morekeys_right_parenthesis",
-        /*  99: 2 */ "morekeys_arabic_diacritics",
-        /* 100: 2 */ "keyhintlabel_tablet_comma",
-        /* 101: 2 */ "keyspec_period",
-        /* 102: 2 */ "morekeys_period",
-        /* 103: 2 */ "keyspec_tablet_period",
+        /*  53: 5 */ "morekeys_tablet_period",
+        /*  54: 4 */ "morekeys_nordic_row2_11",
+        /*  55: 4 */ "morekeys_punctuation",
+        /*  56: 4 */ "keyspec_tablet_comma",
+        /*  57: 4 */ "keyspec_period",
+        /*  58: 4 */ "morekeys_period",
+        /*  59: 4 */ "keyspec_tablet_period",
+        /*  60: 3 */ "keyspec_swiss_row1_11",
+        /*  61: 3 */ "keyspec_swiss_row2_10",
+        /*  62: 3 */ "keyspec_swiss_row2_11",
+        /*  63: 3 */ "morekeys_swiss_row1_11",
+        /*  64: 3 */ "morekeys_swiss_row2_10",
+        /*  65: 3 */ "morekeys_swiss_row2_11",
+        /*  66: 3 */ "morekeys_star",
+        /*  67: 3 */ "keyspec_left_parenthesis",
+        /*  68: 3 */ "keyspec_right_parenthesis",
+        /*  69: 3 */ "keyspec_left_square_bracket",
+        /*  70: 3 */ "keyspec_right_square_bracket",
+        /*  71: 3 */ "keyspec_left_curly_bracket",
+        /*  72: 3 */ "keyspec_right_curly_bracket",
+        /*  73: 3 */ "keyspec_less_than",
+        /*  74: 3 */ "keyspec_greater_than",
+        /*  75: 3 */ "keyspec_less_than_equal",
+        /*  76: 3 */ "keyspec_greater_than_equal",
+        /*  77: 3 */ "keyspec_left_double_angle_quote",
+        /*  78: 3 */ "keyspec_right_double_angle_quote",
+        /*  79: 3 */ "keyspec_left_single_angle_quote",
+        /*  80: 3 */ "keyspec_right_single_angle_quote",
+        /*  81: 3 */ "keyspec_comma",
+        /*  82: 3 */ "morekeys_tablet_comma",
+        /*  83: 3 */ "keyhintlabel_period",
+        /*  84: 3 */ "morekeys_question",
+        /*  85: 2 */ "morekeys_h",
+        /*  86: 2 */ "morekeys_w",
+        /*  87: 2 */ "morekeys_east_slavic_row2_2",
+        /*  88: 2 */ "morekeys_cyrillic_u",
+        /*  89: 2 */ "morekeys_cyrillic_en",
+        /*  90: 2 */ "morekeys_cyrillic_ghe",
+        /*  91: 2 */ "morekeys_cyrillic_o",
+        /*  92: 2 */ "morekeys_cyrillic_i",
+        /*  93: 2 */ "keyspec_south_slavic_row1_6",
+        /*  94: 2 */ "keyspec_south_slavic_row2_11",
+        /*  95: 2 */ "keyspec_south_slavic_row3_1",
+        /*  96: 2 */ "keyspec_south_slavic_row3_8",
+        /*  97: 2 */ "morekeys_tablet_punctuation",
+        /*  98: 2 */ "keyspec_spanish_row2_10",
+        /*  99: 2 */ "morekeys_bullet",
+        /* 100: 2 */ "morekeys_left_parenthesis",
+        /* 101: 2 */ "morekeys_right_parenthesis",
+        /* 102: 2 */ "morekeys_arabic_diacritics",
+        /* 103: 2 */ "keyhintlabel_tablet_comma",
         /* 104: 2 */ "keyhintlabel_tablet_period",
         /* 105: 2 */ "keyspec_symbols_question",
         /* 106: 2 */ "keyspec_symbols_semicolon",
         /* 107: 2 */ "keyspec_symbols_percent",
         /* 108: 2 */ "morekeys_symbols_semicolon",
         /* 109: 2 */ "morekeys_symbols_percent",
-        /* 110: 1 */ "morekeys_v",
-        /* 111: 1 */ "morekeys_j",
-        /* 112: 1 */ "morekeys_q",
-        /* 113: 1 */ "morekeys_x",
-        /* 114: 1 */ "keyspec_q",
-        /* 115: 1 */ "keyspec_w",
-        /* 116: 1 */ "keyspec_y",
-        /* 117: 1 */ "keyspec_x",
-        /* 118: 1 */ "morekeys_east_slavic_row2_11",
-        /* 119: 1 */ "morekeys_cyrillic_ka",
-        /* 120: 1 */ "morekeys_cyrillic_a",
-        /* 121: 1 */ "morekeys_currency_dollar",
-        /* 122: 1 */ "morekeys_plus",
-        /* 123: 1 */ "morekeys_less_than",
-        /* 124: 1 */ "morekeys_greater_than",
-        /* 125: 1 */ "morekeys_exclamation",
-        /* 126: 0 */ "morekeys_currency_generic",
-        /* 127: 0 */ "morekeys_symbols_1",
-        /* 128: 0 */ "morekeys_symbols_2",
-        /* 129: 0 */ "morekeys_symbols_3",
-        /* 130: 0 */ "morekeys_symbols_4",
-        /* 131: 0 */ "morekeys_symbols_5",
-        /* 132: 0 */ "morekeys_symbols_6",
-        /* 133: 0 */ "morekeys_symbols_7",
-        /* 134: 0 */ "morekeys_symbols_8",
-        /* 135: 0 */ "morekeys_symbols_9",
-        /* 136: 0 */ "morekeys_symbols_0",
-        /* 137: 0 */ "morekeys_am_pm",
-        /* 138: 0 */ "keyspec_settings",
-        /* 139: 0 */ "keyspec_shortcut",
-        /* 140: 0 */ "keyspec_action_next",
-        /* 141: 0 */ "keyspec_action_previous",
-        /* 142: 0 */ "keylabel_to_more_symbol",
-        /* 143: 0 */ "keylabel_tablet_to_more_symbol",
-        /* 144: 0 */ "keylabel_to_phone_numeric",
-        /* 145: 0 */ "keylabel_to_phone_symbols",
-        /* 146: 0 */ "keylabel_time_am",
-        /* 147: 0 */ "keylabel_time_pm",
-        /* 148: 0 */ "keyspec_popular_domain",
-        /* 149: 0 */ "morekeys_popular_domain",
-        /* 150: 0 */ "keyspecs_left_parenthesis_more_keys",
-        /* 151: 0 */ "keyspecs_right_parenthesis_more_keys",
-        /* 152: 0 */ "single_laqm_raqm",
-        /* 153: 0 */ "single_raqm_laqm",
-        /* 154: 0 */ "double_laqm_raqm",
-        /* 155: 0 */ "double_raqm_laqm",
-        /* 156: 0 */ "single_lqm_rqm",
-        /* 157: 0 */ "single_9qm_lqm",
-        /* 158: 0 */ "single_9qm_rqm",
-        /* 159: 0 */ "single_rqm_9qm",
-        /* 160: 0 */ "double_lqm_rqm",
-        /* 161: 0 */ "double_9qm_lqm",
-        /* 162: 0 */ "double_9qm_rqm",
-        /* 163: 0 */ "double_rqm_9qm",
-        /* 164: 0 */ "morekeys_single_quote",
-        /* 165: 0 */ "morekeys_double_quote",
-        /* 166: 0 */ "morekeys_tablet_double_quote",
-        /* 167: 0 */ "keyspec_emoji_action_key",
+        /* 110: 2 */ "label_go_key",
+        /* 111: 2 */ "label_send_key",
+        /* 112: 2 */ "label_next_key",
+        /* 113: 2 */ "label_done_key",
+        /* 114: 2 */ "label_search_key",
+        /* 115: 2 */ "label_previous_key",
+        /* 116: 2 */ "label_pause_key",
+        /* 117: 2 */ "label_wait_key",
+        /* 118: 1 */ "morekeys_v",
+        /* 119: 1 */ "morekeys_j",
+        /* 120: 1 */ "morekeys_q",
+        /* 121: 1 */ "morekeys_x",
+        /* 122: 1 */ "keyspec_q",
+        /* 123: 1 */ "keyspec_w",
+        /* 124: 1 */ "keyspec_y",
+        /* 125: 1 */ "keyspec_x",
+        /* 126: 1 */ "morekeys_east_slavic_row2_11",
+        /* 127: 1 */ "morekeys_cyrillic_ka",
+        /* 128: 1 */ "morekeys_cyrillic_a",
+        /* 129: 1 */ "morekeys_currency_dollar",
+        /* 130: 1 */ "morekeys_plus",
+        /* 131: 1 */ "morekeys_less_than",
+        /* 132: 1 */ "morekeys_greater_than",
+        /* 133: 1 */ "morekeys_exclamation",
+        /* 134: 0 */ "morekeys_currency_generic",
+        /* 135: 0 */ "morekeys_symbols_1",
+        /* 136: 0 */ "morekeys_symbols_2",
+        /* 137: 0 */ "morekeys_symbols_3",
+        /* 138: 0 */ "morekeys_symbols_4",
+        /* 139: 0 */ "morekeys_symbols_5",
+        /* 140: 0 */ "morekeys_symbols_6",
+        /* 141: 0 */ "morekeys_symbols_7",
+        /* 142: 0 */ "morekeys_symbols_8",
+        /* 143: 0 */ "morekeys_symbols_9",
+        /* 144: 0 */ "morekeys_symbols_0",
+        /* 145: 0 */ "morekeys_am_pm",
+        /* 146: 0 */ "keyspec_settings",
+        /* 147: 0 */ "keyspec_shortcut",
+        /* 148: 0 */ "keyspec_action_next",
+        /* 149: 0 */ "keyspec_action_previous",
+        /* 150: 0 */ "keylabel_to_more_symbol",
+        /* 151: 0 */ "keylabel_tablet_to_more_symbol",
+        /* 152: 0 */ "keylabel_to_phone_numeric",
+        /* 153: 0 */ "keylabel_to_phone_symbols",
+        /* 154: 0 */ "keylabel_time_am",
+        /* 155: 0 */ "keylabel_time_pm",
+        /* 156: 0 */ "keyspec_popular_domain",
+        /* 157: 0 */ "morekeys_popular_domain",
+        /* 158: 0 */ "keyspecs_left_parenthesis_more_keys",
+        /* 159: 0 */ "keyspecs_right_parenthesis_more_keys",
+        /* 160: 0 */ "single_laqm_raqm",
+        /* 161: 0 */ "single_raqm_laqm",
+        /* 162: 0 */ "double_laqm_raqm",
+        /* 163: 0 */ "double_raqm_laqm",
+        /* 164: 0 */ "single_lqm_rqm",
+        /* 165: 0 */ "single_9qm_lqm",
+        /* 166: 0 */ "single_9qm_rqm",
+        /* 167: 0 */ "single_rqm_9qm",
+        /* 168: 0 */ "double_lqm_rqm",
+        /* 169: 0 */ "double_9qm_lqm",
+        /* 170: 0 */ "double_9qm_rqm",
+        /* 171: 0 */ "double_rqm_9qm",
+        /* 172: 0 */ "morekeys_single_quote",
+        /* 173: 0 */ "morekeys_double_quote",
+        /* 174: 0 */ "morekeys_tablet_double_quote",
+        /* 175: 0 */ "keyspec_emoji_action_key",
     };
 
     private static final String EMPTY = "";
@@ -258,17 +266,16 @@
     /* Default texts */
     private static final String[] TEXTS_DEFAULT = {
         /* morekeys_a ~ */
-        EMPTY, EMPTY, EMPTY,
+        EMPTY, EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         /* keylabel_to_alpha */ "ABC",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_lqm_rqm",
-        /* morekeys_n */ EMPTY,
-        /* single_quotes */ "!text/single_lqm_rqm",
         /* morekeys_s */ EMPTY,
+        /* single_quotes */ "!text/single_lqm_rqm",
         /* keyspec_currency */ "$",
         /* morekeys_y ~ */
         EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
@@ -291,10 +298,16 @@
         // Label for "switch to symbols" key.
         /* keylabel_to_symbol */ "?123",
         /* additional_morekeys_symbols_1 ~ */
-        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
-        /* ~ morekeys_nordic_row2_11 */
+        EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
+        /* ~ additional_morekeys_symbols_0 */
+        /* morekeys_tablet_period */ "!text/morekeys_tablet_punctuation",
+        /* morekeys_nordic_row2_11 */ EMPTY,
         /* morekeys_punctuation */ "!autoColumnOrder!8,\\,,?,!,#,!text/keyspec_right_parenthesis,!text/keyspec_left_parenthesis,/,;,',@,:,-,\",+,\\%,&",
         /* keyspec_tablet_comma */ ",",
+        // Period key
+        /* keyspec_period */ ".",
+        /* morekeys_period */ "!text/morekeys_punctuation",
+        /* keyspec_tablet_period */ ".",
         /* keyspec_swiss_row1_11 ~ */
         EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_swiss_row2_11 */
@@ -328,7 +341,6 @@
         /* keyspec_comma */ ",",
         /* morekeys_tablet_comma */ EMPTY,
         /* keyhintlabel_period */ EMPTY,
-        /* morekeys_tablet_period */ "!text/morekeys_tablet_punctuation",
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "\u00BF",
         /* morekeys_h ~ */
@@ -345,19 +357,23 @@
         /* morekeys_bullet */ "\u266A,\u2665,\u2660,\u2666,\u2663",
         /* morekeys_left_parenthesis */ "!fixedColumnOrder!3,!text/keyspecs_left_parenthesis_more_keys",
         /* morekeys_right_parenthesis */ "!fixedColumnOrder!3,!text/keyspecs_right_parenthesis_more_keys",
-        /* morekeys_arabic_diacritics */ EMPTY,
-        /* keyhintlabel_tablet_comma */ EMPTY,
-        // Period key
-        /* keyspec_period */ ".",
-        /* morekeys_period */ "!text/morekeys_punctuation",
-        /* keyspec_tablet_period */ ".",
-        /* keyhintlabel_tablet_period */ EMPTY,
+        /* morekeys_arabic_diacritics ~ */
+        EMPTY, EMPTY, EMPTY,
+        /* ~ keyhintlabel_tablet_period */
         /* keyspec_symbols_question */ "?",
         /* keyspec_symbols_semicolon */ ";",
         /* keyspec_symbols_percent */ "%",
         /* morekeys_symbols_semicolon */ EMPTY,
         // U+2030: "‰" PER MILLE SIGN
         /* morekeys_symbols_percent */ "\u2030",
+        /* label_go_key */ "!string/label_go_key",
+        /* label_send_key */ "!string/label_send_key",
+        /* label_next_key */ "!string/label_next_key",
+        /* label_done_key */ "!string/label_done_key",
+        /* label_search_key */ "!string/label_search_key",
+        /* label_previous_key */ "!string/label_previous_key",
+        /* label_pause_key */ "!string/label_pause_key",
+        /* label_wait_key */ "!string/label_wait_key",
         /* morekeys_v ~ */
         EMPTY, EMPTY, EMPTY, EMPTY,
         /* ~ morekeys_x */
@@ -488,13 +504,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F4,\u00F6,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -503,6 +512,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -511,13 +527,11 @@
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_i */ "\u00ED,\u00EC,\u00EF,\u00EE,\u012F,\u012B,\u0133",
-        /* morekeys_c */ null,
-        /* double_quotes */ null,
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes ~ */
-        null, null, null,
+        /* morekeys_c ~ */
+        null, null, null, null, null,
         /* ~ keyspec_currency */
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
@@ -527,7 +541,7 @@
     /* Locale ar: Arabic */
     private static final String[] TEXTS_ar = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0623: "أ" ARABIC LETTER ALEF WITH HAMZA ABOVE
@@ -535,9 +549,9 @@
         // U+0628: "ب" ARABIC LETTER BEH
         // U+062C: "ج" ARABIC LETTER JEEM
         /* keylabel_to_alpha */ "\u0623\u200C\u0628\u200C\u062C",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         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, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_soft_sign */
         // U+0661: "١" ARABIC-INDIC DIGIT ONE
         /* keyspec_symbols_1 */ "\u0661",
@@ -574,14 +588,17 @@
         // U+066B: "٫" ARABIC DECIMAL SEPARATOR
         // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
         /* additional_morekeys_symbols_0 */ "0,\u066B,\u066C",
+        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         /* morekeys_nordic_row2_11 */ null,
         /* morekeys_punctuation */ null,
         // U+061F: "؟" ARABIC QUESTION MARK
         // U+060C: "،" ARABIC COMMA
         // U+061B: "؛" ARABIC SEMICOLON
         /* keyspec_tablet_comma */ "\u060C",
-        /* keyspec_swiss_row1_11 ~ */
-        null, null, null, null, null, null,
+        /* keyspec_period */ null,
+        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
+        /* keyspec_tablet_period ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_swiss_row2_11 */
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
@@ -611,7 +628,6 @@
         /* morekeys_tablet_comma */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,\",\'",
         // U+0651: "ّ" ARABIC SHADDA
         /* keyhintlabel_period */ "\u0651",
-        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
@@ -643,9 +659,6 @@
         // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
         /* morekeys_arabic_diacritics */ "!fixedColumnOrder!7, \u0655|\u0655, \u0654|\u0654, \u0652|\u0652, \u064D|\u064D, \u064C|\u064C, \u064B|\u064B, \u0651|\u0651, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u0650|\u0650, \u064F|\u064F, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
         /* keyhintlabel_tablet_comma */ "\u061F",
-        /* keyspec_period */ null,
-        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
-        /* keyspec_tablet_period */ null,
         /* keyhintlabel_tablet_period */ "\u0651",
         /* keyspec_symbols_question */ "\u061F",
         /* keyspec_symbols_semicolon */ "\u061B",
@@ -658,8 +671,11 @@
 
     /* Locale az_AZ: Azerbaijani (Azerbaijan) */
     private static final String[] TEXTS_az_AZ = {
+        // This is the same as Turkish
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-        /* morekeys_a */ "\u00E2",
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+        /* morekeys_a */ "\u00E2,\u00E4,\u00E1",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+0153: "œ" LATIN SMALL LIGATURE OE
@@ -669,6 +685,9 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D",
+        // U+0259: "ə" LATIN SMALL LETTER SCHWA
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        /* morekeys_e */ "\u0259,\u00E9",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -676,8 +695,6 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+0259: "ə" LATIN SMALL LETTER SCHWA
-        /* morekeys_e */ "\u0259",
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -686,20 +703,27 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u0148,\u00F1",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes ~ */
-        null, null, null,
-        /* ~ single_quotes */
+        /* double_quotes */ null,
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
-        /* keyspec_currency ~ */
-        null, null, null, null, null, null,
+        /* single_quotes */ null,
+        /* keyspec_currency */ null,
+        // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+        /* morekeys_y */ "\u00FD",
+        // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+        /* morekeys_z */ "\u017E",
+        /* morekeys_d ~ */
+        null, null, null,
         /* ~ morekeys_l */
         // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
         /* morekeys_g */ "\u011F",
@@ -708,21 +732,21 @@
     /* Locale be_BY: Belarusian (Belarus) */
     private static final String[] TEXTS_be_BY = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -744,33 +768,50 @@
     /* Locale bg: Bulgarian */
     private static final String[] TEXTS_bg = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         // single_quotes of Bulgarian is default single_quotes_right_left.
         /* double_quotes */ "!text/double_9qm_lqm",
     };
 
-    /* Locale bn_IN: Bengali (India) */
-    private static final String[] TEXTS_bn_IN = {
+    /* Locale bn_BD: Bengali (Bangladesh) */
+    private static final String[] TEXTS_bn_BD = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0995: "क" BENGALI LETTER KA
         // U+0996: "ख" BENGALI LETTER KHA
         // U+0997: "ग" BENGALI LETTER GA
         /* keylabel_to_alpha */ "\u0995\u0996\u0997",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
+        // U+09F3: "৳" BENGALI RUPEE SIGN
+        /* keyspec_currency */ "\u09F3",
+    };
+
+    /* Locale bn_IN: Bengali (India) */
+    private static final String[] TEXTS_bn_IN = {
+        /* morekeys_a ~ */
+        null, null, null, null,
+        /* ~ morekeys_u */
+        // Label for "switch to alphabetic" key.
+        // U+0995: "क" BENGALI LETTER KA
+        // U+0996: "ख" BENGALI LETTER KHA
+        // U+0997: "ग" BENGALI LETTER GA
+        /* keylabel_to_alpha */ "\u0995\u0996\u0997",
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -798,13 +839,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F2,\u00F3,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
@@ -813,6 +847,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E8,\u00E9,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -820,16 +861,15 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes ~ */
-        null, null, null, null, null, null, null,
+        /* double_quotes ~ */
+        null, null, null, null, null, null, null, null,
         /* ~ morekeys_t */
         // U+00B7: "·" MIDDLE DOT
         // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
@@ -837,14 +877,14 @@
         /* morekeys_g ~ */
         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,
-        null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null,
         /* ~ morekeys_nordic_row2_11 */
         // U+00B7: "·" MIDDLE DOT
         /* morekeys_punctuation */ "!autoColumnOrder!9,\\,,?,!,\u00B7,#,),(,/,;,',@,:,-,\",+,\\%,&",
         /* keyspec_tablet_comma ~ */
         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,
-        null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ keyspec_south_slavic_row3_8 */
         /* morekeys_tablet_punctuation */ "!autoColumnOrder!8,\\,,',\u00B7,#,),(,/,;,@,:,-,\",+,\\%,&",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
@@ -871,14 +911,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u016F,\u00FB,\u00FC,\u00F9,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
@@ -888,6 +920,14 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u011B,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u016F,\u00FB,\u00FC,\u00F9,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -895,30 +935,30 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B",
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u0148,\u00F1,\u0144",
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u0148,\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         /* morekeys_s */ "\u0161,\u00DF,\u015B",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u010F",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         /* morekeys_z */ "\u017E,\u017A,\u017C",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u010F",
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         /* morekeys_t */ "\u0165",
         /* morekeys_l */ null,
@@ -931,20 +971,27 @@
 
     /* Locale da: Danish */
     private static final String[] TEXTS_da = {
+        // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+        // U+00E6: "æ" LATIN SMALL LETTER AE
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-        /* morekeys_a */ "\u00E1,\u00E4,\u00E0,\u00E2,\u00E3,\u0101",
+        /* morekeys_a */ "\u00E5,\u00E6,\u00E1,\u00E4,\u00E0,\u00E2,\u00E3,\u0101",
+        // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-        /* morekeys_o */ "\u00F3,\u00F4,\u00F2,\u00F5,\u0153,\u014D",
+        /* morekeys_o */ "\u00F8,\u00F6,\u00F3,\u00F4,\u00F2,\u00F5,\u0153,\u014D",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        /* morekeys_e */ "\u00E9,\u00EB",
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
@@ -952,29 +999,26 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        /* morekeys_e */ "\u00E9,\u00EB",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         /* morekeys_i */ "\u00ED,\u00EF",
-        /* morekeys_c */ null,
-        /* double_quotes */ "!text/double_9qm_lqm",
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
+        /* morekeys_c */ null,
+        /* double_quotes */ "!text/double_9qm_lqm",
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
+        /* morekeys_z */ null,
         // U+00F0: "ð" LATIN SMALL LETTER ETH
         /* morekeys_d */ "\u00F0",
-        /* morekeys_z */ null,
         /* morekeys_t */ null,
         // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
         /* morekeys_l */ "\u0142",
@@ -994,8 +1038,8 @@
         /* morekeys_nordic_row2_10 */ "\u00E4",
         /* keyspec_east_slavic_row1_9 ~ */
         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,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         /* morekeys_nordic_row2_11 */ "\u00F6",
     };
@@ -1020,6 +1064,12 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F6,%,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u00F8,\u014D",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0117",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -1027,23 +1077,17 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FC,%,\u00FB,\u00F9,\u00FA,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0117",
         /* morekeys_i */ null,
-        /* morekeys_c */ null,
-        /* double_quotes */ "!text/double_9qm_lqm",
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
+        /* morekeys_c */ null,
+        /* double_quotes */ "!text/double_9qm_lqm",
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency ~ */
         null, null, null, null, null, null, null,
         /* ~ morekeys_g */
@@ -1052,8 +1096,8 @@
         /* morekeys_r ~ */
         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,
-        null, null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null, null, null, null, null,
+        /* ~ keyspec_tablet_period */
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keyspec_swiss_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
@@ -1071,7 +1115,7 @@
     /* Locale el: Greek */
     private static final String[] TEXTS_el = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0391: "Α" GREEK CAPITAL LETTER ALPHA
@@ -1100,6 +1144,12 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         /* morekeys_o */ "\u00F3,\u00F4,\u00F6,\u00F2,\u0153,\u00F8,\u014D,\u00F5",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
@@ -1107,24 +1157,17 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u012B,\u00EC",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u00F1",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        /* morekeys_n */ "\u00F1",
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
     };
@@ -1154,6 +1197,15 @@
         // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D,\u0151,\u00BA",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        /* morekeys_e */ "\u00E9,\u011B,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
@@ -1166,15 +1218,6 @@
         // U+00B5: "µ" MICRO SIGN
         /* morekeys_u */ "\u00FA,\u016F,\u00FB,\u00FC,\u00F9,\u016B,\u0169,\u0171,\u0173,\u00B5",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E9,\u011B,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -1185,12 +1228,6 @@
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u0129,\u00EC,\u012F,\u012B,\u0131,\u0133",
-        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-        // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
-        /* morekeys_c */ "\u0107,\u010D,\u00E7,\u010B",
-        /* double_quotes */ null,
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
@@ -1198,27 +1235,33 @@
         // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
         // U+014B: "ŋ" LATIN SMALL LETTER ENG
         /* morekeys_n */ "\u00F1,\u0144,\u0146,\u0148,\u0149,\u014B",
-        /* single_quotes */ null,
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
+        /* morekeys_c */ "\u0107,\u010D,\u00E7,\u010B",
+        /* double_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u00DF,\u0161,\u015B,\u0219,\u015F",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         // U+00FE: "þ" LATIN SMALL LETTER THORN
         /* morekeys_y */ "y,\u00FD,\u0177,\u00FF,\u00FE",
-        // U+00F0: "ð" LATIN SMALL LETTER ETH
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
-        /* morekeys_d */ "\u00F0,\u010F,\u0111",
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         /* morekeys_z */ "\u017A,\u017C,\u017E",
+        // U+00F0: "ð" LATIN SMALL LETTER ETH
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+        /* morekeys_d */ "\u00F0,\u010F,\u0111",
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         // U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
@@ -1248,6 +1291,7 @@
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         // U+0127: "ħ" LATIN SMALL LETTER H WITH STROKE
@@ -1260,8 +1304,9 @@
         // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
         /* keyspec_spanish_row2_10 */ "\u0135",
         /* morekeys_bullet ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ morekeys_symbols_percent */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
+        /* ~ label_wait_key */
         // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
         /* morekeys_v */ "w,\u0175",
         /* morekeys_j */ null,
@@ -1300,13 +1345,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
@@ -1315,6 +1353,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -1322,18 +1367,18 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes ~ */
+        /* double_quotes ~ */
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null,
         /* ~ morekeys_nordic_row2_11 */
         // U+00A1: "¡" INVERTED EXCLAMATION MARK
         // U+00BF: "¿" INVERTED QUESTION MARK
@@ -1361,6 +1406,15 @@
         // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* morekeys_o */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8",
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        /* morekeys_e */ "\u0113,\u00E8,\u0117,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
@@ -1371,15 +1425,6 @@
         // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
         /* morekeys_u */ "\u00FC,\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u016F,\u0171",
         /* keylabel_to_alpha */ null,
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        /* morekeys_e */ "\u0113,\u00E8,\u0117,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
@@ -1388,31 +1433,31 @@
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         /* morekeys_i */ "\u012B,\u00EC,\u012F,\u00ED,\u00EE,\u00EF,\u0131",
+        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u0146,\u00F1,\u0144",
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u0146,\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u010F",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         /* morekeys_z */ "\u017E,\u017C,\u017A",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u010F",
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         /* morekeys_t */ "\u0163,\u0165",
@@ -1466,13 +1511,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
@@ -1481,6 +1519,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -1488,20 +1533,19 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
     };
 
     /* Locale fa: Persian */
     private static final String[] TEXTS_fa = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0627: "ا" ARABIC LETTER ALEF
@@ -1509,9 +1553,9 @@
         // U+0628: "ب" ARABIC LETTER BEH
         // U+067E: "پ" ARABIC LETTER PEH
         /* keylabel_to_alpha */ "\u0627\u200C\u0628\u200C\u067E",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+FDFC: "﷼" RIAL SIGN
         /* keyspec_currency */ "\uFDFC",
         /* morekeys_y ~ */
@@ -1553,6 +1597,7 @@
         // U+066B: "٫" ARABIC DECIMAL SEPARATOR
         // U+066C: "٬" ARABIC THOUSANDS SEPARATOR
         /* additional_morekeys_symbols_0 */ "0,\u066B,\u066C",
+        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         /* morekeys_nordic_row2_11 */ null,
         /* morekeys_punctuation */ null,
         // U+060C: "،" ARABIC COMMA
@@ -1561,8 +1606,10 @@
         // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
         // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
         /* keyspec_tablet_comma */ "\u060C",
-        /* keyspec_swiss_row1_11 ~ */
-        null, null, null, null, null, null,
+        /* keyspec_period */ null,
+        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
+        /* keyspec_tablet_period ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_swiss_row2_11 */
         // U+2605: "★" BLACK STAR
         // U+066D: "٭" ARABIC FIVE POINTED STAR
@@ -1586,7 +1633,6 @@
         /* morekeys_tablet_comma */ "!fixedColumnOrder!4,:,!,\u061F,\u061B,-,!text/keyspec_left_double_angle_quote,!text/keyspec_right_double_angle_quote",
         // U+064B: "ً" ARABIC FATHATAN
         /* keyhintlabel_period */ "\u064B",
-        /* morekeys_tablet_period */ "!text/morekeys_arabic_diacritics",
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "?,\u00BF",
         /* morekeys_h ~ */
@@ -1618,9 +1664,6 @@
         // Note: The space character is needed as a preceding letter to draw Arabic diacritics characters correctly.
         /* morekeys_arabic_diacritics */ "!fixedColumnOrder!7, \u0655|\u0655, \u0652|\u0652, \u0651|\u0651, \u064C|\u064C, \u064D|\u064D, \u064B|\u064B, \u0654|\u0654, \u0656|\u0656, \u0670|\u0670, \u0653|\u0653, \u064F|\u064F, \u0650|\u0650, \u064E|\u064E,\u0640\u0640\u0640|\u0640",
         /* keyhintlabel_tablet_comma */ "\u061F",
-        /* keyspec_period */ null,
-        /* morekeys_period */ "!text/morekeys_arabic_diacritics",
-        /* keyspec_tablet_period */ null,
         /* keyhintlabel_tablet_period */ "\u064B",
         /* keyspec_symbols_question */ "\u061F",
         /* keyspec_symbols_semicolon */ "\u061B",
@@ -1629,8 +1672,9 @@
         /* morekeys_symbols_semicolon */ ";",
         // U+2030: "‰" PER MILLE SIGN
         /* morekeys_symbols_percent */ "\\%,\u2030",
-        /* morekeys_v ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* label_go_key ~ */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null, null, null,
         /* ~ morekeys_plus */
         // U+2264: "≤" LESS-THAN OR EQUAL TO
         // U+2265: "≥" GREATER-THAN EQUAL TO
@@ -1644,13 +1688,16 @@
 
     /* Locale fi: Finnish */
     private static final String[] TEXTS_fi = {
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+00E6: "æ" LATIN SMALL LETTER AE
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-        /* morekeys_a */ "\u00E6,\u00E0,\u00E1,\u00E2,\u00E3,\u0101",
+        /* morekeys_a */ "\u00E4,\u00E5,\u00E6,\u00E0,\u00E1,\u00E2,\u00E3,\u0101",
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
@@ -1658,25 +1705,26 @@
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-        /* morekeys_o */ "\u00F8,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u014D",
+        /* morekeys_o */ "\u00F6,\u00F8,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u014D",
+        /* morekeys_e */ null,
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* morekeys_u */ "\u00FC",
         /* keylabel_to_alpha ~ */
-        null, null, null, null, null, null, null,
-        /* ~ single_quotes */
+        null, null, null, null, null,
+        /* ~ double_quotes */
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         /* morekeys_s */ "\u0161,\u00DF,\u015B",
-        /* keyspec_currency ~ */
+        /* single_quotes ~ */
         null, null, null,
-        /* ~ morekeys_d */
+        /* ~ morekeys_y */
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         /* morekeys_z */ "\u017E,\u017A,\u017C",
-        /* morekeys_t ~ */
-        null, null, null, null, null, null, null, null,
+        /* morekeys_d ~ */
+        null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keyspec_nordic_row1_11 */ "\u00E5",
@@ -1688,8 +1736,8 @@
         /* morekeys_nordic_row2_10 */ "\u00F8",
         /* keyspec_east_slavic_row1_9 ~ */
         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,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00E6: "æ" LATIN SMALL LETTER AE
         /* morekeys_nordic_row2_11 */ "\u00E6",
     };
@@ -1716,13 +1764,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F4,\u0153,%,\u00F6,\u00F2,\u00F3,\u00F5,\u00F8,\u014D,\u00BA",
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00F9,\u00FB,%,\u00FC,\u00FA,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -1731,6 +1772,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,%,\u0119,\u0117,\u0113",
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00F9,\u00FB,%,\u00FC,\u00FA,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -1738,20 +1786,22 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00EE,%,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        /* morekeys_n */ null,
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,%,\u0107,\u010D",
         /* double_quotes ~ */
-        null, null, null, null, null,
+        null, null, null, null,
         /* ~ keyspec_currency */
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "%,\u00FF",
-        /* morekeys_d ~ */
+        /* morekeys_z ~ */
         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,
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null,
+        /* ~ keyspec_tablet_period */
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         /* keyspec_swiss_row1_11 */ "\u00E8",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
@@ -1789,13 +1839,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
@@ -1804,6 +1847,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -1811,29 +1861,28 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
     };
 
     /* Locale hi: Hindi */
     private static final String[] TEXTS_hi = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0915: "क" DEVANAGARI LETTER KA
         // U+0916: "ख" DEVANAGARI LETTER KHA
         // U+0917: "ग" DEVANAGARI LETTER GA
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
         /* morekeys_y ~ */
@@ -1872,6 +1921,40 @@
         /* additional_morekeys_symbols_8 */ "8",
         /* additional_morekeys_symbols_9 */ "9",
         /* additional_morekeys_symbols_0 */ "0",
+        /* morekeys_tablet_period */ "!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,\",+,\\%,&",
+        /* morekeys_nordic_row2_11 ~ */
+        null, null, null,
+        /* ~ keyspec_tablet_comma */
+        // U+0964: "।" DEVANAGARI DANDA
+        /* keyspec_period */ "\u0964",
+        /* morekeys_period */ "!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&",
+        /* keyspec_tablet_period */ "\u0964",
+    };
+
+    /* Locale hi_ZZ: Hindi (ZZ) */
+    private static final String[] TEXTS_hi_ZZ = {
+        /* morekeys_a ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ single_quotes */
+        // U+20B9: "₹" INDIAN RUPEE SIGN
+        /* keyspec_currency */ "\u20B9",
+        /* morekeys_y ~ */
+        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,
+        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,
+        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,
+        null, null, null, null, null, null, null, null,
+        /* ~ morekeys_symbols_percent */
+        /* label_go_key */ "Go",
+        /* label_send_key */ "Send",
+        /* label_next_key */ "Next",
+        /* label_done_key */ "Done",
+        /* label_search_key */ "Search",
+        /* label_previous_key */ "Prev",
+        /* label_pause_key */ "Pause",
+        /* label_wait_key */ "Wait",
     };
 
     /* Locale hr: Croatian */
@@ -1879,27 +1962,27 @@
         /* morekeys_a ~ */
         null, null, null, null, null, null,
         /* ~ morekeys_i */
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u010D,\u0107,\u00E7",
         /* double_quotes */ "!text/double_9qm_rqm",
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u0161,\u015B,\u00DF",
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency */ null,
         /* morekeys_y */ null,
-        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
-        /* morekeys_d */ "\u0111",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         /* morekeys_z */ "\u017E,\u017A,\u017C",
+        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+        /* morekeys_d */ "\u0111",
         /* morekeys_t ~ */
         null, null, null,
         /* ~ morekeys_g */
@@ -1928,14 +2011,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F6,\u0151,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u0171,\u00FB,\u00F9,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -1944,6 +2019,14 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u0171,\u00FB,\u00F9,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -1951,12 +2034,13 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u00EC,\u012F,\u012B",
+        /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_rqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_g */
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
@@ -1965,19 +2049,21 @@
     /* Locale hy_AM: Armenian (Armenia) */
     private static final String[] TEXTS_hy_AM = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0531: "Ա" ARMENIAN CAPITAL LETTER AYB
         // U+0532: "Բ" ARMENIAN CAPITAL LETTER BEN
         // U+0533: "Գ" ARMENIAN CAPITAL LETTER GIM
         /* keylabel_to_alpha */ "\u0531\u0532\u0533",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
-        /* ~ morekeys_nordic_row2_11 */
+        null, null, null,
+        /* ~ additional_morekeys_symbols_0 */
+        /* morekeys_tablet_period */ "!text/morekeys_punctuation",
+        /* morekeys_nordic_row2_11 */ null,
         // U+055E: "՞" ARMENIAN QUESTION MARK
         // U+055C: "՜" ARMENIAN EXCLAMATION MARK
         // U+055A: "՚" ARMENIAN APOSTROPHE
@@ -1990,6 +2076,10 @@
         // U+055F: "՟" ARMENIAN ABBREVIATION MARK
         /* morekeys_punctuation */ "!autoColumnOrder!8,\\,,\u055E,\u055C,.,\u055A,\u0559,?,!,\u055D,\u055B,\u058A,\u00BB,\u00AB,\u055F,;,:",
         /* keyspec_tablet_comma */ "\u055D",
+        // U+0589: "։" ARMENIAN FULL STOP
+        /* keyspec_period */ "\u0589",
+        /* morekeys_period */ null,
+        /* keyspec_tablet_period */ "\u0589",
         /* keyspec_swiss_row1_11 ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
         null, null, null, null, null, null,
@@ -2002,21 +2092,14 @@
         /* keyspec_comma */ "\u055D",
         /* morekeys_tablet_comma */ null,
         /* keyhintlabel_period */ null,
-        /* morekeys_tablet_period */ "!text/morekeys_punctuation",
         // U+055E: "՞" ARMENIAN QUESTION MARK
         // U+00BF: "¿" INVERTED QUESTION MARK
         /* morekeys_question */ "\u055E,\u00BF",
         /* morekeys_h ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null,
-        /* ~ keyhintlabel_tablet_comma */
-        // U+0589: "։" ARMENIAN FULL STOP
-        /* keyspec_period */ "\u0589",
-        /* morekeys_period */ null,
-        /* keyspec_tablet_period */ "\u0589",
-        /* keyhintlabel_tablet_period ~ */
         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, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_greater_than */
         // U+055C: "՜" ARMENIAN EXCLAMATION MARK
         // U+00A1: "¡" INVERTED EXCLAMATION MARK
@@ -2043,13 +2126,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
@@ -2058,6 +2134,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00EB,\u00E8,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
@@ -2065,18 +2148,18 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EE,\u00EC,\u012F,\u012B",
+        /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
-        /* single_quotes */ "!text/single_9qm_lqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
+        /* morekeys_z */ null,
         // U+00F0: "ð" LATIN SMALL LETTER ETH
         /* morekeys_d */ "\u00F0",
-        /* morekeys_z */ null,
         // U+00FE: "þ" LATIN SMALL LETTER THORN
         /* morekeys_t */ "\u00FE",
     };
@@ -2103,13 +2186,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F2,\u00F3,\u00F4,\u00F6,\u00F5,\u0153,\u00F8,\u014D,\u00BA",
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00F9,\u00FA,\u00FB,\u00FC,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -2118,6 +2194,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u0117,\u0113",
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00F9,\u00FA,\u00FB,\u00FC,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
@@ -2125,12 +2208,12 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00EC,\u00ED,\u00EE,\u00EF,\u012F,\u012B",
-        /* morekeys_c ~ */
+        /* morekeys_n ~ */
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
-        /* ~ keyspec_tablet_comma */
+        null, null, null, null, null, null, null, null, null,
+        /* ~ keyspec_tablet_period */
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         /* keyspec_swiss_row1_11 */ "\u00FC",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
@@ -2148,27 +2231,26 @@
     /* Locale iw: Hebrew */
     private static final String[] TEXTS_iw = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+05D0: "א" HEBREW LETTER ALEF
         // U+05D1: "ב" HEBREW LETTER BET
         // U+05D2: "ג" HEBREW LETTER GIMEL
         /* keylabel_to_alpha */ "\u05D0\u05D1\u05D2",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_rqm_9qm",
-        /* morekeys_n */ null,
-        /* single_quotes */ "!text/single_rqm_9qm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_rqm_9qm",
         // U+20AA: "₪" NEW SHEQEL SIGN
         /* keyspec_currency */ "\u20AA",
         /* morekeys_y ~ */
         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,
         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,
         /* ~ morekeys_swiss_row2_11 */
         // U+2605: "★" BLACK STAR
         /* morekeys_star */ "\u2605",
@@ -2198,6 +2280,7 @@
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ morekeys_currency_dollar */
         // U+00B1: "±" PLUS-MINUS SIGN
         // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
@@ -2207,34 +2290,34 @@
     /* Locale ka_GE: Georgian (Georgia) */
     private static final String[] TEXTS_ka_GE = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+10D0: "ა" GEORGIAN LETTER AN
         // U+10D1: "ბ" GEORGIAN LETTER BAN
         // U+10D2: "გ" GEORGIAN LETTER GAN
         /* keylabel_to_alpha */ "\u10D0\u10D1\u10D2",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
     };
 
     /* Locale kk: Kazakh */
     private static final String[] TEXTS_kk = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null,
+        null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -2255,7 +2338,7 @@
         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,
         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, null, null,
         /* ~ morekeys_w */
         // U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
         /* morekeys_east_slavic_row2_2 */ "\u0456",
@@ -2270,7 +2353,8 @@
         /* morekeys_cyrillic_o */ "\u04E9",
         /* morekeys_cyrillic_i ~ */
         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, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ keyspec_x */
         // U+04BB: "һ" CYRILLIC SMALL LETTER SHHA
         /* morekeys_east_slavic_row2_11 */ "\u04BB",
@@ -2283,14 +2367,14 @@
     /* Locale km_KH: Khmer (Cambodia) */
     private static final String[] TEXTS_km_KH = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+1780: "ក" KHMER LETTER KA
         // U+1781: "ខ" KHMER LETTER KHA
         // U+1782: "គ" KHMER LETTER KO
         /* keylabel_to_alpha */ "\u1780\u1781\u1782",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
@@ -2298,7 +2382,8 @@
         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,
         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, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null, null,
         /* ~ morekeys_cyrillic_a */
         // U+17DB: "៛" KHMER CURRENCY SYMBOL RIEL
         /* morekeys_currency_dollar */ "\u17DB,\u00A2,\u00A3,\u20AC,\u00A5,\u20B1",
@@ -2307,16 +2392,16 @@
     /* Locale kn_IN: Kannada (India) */
     private static final String[] TEXTS_kn_IN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0C85: "ಅ" KANNADA LETTER A
         // U+0C86: "ಆ" KANNADA LETTER AA
         // U+0C87: "ಇ" KANNADA LETTER I
         /* keylabel_to_alpha */ "\u0C85\u0C86\u0C87",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -2324,16 +2409,16 @@
     /* Locale ky: Kirghiz */
     private static final String[] TEXTS_ky = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null,
+        null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -2354,7 +2439,7 @@
         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,
         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, null, null, null, null,
         /* ~ morekeys_east_slavic_row2_2 */
         // U+04AF: "ү" CYRILLIC SMALL LETTER STRAIGHT U
         /* morekeys_cyrillic_u */ "\u04AF",
@@ -2368,16 +2453,16 @@
     /* Locale lo_LA: Lao (Laos) */
     private static final String[] TEXTS_lo_LA = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0E81: "ກ" LAO LETTER KO
         // U+0E82: "ຂ" LAO LETTER KHO SUNG
         // U+0E84: "ຄ" LAO LETTER KHO TAM
         /* keylabel_to_alpha */ "\u0E81\u0E82\u0E84",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20AD: "₭" KIP SIGN
         /* keyspec_currency */ "\u20AD",
     };
@@ -2403,6 +2488,15 @@
         // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* morekeys_o */ "\u00F6,\u00F5,\u00F2,\u00F3,\u00F4,\u0153,\u0151,\u00F8",
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        /* morekeys_e */ "\u0117,\u0119,\u0113,\u00E8,\u00E9,\u00EA,\u00EB,\u011B",
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
@@ -2414,15 +2508,6 @@
         // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
         /* morekeys_u */ "\u016B,\u0173,\u00FC,\u016B,\u00F9,\u00FA,\u00FB,\u016F,\u0171",
         /* keylabel_to_alpha */ null,
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        /* morekeys_e */ "\u0117,\u0119,\u0113,\u00E8,\u00E9,\u00EA,\u00EB,\u011B",
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -2431,31 +2516,31 @@
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         /* morekeys_i */ "\u012F,\u012B,\u00EC,\u00ED,\u00EE,\u00EF,\u0131",
+        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u0146,\u00F1,\u0144",
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u0146,\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u010F",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         /* morekeys_z */ "\u017E,\u017C,\u017A",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u010F",
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         /* morekeys_t */ "\u0163,\u0165",
@@ -2498,6 +2583,15 @@
         // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* morekeys_o */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u0153,\u0151,\u00F8",
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        /* morekeys_e */ "\u0113,\u0117,\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -2508,15 +2602,6 @@
         // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
         /* morekeys_u */ "\u016B,\u0173,\u00F9,\u00FA,\u00FB,\u00FC,\u016F,\u0171",
         /* keylabel_to_alpha */ null,
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        /* morekeys_e */ "\u0113,\u0117,\u00E8,\u00E9,\u00EA,\u00EB,\u0119,\u011B",
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -2525,31 +2610,31 @@
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         /* morekeys_i */ "\u012B,\u012F,\u00EC,\u00ED,\u00EE,\u00EF,\u0131",
+        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u0146,\u00F1,\u0144",
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u00E7,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u0146,\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u010F",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         /* morekeys_z */ "\u017E,\u017C,\u017A",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u010F",
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         /* morekeys_t */ "\u0163,\u0165",
@@ -2574,21 +2659,21 @@
     /* Locale mk: Macedonian */
     private static final String[] TEXTS_mk = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0450: "ѐ" CYRILLIC SMALL LETTER IE WITH GRAVE
         /* morekeys_cyrillic_ie */ "\u0450",
@@ -2597,7 +2682,7 @@
         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,
         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,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -2614,14 +2699,14 @@
     /* Locale ml_IN: Malayalam (India) */
     private static final String[] TEXTS_ml_IN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0D05: "അ" MALAYALAM LETTER A
         /* keylabel_to_alpha */ "\u0D05",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -2629,16 +2714,16 @@
     /* Locale mn_MN: Mongolian (Mongolia) */
     private static final String[] TEXTS_mn_MN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20AE: "₮" TUGRIK SIGN
         /* keyspec_currency */ "\u20AE",
     };
@@ -2646,16 +2731,16 @@
     /* Locale mr_IN: Marathi (India) */
     private static final String[] TEXTS_mr_IN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0915: "क" DEVANAGARI LETTER KA
         // U+0916: "ख" DEVANAGARI LETTER KHA
         // U+0917: "ग" DEVANAGARI LETTER GA
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
         /* morekeys_y ~ */
@@ -2696,68 +2781,26 @@
         /* additional_morekeys_symbols_0 */ "0",
     };
 
-    /* Locale my_MM: Burmese (Myanmar) */
-    private static final String[] TEXTS_my_MM = {
-        /* morekeys_a ~ */
-        null, null, null,
-        /* ~ morekeys_u */
-        // Label for "switch to alphabetic" key.
-        // U+1000: "က" MYANMAR LETTER KA
-        // U+1001: "ခ" MYANMAR LETTER KHA
-        // U+1002: "ဂ" MYANMAR LETTER GA
-        /* keylabel_to_alpha */ "\u1000\u1001\u1002",
-        /* morekeys_e ~ */
-        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,
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null,
-        /* ~ morekeys_nordic_row2_11 */
-        /* morekeys_punctuation */ "!autoColumnOrder!9,\u104A,.,?,!,#,),(,/,;,...,',@,:,-,\",+,\\%,&",
-        // U+104A: "၊" MYANMAR SIGN LITTLE SECTION
-        // U+104B: "။" MYANMAR SIGN SECTION
-        /* keyspec_tablet_comma */ "\u104A",
-        /* keyspec_swiss_row1_11 ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        null, null, null, null, null, null, null,
-        /* ~ keyspec_comma */
-        /* morekeys_tablet_comma */ "\\,",
-        /* keyhintlabel_period */ "\u104A",
-        /* morekeys_tablet_period ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-        /* ~ keyspec_south_slavic_row3_8 */
-        /* morekeys_tablet_punctuation */ "!autoColumnOrder!8,.,',#,),(,/,;,@,...,:,-,\",+,\\%,&",
-        /* keyspec_spanish_row2_10 ~ */
-        null, null, null, null, null, null,
-        /* ~ keyhintlabel_tablet_comma */
-        /* keyspec_period */ "\u104B",
-        /* morekeys_period */ null,
-        /* keyspec_tablet_period */ "\u104B",
-    };
-
     /* Locale nb: Norwegian Bokmål */
     private static final String[] TEXTS_nb = {
-        // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+        // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+        // U+00E6: "æ" LATIN SMALL LETTER AE
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-        /* morekeys_a */ "\u00E0,\u00E4,\u00E1,\u00E2,\u00E3,\u0101",
+        /* morekeys_a */ "\u00E5,\u00E6,\u00E4,\u00E0,\u00E1,\u00E2,\u00E3,\u0101",
+        // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
         // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-        /* morekeys_o */ "\u00F4,\u00F2,\u00F3,\u00F6,\u00F5,\u0153,\u014D",
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
-        /* keylabel_to_alpha */ null,
+        /* morekeys_o */ "\u00F8,\u00F6,\u00F4,\u00F2,\u00F3,\u00F5,\u0153,\u014D",
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -2766,13 +2809,20 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119,\u0117,\u0113",
-        /* morekeys_i */ null,
-        /* morekeys_c */ null,
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+        /* keylabel_to_alpha ~ */
+        null, null, null, null,
+        /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_rqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_cyrillic_ie */
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         /* keyspec_nordic_row1_11 */ "\u00E5",
@@ -2784,8 +2834,8 @@
         /* morekeys_nordic_row2_10 */ "\u00F6",
         /* keyspec_east_slavic_row1_9 ~ */
         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,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         /* morekeys_nordic_row2_11 */ "\u00E4",
     };
@@ -2793,16 +2843,16 @@
     /* Locale ne_NP: Nepali (Nepal) */
     private static final String[] TEXTS_ne_NP = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0915: "क" DEVANAGARI LETTER KA
         // U+0916: "ख" DEVANAGARI LETTER KHA
         // U+0917: "ग" DEVANAGARI LETTER GA
         /* keylabel_to_alpha */ "\u0915\u0916\u0917",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN
         /* keyspec_currency */ "\u0930\u0941.",
         /* morekeys_y ~ */
@@ -2841,6 +2891,14 @@
         /* additional_morekeys_symbols_8 */ "8",
         /* additional_morekeys_symbols_9 */ "9",
         /* additional_morekeys_symbols_0 */ "0",
+        /* morekeys_tablet_period */ "!autoColumnOrder!8,.,\\,,',#,),(,/,;,@,:,-,\",+,\\%,&",
+        /* morekeys_nordic_row2_11 ~ */
+        null, null, null,
+        /* ~ keyspec_tablet_comma */
+        // U+0964: "।" DEVANAGARI DANDA
+        /* keyspec_period */ "\u0964",
+        /* morekeys_period */ "!autoColumnOrder!9,.,\\,,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&",
+        /* keyspec_tablet_period */ "\u0964",
     };
 
     /* Locale nl: Dutch */
@@ -2863,13 +2921,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -2878,6 +2929,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00EB,\u00EA,\u00E8,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00FB,\u00F9,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -2886,13 +2944,13 @@
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B,\u0133",
-        /* morekeys_c */ null,
-        /* double_quotes */ "!text/double_9qm_rqm",
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         /* morekeys_n */ "\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_rqm",
+        /* morekeys_c */ null,
+        /* double_quotes */ "!text/double_9qm_rqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency */ null,
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_y */ "\u0133",
@@ -2919,8 +2977,6 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F3,\u00F6,\u00F4,\u00F2,\u00F5,\u0153,\u00F8,\u014D",
-        /* morekeys_u */ null,
-        /* keylabel_to_alpha */ null,
         // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
@@ -2929,27 +2985,29 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u0119,\u00E8,\u00E9,\u00EA,\u00EB,\u0117,\u0113",
-        /* morekeys_i */ null,
+        /* morekeys_u ~ */
+        null, null, null,
+        /* ~ morekeys_i */
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u0144,\u00F1",
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u0107,\u00E7,\u010D",
         /* double_quotes */ "!text/double_9qm_rqm",
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        /* morekeys_n */ "\u0144,\u00F1",
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015B,\u00DF,\u0161",
-        /* keyspec_currency ~ */
-        null, null, null,
-        /* ~ morekeys_d */
+        /* single_quotes */ "!text/single_9qm_rqm",
+        /* keyspec_currency */ null,
+        /* morekeys_y */ null,
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         /* morekeys_z */ "\u017C,\u017A,\u017E",
+        /* morekeys_d */ null,
         /* morekeys_t */ null,
         // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
         /* morekeys_l */ "\u0142",
@@ -2976,13 +3034,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F5,\u00F4,\u00F2,\u00F6,\u0153,\u00F8,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
@@ -2991,6 +3042,13 @@
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
         /* morekeys_e */ "\u00E9,\u00EA,\u00E8,\u0119,\u0117,\u0113,\u00EB",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -2998,6 +3056,7 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EE,\u00EC,\u00EF,\u012F,\u012B",
+        /* morekeys_n */ null,
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
@@ -3019,19 +3078,19 @@
 
     /* Locale ro: Romanian */
     private static final String[] TEXTS_ro = {
+        // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-        // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
         // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
         // U+00E6: "æ" LATIN SMALL LETTER AE
         // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
         // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-        /* morekeys_a */ "\u00E2,\u00E3,\u0103,\u00E0,\u00E1,\u00E4,\u00E6,\u00E5,\u0101",
+        /* morekeys_a */ "\u0103,\u00E2,\u00E3,\u00E0,\u00E1,\u00E4,\u00E6,\u00E5,\u0101",
         /* morekeys_o ~ */
         null, null, null, null,
-        /* ~ morekeys_e */
+        /* ~ keylabel_to_alpha */
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -3039,18 +3098,18 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        /* morekeys_n */ null,
         /* morekeys_c */ null,
         /* double_quotes */ "!text/double_9qm_rqm",
-        /* morekeys_n */ null,
-        /* single_quotes */ "!text/single_9qm_rqm",
         // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u0219,\u00DF,\u015B,\u0161",
+        /* single_quotes */ "!text/single_9qm_rqm",
         /* keyspec_currency ~ */
         null, null, null, null,
-        /* ~ morekeys_z */
+        /* ~ morekeys_d */
         // U+021B: "ț" LATIN SMALL LETTER T WITH COMMA BELOW
         /* morekeys_t */ "\u021B",
     };
@@ -3058,21 +3117,21 @@
     /* Locale ru: Russian */
     private static final String[] TEXTS_ru = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null, null, null, null, null,
         /* ~ morekeys_k */
         // U+0451: "ё" CYRILLIC SMALL LETTER IO
         /* morekeys_cyrillic_ie */ "\u0451",
@@ -3094,15 +3153,15 @@
     /* Locale si_LK: Sinhalese (Sri Lanka) */
     private static final String[] TEXTS_si_LK = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0D85: "අ" SINHALA LETTER AYANNA
         // U+0D86: "ආ" SINHALA LETTER AAYANNA
         /* keylabel_to_alpha */ "\u0D85,\u0D86",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+0DBB/U+0DD4: "රු" SINHALA LETTER RAYANNA/SINHALA VOWEL SIGN KETTI PAA-PILLA
         /* keyspec_currency */ "\u0DBB\u0DD4",
     };
@@ -3128,6 +3187,15 @@
         // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         /* morekeys_o */ "\u00F4,\u00F3,\u00F6,\u00F2,\u00F5,\u0153,\u0151,\u00F8",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        /* morekeys_e */ "\u00E9,\u011B,\u0113,\u0117,\u00E8,\u00EA,\u00EB,\u0119",
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
@@ -3138,15 +3206,6 @@
         // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
         /* morekeys_u */ "\u00FA,\u016F,\u00FC,\u016B,\u0173,\u00F9,\u00FB,\u0171",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        /* morekeys_e */ "\u00E9,\u011B,\u0113,\u0117,\u00E8,\u00EA,\u00EB,\u0119",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
@@ -3155,32 +3214,32 @@
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         /* morekeys_i */ "\u00ED,\u012B,\u012F,\u00EC,\u00EE,\u00EF,\u0131",
-        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-        /* morekeys_c */ "\u010D,\u00E7,\u0107",
-        /* double_quotes */ "!text/double_9qm_lqm",
         // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         /* morekeys_n */ "\u0148,\u0146,\u00F1,\u0144",
-        /* single_quotes */ "!text/single_9qm_lqm",
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        /* morekeys_c */ "\u010D,\u00E7,\u0107",
+        /* double_quotes */ "!text/double_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         /* morekeys_s */ "\u0161,\u00DF,\u015B,\u015F",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u010F",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         /* morekeys_z */ "\u017E,\u017C,\u017A",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u010F",
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
         /* morekeys_t */ "\u0165,\u0163",
@@ -3205,22 +3264,21 @@
     /* Locale sl: Slovenian */
     private static final String[] TEXTS_sl = {
         /* morekeys_a ~ */
-        null, null, null, null, null, null,
-        /* ~ morekeys_i */
+        null, null, null, null, null, null, null,
+        /* ~ morekeys_n */
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         /* morekeys_c */ "\u010D,\u0107",
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
-        /* single_quotes */ "!text/single_9qm_lqm",
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u0161",
+        /* single_quotes */ "!text/single_9qm_lqm",
         /* keyspec_currency */ null,
         /* morekeys_y */ null,
-        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
-        /* morekeys_d */ "\u0111",
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         /* morekeys_z */ "\u017E",
+        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+        /* morekeys_d */ "\u0111",
         /* morekeys_t ~ */
         null, null, null,
         /* ~ morekeys_g */
@@ -3231,7 +3289,7 @@
     /* Locale sr: Serbian */
     private static final String[] TEXTS_sr = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // END: More keys definitions for Serbian (Cyrillic)
         // Label for "switch to alphabetic" key.
@@ -3239,14 +3297,14 @@
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
+        /* morekeys_s */ null,
         /* single_quotes */ "!text/single_9qm_lqm",
-        /* morekeys_s ~ */
-        null, null, null, null, null, null, null, null,
+        /* keyspec_currency ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_g */
         /* single_angle_quotes */ "!text/single_raqm_laqm",
         /* double_angle_quotes */ "!text/double_raqm_laqm",
@@ -3259,7 +3317,7 @@
         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,
         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,
         /* ~ morekeys_cyrillic_o */
         // U+045D: "ѝ" CYRILLIC SMALL LETTER I WITH GRAVE
         /* morekeys_cyrillic_i */ "\u045D",
@@ -3291,20 +3349,75 @@
         /* keyspec_south_slavic_row3_8 */ "\u0452",
     };
 
+    /* Locale sr_ZZ: Serbian (ZZ) */
+    private static final String[] TEXTS_sr_ZZ = {
+        /* morekeys_a */ null,
+        /* morekeys_o */ null,
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        /* morekeys_e */ "\u00E8",
+        /* morekeys_u */ null,
+        /* keylabel_to_alpha */ null,
+        // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+        /* morekeys_i */ "\u00EC",
+        /* morekeys_n */ null,
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        /* morekeys_c */ "\u010D,\u0107,%",
+        /* double_quotes */ null,
+        // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+        /* morekeys_s */ "\u0161,%",
+        /* single_quotes ~ */
+        null, null, null,
+        /* ~ morekeys_y */
+        // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+        /* morekeys_z */ "\u017E,%",
+        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+        /* morekeys_d */ "\u0111,%",
+        /* morekeys_t ~ */
+        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,
+        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,
+        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,
+        null, null, null, null, null,
+        /* ~ morekeys_symbols_percent */
+        /* label_go_key */ "Idi",
+        /* label_send_key */ "\u0160alji",
+        /* label_next_key */ "Sled",
+        /* label_done_key */ "Gotov",
+        /* label_search_key */ "Tra\u017Ei",
+        /* label_previous_key */ "Preth",
+        /* label_pause_key */ "Pauza",
+        /* label_wait_key */ "\u010Cekaj",
+    };
+
     /* Locale sv: Swedish */
     private static final String[] TEXTS_sv = {
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E5: "å" LATIN SMALL LETTER A WITH RING
+        // U+00E6: "æ" LATIN SMALL LETTER AE
         // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
         // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
         // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-        /* morekeys_a */ "\u00E1,\u00E0,\u00E2,\u0105,\u00E3",
+        /* morekeys_a */ "\u00E4,\u00E5,\u00E6,\u00E1,\u00E0,\u00E2,\u0105,\u00E3",
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+        // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+        // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
         // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-        /* morekeys_o */ "\u00F3,\u00F2,\u00F4,\u00F5,\u014D",
+        /* morekeys_o */ "\u00F6,\u00F8,\u0153,\u00F3,\u00F2,\u00F4,\u00F5,\u014D",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -3312,43 +3425,37 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FC,\u00FA,\u00F9,\u00FB,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0119",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         /* morekeys_i */ "\u00ED,\u00EC,\u00EE,\u00EF",
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        /* morekeys_n */ "\u0144,\u00F1,\u0148",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
         /* double_quotes */ null,
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
-        /* morekeys_n */ "\u0144,\u00F1,\u0148",
-        /* single_quotes */ null,
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u015B,\u0161,\u015F,\u00DF",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         /* morekeys_y */ "\u00FD,\u00FF",
-        // U+00F0: "ð" LATIN SMALL LETTER ETH
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        /* morekeys_d */ "\u00F0,\u010F",
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         /* morekeys_z */ "\u017A,\u017E,\u017C",
+        // U+00F0: "ð" LATIN SMALL LETTER ETH
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        /* morekeys_d */ "\u00F0,\u010F",
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
         // U+00FE: "þ" LATIN SMALL LETTER THORN
         /* morekeys_t */ "\u0165,\u00FE",
@@ -3372,8 +3479,8 @@
         /* morekeys_nordic_row2_10 */ "\u00F8,\u0153",
         /* keyspec_east_slavic_row1_9 ~ */
         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,
-        /* ~ additional_morekeys_symbols_0 */
+        null, null, null, null, null, null, null, null, null, null, null, null,
+        /* ~ morekeys_tablet_period */
         // U+00E6: "æ" LATIN SMALL LETTER AE
         /* morekeys_nordic_row2_11 */ "\u00E6",
     };
@@ -3399,6 +3506,12 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         /* morekeys_o */ "\u00F4,\u00F6,\u00F2,\u00F3,\u0153,\u00F8,\u014D,\u00F5",
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -3406,28 +3519,21 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FB,\u00FC,\u00F9,\u00FA,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113",
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         /* morekeys_i */ "\u00EE,\u00EF,\u00ED,\u012B,\u00EC",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u00F1",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        /* morekeys_n */ "\u00F1",
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
-        /* keyspec_currency ~ */
-        null, null, null, null, null, null,
+        /* single_quotes ~ */
+        null, null, null, null, null, null, null,
         /* ~ morekeys_l */
         /* morekeys_g */ "g\'",
     };
@@ -3435,16 +3541,16 @@
     /* Locale ta_IN: Tamil (India) */
     private static final String[] TEXTS_ta_IN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0BA4: "த" TAMIL LETTER TA
         // U+0BAE/U+0BBF: "மி" TAMIL LETTER MA/TAMIL VOWEL SIGN I
         // U+0BB4/U+0BCD: "ழ்" TAMIL LETTER LLLA/TAMIL SIGN VIRAMA
         /* keylabel_to_alpha */ "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+0BF9: "௹" TAMIL RUPEE SIGN
         /* keyspec_currency */ "\u0BF9",
     };
@@ -3452,16 +3558,16 @@
     /* Locale ta_LK: Tamil (Sri Lanka) */
     private static final String[] TEXTS_ta_LK = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0BA4: "த" TAMIL LETTER TA
         // U+0BAE/U+0BBF: "மி" TAMIL LETTER MA/TAMIL VOWEL SIGN I
         // U+0BB4/U+0BCD: "ழ்" TAMIL LETTER LLLA/TAMIL SIGN VIRAMA
         /* keylabel_to_alpha */ "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+0DBB/U+0DD4: "රු" SINHALA LETTER RAYANNA/SINHALA VOWEL SIGN KETTI PAA-PILLA
         /* keyspec_currency */ "\u0DBB\u0DD4",
     };
@@ -3469,7 +3575,7 @@
     /* Locale ta_SG: Tamil (Singapore) */
     private static final String[] TEXTS_ta_SG = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0BA4: "த" TAMIL LETTER TA
@@ -3481,16 +3587,16 @@
     /* Locale te_IN: Telugu (India) */
     private static final String[] TEXTS_te_IN = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0C05: "అ" TELUGU LETTER A
         // U+0C06: "ఆ" TELUGU LETTER AA
         // U+0C07: "ఇ" TELUGU LETTER I
         /* keylabel_to_alpha */ "\u0C05\u0C06\u0C07",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+20B9: "₹" INDIAN RUPEE SIGN
         /* keyspec_currency */ "\u20B9",
     };
@@ -3498,16 +3604,16 @@
     /* Locale th: Thai */
     private static final String[] TEXTS_th = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0E01: "ก" THAI CHARACTER KO KAI
         // U+0E02: "ข" THAI CHARACTER KHO KHAI
         // U+0E04: "ค" THAI CHARACTER KHO KHWAI
         /* keylabel_to_alpha */ "\u0E01\u0E02\u0E04",
-        /* morekeys_e ~ */
-        null, null, null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* morekeys_i ~ */
+        null, null, null, null, null, null,
+        /* ~ single_quotes */
         // U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT
         /* keyspec_currency */ "\u0E3F",
     };
@@ -3535,13 +3641,6 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F3,\u00F2,\u00F6,\u00F4,\u00F5,\u00F8,\u0153,\u014D,\u00BA",
-        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
-        /* keylabel_to_alpha */ null,
         // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
         // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
         // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
@@ -3550,6 +3649,13 @@
         // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
         // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
         /* morekeys_e */ "\u00E9,\u00E8,\u00EB,\u00EA,\u0119,\u0117,\u0113",
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FA,\u00FC,\u00F9,\u00FB,\u016B",
+        /* keylabel_to_alpha */ null,
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
@@ -3557,20 +3663,21 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u00ED,\u00EF,\u00EC,\u00EE,\u012F,\u012B",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+        /* morekeys_n */ "\u00F1,\u0144",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-        /* morekeys_n */ "\u00F1,\u0144",
     };
 
     /* Locale tr: Turkish */
     private static final String[] TEXTS_tr = {
         // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-        /* morekeys_a */ "\u00E2",
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+        /* morekeys_a */ "\u00E2,\u00E4,\u00E1",
         // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
         // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
         // U+0153: "œ" LATIN SMALL LIGATURE OE
@@ -3580,6 +3687,9 @@
         // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         /* morekeys_o */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D",
+        // U+0259: "ə" LATIN SMALL LETTER SCHWA
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        /* morekeys_e */ "\u0259,\u00E9",
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
@@ -3587,7 +3697,6 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
         /* keylabel_to_alpha */ null,
-        /* morekeys_e */ null,
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -3596,20 +3705,27 @@
         // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         /* morekeys_i */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u0148,\u00F1",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
         // U+010D: "č" LATIN SMALL LETTER C WITH CARON
         /* morekeys_c */ "\u00E7,\u0107,\u010D",
-        /* double_quotes ~ */
-        null, null, null,
-        /* ~ single_quotes */
+        /* double_quotes */ null,
         // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
-        /* keyspec_currency ~ */
-        null, null, null, null, null, null,
+        /* single_quotes */ null,
+        /* keyspec_currency */ null,
+        // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+        /* morekeys_y */ "\u00FD",
+        // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+        /* morekeys_z */ "\u017E",
+        /* morekeys_d ~ */
+        null, null, null,
         /* ~ morekeys_l */
         // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
         /* morekeys_g */ "\u011F",
@@ -3618,20 +3734,19 @@
     /* Locale uk: Ukrainian */
     private static final String[] TEXTS_uk = {
         /* morekeys_a ~ */
-        null, null, null,
+        null, null, null, null,
         /* ~ morekeys_u */
         // Label for "switch to alphabetic" key.
         // U+0410: "А" CYRILLIC CAPITAL LETTER A
         // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
         // U+0412: "В" CYRILLIC CAPITAL LETTER VE
         /* keylabel_to_alpha */ "\u0410\u0411\u0412",
-        /* morekeys_e ~ */
+        /* morekeys_i ~ */
         null, null, null,
         /* ~ morekeys_c */
         /* double_quotes */ "!text/double_9qm_lqm",
-        /* morekeys_n */ null,
-        /* single_quotes */ "!text/single_9qm_lqm",
         /* morekeys_s */ null,
+        /* single_quotes */ "!text/single_9qm_lqm",
         // U+20B4: "₴" HRYVNIA SIGN
         /* keyspec_currency */ "\u20B4",
         /* morekeys_y ~ */
@@ -3651,7 +3766,7 @@
         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,
         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, null, null,
         /* ~ morekeys_w */
         // U+0457: "ї" CYRILLIC SMALL LETTER YI
         /* morekeys_east_slavic_row2_2 */ "\u0457",
@@ -3661,6 +3776,66 @@
         /* morekeys_cyrillic_ghe */ "\u0491",
     };
 
+    /* Locale uz_UZ: Uzbek (Uzbekistan) */
+    private static final String[] TEXTS_uz_UZ = {
+        // This is the same as Turkish
+        // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+        // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+        // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+        /* morekeys_a */ "\u00E2,\u00E4,\u00E1",
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+        // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+        // U+0153: "œ" LATIN SMALL LIGATURE OE
+        // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+        // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+        // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+        // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+        // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+        /* morekeys_o */ "\u00F6,\u00F4,\u0153,\u00F2,\u00F3,\u00F5,\u00F8,\u014D",
+        // U+0259: "ə" LATIN SMALL LETTER SCHWA
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        /* morekeys_e */ "\u0259,\u00E9",
+        // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+        // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+        // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+        // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        /* morekeys_u */ "\u00FC,\u00FB,\u00F9,\u00FA,\u016B",
+        /* keylabel_to_alpha */ null,
+        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+        // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+        // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+        // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+        // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+        // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+        // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+        /* morekeys_i */ "\u0131,\u00EE,\u00EF,\u00EC,\u00ED,\u012F,\u012B",
+        // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u0148,\u00F1",
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        /* morekeys_c */ "\u00E7,\u0107,\u010D",
+        /* double_quotes */ null,
+        // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+        // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+        // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+        /* morekeys_s */ "\u015F,\u00DF,\u015B,\u0161",
+        /* single_quotes */ null,
+        /* keyspec_currency */ null,
+        // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+        /* morekeys_y */ "\u00FD",
+        // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+        /* morekeys_z */ "\u017E",
+        /* morekeys_d ~ */
+        null, null, null,
+        /* ~ morekeys_l */
+        // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+        /* morekeys_g */ "\u011F",
+    };
+
     /* Locale vi: Vietnamese */
     private static final String[] TEXTS_vi = {
         // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
@@ -3699,6 +3874,18 @@
         // U+1EE1: "ỡ" LATIN SMALL LETTER O WITH HORN AND TILDE
         // U+1EE3: "ợ" LATIN SMALL LETTER O WITH HORN AND DOT BELOW
         /* morekeys_o */ "\u00F2,\u00F3,\u1ECF,\u00F5,\u1ECD,\u00F4,\u1ED3,\u1ED1,\u1ED5,\u1ED7,\u1ED9,\u01A1,\u1EDD,\u1EDB,\u1EDF,\u1EE1,\u1EE3",
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+1EBB: "ẻ" LATIN SMALL LETTER E WITH HOOK ABOVE
+        // U+1EBD: "ẽ" LATIN SMALL LETTER E WITH TILDE
+        // U+1EB9: "ẹ" LATIN SMALL LETTER E WITH DOT BELOW
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+1EC1: "ề" LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
+        // U+1EBF: "ế" LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
+        // U+1EC3: "ể" LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
+        // U+1EC5: "ễ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
+        // U+1EC7: "ệ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
+        /* morekeys_e */ "\u00E8,\u00E9,\u1EBB,\u1EBD,\u1EB9,\u00EA,\u1EC1,\u1EBF,\u1EC3,\u1EC5,\u1EC7",
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+1EE7: "ủ" LATIN SMALL LETTER U WITH HOOK ABOVE
@@ -3712,27 +3899,15 @@
         // U+1EF1: "ự" LATIN SMALL LETTER U WITH HORN AND DOT BELOW
         /* morekeys_u */ "\u00F9,\u00FA,\u1EE7,\u0169,\u1EE5,\u01B0,\u1EEB,\u1EE9,\u1EED,\u1EEF,\u1EF1",
         /* keylabel_to_alpha */ null,
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+1EBB: "ẻ" LATIN SMALL LETTER E WITH HOOK ABOVE
-        // U+1EBD: "ẽ" LATIN SMALL LETTER E WITH TILDE
-        // U+1EB9: "ẹ" LATIN SMALL LETTER E WITH DOT BELOW
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+1EC1: "ề" LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE
-        // U+1EBF: "ế" LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE
-        // U+1EC3: "ể" LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE
-        // U+1EC5: "ễ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE
-        // U+1EC7: "ệ" LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW
-        /* morekeys_e */ "\u00E8,\u00E9,\u1EBB,\u1EBD,\u1EB9,\u00EA,\u1EC1,\u1EBF,\u1EC3,\u1EC5,\u1EC7",
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+1EC9: "ỉ" LATIN SMALL LETTER I WITH HOOK ABOVE
         // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE
         // U+1ECB: "ị" LATIN SMALL LETTER I WITH DOT BELOW
         /* morekeys_i */ "\u00EC,\u00ED,\u1EC9,\u0129,\u1ECB",
-        /* morekeys_c ~ */
+        /* morekeys_n ~ */
         null, null, null, null, null,
-        /* ~ morekeys_s */
+        /* ~ single_quotes */
         // U+20AB: "₫" DONG SIGN
         /* keyspec_currency */ "\u20AB",
         // U+1EF3: "ỳ" LATIN SMALL LETTER Y WITH GRAVE
@@ -3741,6 +3916,7 @@
         // U+1EF9: "ỹ" LATIN SMALL LETTER Y WITH TILDE
         // U+1EF5: "ỵ" LATIN SMALL LETTER Y WITH DOT BELOW
         /* morekeys_y */ "\u1EF3,\u00FD,\u1EF7,\u1EF9,\u1EF5",
+        /* morekeys_z */ null,
         // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
         /* morekeys_d */ "\u0111",
     };
@@ -3766,6 +3942,12 @@
         // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
         // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
         /* morekeys_o */ "\u00F3,\u00F4,\u00F6,\u00F2,\u0153,\u00F8,\u014D,\u00F5",
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
         // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
@@ -3773,24 +3955,17 @@
         // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
         /* morekeys_u */ "\u00FA,\u00FB,\u00FC,\u00F9,\u016B",
         /* keylabel_to_alpha */ null,
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        /* morekeys_e */ "\u00E9,\u00E8,\u00EA,\u00EB,\u0113",
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
         // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
         // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         /* morekeys_i */ "\u00ED,\u00EE,\u00EF,\u012B,\u00EC",
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        /* morekeys_n */ "\u00F1",
         // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
         /* morekeys_c */ "\u00E7",
         /* double_quotes */ null,
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        /* morekeys_n */ "\u00F1",
-        /* single_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         /* morekeys_s */ "\u00DF",
     };
@@ -3821,6 +3996,16 @@
         // U+0153: "œ" LATIN SMALL LIGATURE OE
         // U+00BA: "º" MASCULINE ORDINAL INDICATOR
         /* morekeys_o */ "\u00F2,\u00F3,\u00F4,\u00F5,\u00F6,\u00F8,\u014D,\u014F,\u0151,\u0153,\u00BA",
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+        // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE
+        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113,\u0115,\u0117,\u0119,\u011B",
         // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
         // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
         // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
@@ -3833,16 +4018,6 @@
         // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
         /* morekeys_u */ "\u00F9,\u00FA,\u00FB,\u00FC,\u0169,\u016B,\u016D,\u016F,\u0171,\u0173",
         /* keylabel_to_alpha */ null,
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-        // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-        // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-        // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-        // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE
-        // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-        // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-        // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-        /* morekeys_e */ "\u00E8,\u00E9,\u00EA,\u00EB,\u0113,\u0115,\u0117,\u0119,\u011B",
         // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
         // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
         // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
@@ -3854,13 +4029,6 @@
         // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_i */ "\u00EC,\u00ED,\u00EE,\u00EF,\u0129,\u012B,\u012D,\u012F,\u0131,\u0133",
-        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-        // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
-        // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
-        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-        /* morekeys_c */ "\u00E7,\u0107,\u0109,\u010B,\u010D",
-        /* double_quotes */ null,
         // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
         // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
         // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
@@ -3868,7 +4036,13 @@
         // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
         // U+014B: "ŋ" LATIN SMALL LETTER ENG
         /* morekeys_n */ "\u00F1,\u0144,\u0146,\u0148,\u0149,\u014B",
-        /* single_quotes */ null,
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+        // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
+        // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
+        // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+        /* morekeys_c */ "\u00E7,\u0107,\u0109,\u010B,\u010D",
+        /* double_quotes */ null,
         // U+00DF: "ß" LATIN SMALL LETTER SHARP S
         // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
         // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
@@ -3876,20 +4050,21 @@
         // U+0161: "š" LATIN SMALL LETTER S WITH CARON
         // U+017F: "ſ" LATIN SMALL LETTER LONG S
         /* morekeys_s */ "\u00DF,\u015B,\u015D,\u015F,\u0161,\u017F",
+        /* single_quotes */ null,
         /* keyspec_currency */ null,
         // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
         // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
         // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
         // U+0133: "ij" LATIN SMALL LIGATURE IJ
         /* morekeys_y */ "\u00FD,\u0177,\u00FF,\u0133",
-        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
-        // U+00F0: "ð" LATIN SMALL LETTER ETH
-        /* morekeys_d */ "\u010F,\u0111,\u00F0",
         // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
         // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
         // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
         /* morekeys_z */ "\u017A,\u017C,\u017E",
+        // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+        // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+        // U+00F0: "ð" LATIN SMALL LETTER ETH
+        /* morekeys_d */ "\u010F,\u0111,\u00F0",
         // U+00FE: "þ" LATIN SMALL LETTER THORN
         // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
         // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
@@ -3920,6 +4095,7 @@
         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,
         null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null, null,
         /* ~ morekeys_question */
         // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
         /* morekeys_h */ "\u0125",
@@ -3927,7 +4103,8 @@
         /* morekeys_w */ "\u0175",
         /* morekeys_east_slavic_row2_2 ~ */
         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, null, null, null, null, null, null, null, null, null, null, null, null,
+        null, null,
         /* ~ morekeys_v */
         // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
         /* morekeys_j */ "\u0135",
@@ -3935,72 +4112,75 @@
 
     private static final Object[] LOCALES_AND_TEXTS = {
     // "locale", TEXT_ARRAY,  /* numberOfNonNullText/lengthOf_TEXT_ARRAY localeName */
-        "DEFAULT", TEXTS_DEFAULT, /* 168/168 DEFAULT */
+        "DEFAULT", TEXTS_DEFAULT, /* 176/176 DEFAULT */
         "af"     , TEXTS_af,    /*   7/ 13 Afrikaans */
         "ar"     , TEXTS_ar,    /*  55/110 Arabic */
-        "az_AZ"  , TEXTS_az_AZ, /*   8/ 18 Azerbaijani (Azerbaijan) */
+        "az_AZ"  , TEXTS_az_AZ, /*  11/ 18 Azerbaijani (Azerbaijan) */
         "be_BY"  , TEXTS_be_BY, /*   9/ 32 Belarusian (Belarus) */
-        "bg"     , TEXTS_bg,    /*   2/  8 Bulgarian */
+        "bg"     , TEXTS_bg,    /*   2/  9 Bulgarian */
+        "bn_BD"  , TEXTS_bn_BD, /*   2/ 12 Bengali (Bangladesh) */
         "bn_IN"  , TEXTS_bn_IN, /*   2/ 12 Bengali (India) */
-        "ca"     , TEXTS_ca,    /*  11/ 96 Catalan */
+        "ca"     , TEXTS_ca,    /*  11/ 99 Catalan */
         "cs"     , TEXTS_cs,    /*  17/ 21 Czech */
-        "da"     , TEXTS_da,    /*  19/ 54 Danish */
-        "de"     , TEXTS_de,    /*  16/ 62 German */
-        "el"     , TEXTS_el,    /*   1/  4 Greek */
-        "en"     , TEXTS_en,    /*   8/ 11 English */
-        "eo"     , TEXTS_eo,    /*  26/118 Esperanto */
-        "es"     , TEXTS_es,    /*   8/ 55 Spanish */
+        "da"     , TEXTS_da,    /*  19/ 55 Danish */
+        "de"     , TEXTS_de,    /*  16/ 66 German */
+        "el"     , TEXTS_el,    /*   1/  5 Greek */
+        "en"     , TEXTS_en,    /*   8/ 10 English */
+        "eo"     , TEXTS_eo,    /*  26/126 Esperanto */
+        "es"     , TEXTS_es,    /*   8/ 56 Spanish */
         "et_EE"  , TEXTS_et_EE, /*  22/ 27 Estonian (Estonia) */
-        "eu_ES"  , TEXTS_eu_ES, /*   7/  9 Basque (Spain) */
-        "fa"     , TEXTS_fa,    /*  58/125 Persian */
-        "fi"     , TEXTS_fi,    /*  10/ 54 Finnish */
-        "fr"     , TEXTS_fr,    /*  13/ 62 French */
-        "gl_ES"  , TEXTS_gl_ES, /*   7/  9 Gallegan (Spain) */
-        "hi"     , TEXTS_hi,    /*  23/ 53 Hindi */
+        "eu_ES"  , TEXTS_eu_ES, /*   7/  8 Basque (Spain) */
+        "fa"     , TEXTS_fa,    /*  58/133 Persian */
+        "fi"     , TEXTS_fi,    /*  10/ 55 Finnish */
+        "fr"     , TEXTS_fr,    /*  13/ 66 French */
+        "gl_ES"  , TEXTS_gl_ES, /*   7/  8 Gallegan (Spain) */
+        "hi"     , TEXTS_hi,    /*  27/ 60 Hindi */
+        "hi_ZZ"  , TEXTS_hi_ZZ, /*   9/118 Hindi (ZZ) */
         "hr"     , TEXTS_hr,    /*   9/ 20 Croatian */
         "hu"     , TEXTS_hu,    /*   9/ 20 Hungarian */
-        "hy_AM"  , TEXTS_hy_AM, /*   9/126 Armenian (Armenia) */
+        "hy_AM"  , TEXTS_hy_AM, /*   9/134 Armenian (Armenia) */
         "is"     , TEXTS_is,    /*  10/ 16 Icelandic */
-        "it"     , TEXTS_it,    /*  11/ 62 Italian */
-        "iw"     , TEXTS_iw,    /*  20/123 Hebrew */
-        "ka_GE"  , TEXTS_ka_GE, /*   3/ 10 Georgian (Georgia) */
-        "kk"     , TEXTS_kk,    /*  15/121 Kazakh */
-        "km_KH"  , TEXTS_km_KH, /*   2/122 Khmer (Cambodia) */
+        "it"     , TEXTS_it,    /*  11/ 66 Italian */
+        "iw"     , TEXTS_iw,    /*  20/131 Hebrew */
+        "ka_GE"  , TEXTS_ka_GE, /*   3/ 11 Georgian (Georgia) */
+        "kk"     , TEXTS_kk,    /*  15/129 Kazakh */
+        "km_KH"  , TEXTS_km_KH, /*   2/130 Khmer (Cambodia) */
         "kn_IN"  , TEXTS_kn_IN, /*   2/ 12 Kannada (India) */
-        "ky"     , TEXTS_ky,    /*  10/ 89 Kirghiz */
+        "ky"     , TEXTS_ky,    /*  10/ 92 Kirghiz */
         "lo_LA"  , TEXTS_lo_LA, /*   2/ 12 Lao (Laos) */
         "lt"     , TEXTS_lt,    /*  18/ 22 Lithuanian */
         "lv"     , TEXTS_lv,    /*  18/ 22 Latvian */
-        "mk"     , TEXTS_mk,    /*   9/ 94 Macedonian */
+        "mk"     , TEXTS_mk,    /*   9/ 97 Macedonian */
         "ml_IN"  , TEXTS_ml_IN, /*   2/ 12 Malayalam (India) */
         "mn_MN"  , TEXTS_mn_MN, /*   2/ 12 Mongolian (Mongolia) */
         "mr_IN"  , TEXTS_mr_IN, /*  23/ 53 Marathi (India) */
-        "my_MM"  , TEXTS_my_MM, /*   8/104 Burmese (Myanmar) */
-        "nb"     , TEXTS_nb,    /*  11/ 54 Norwegian Bokmål */
-        "ne_NP"  , TEXTS_ne_NP, /*  23/ 53 Nepali (Nepal) */
+        "nb"     , TEXTS_nb,    /*  11/ 55 Norwegian Bokmål */
+        "ne_NP"  , TEXTS_ne_NP, /*  27/ 60 Nepali (Nepal) */
         "nl"     , TEXTS_nl,    /*   9/ 13 Dutch */
         "pl"     , TEXTS_pl,    /*  10/ 17 Polish */
-        "pt"     , TEXTS_pt,    /*   6/  7 Portuguese */
+        "pt"     , TEXTS_pt,    /*   6/  8 Portuguese */
         "rm"     , TEXTS_rm,    /*   1/  2 Raeto-Romance */
         "ro"     , TEXTS_ro,    /*   6/ 16 Romanian */
         "ru"     , TEXTS_ru,    /*   9/ 32 Russian */
         "si_LK"  , TEXTS_si_LK, /*   2/ 12 Sinhalese (Sri Lanka) */
         "sk"     , TEXTS_sk,    /*  20/ 22 Slovak */
         "sl"     , TEXTS_sl,    /*   8/ 20 Slovenian */
-        "sr"     , TEXTS_sr,    /*  11/ 94 Serbian */
-        "sv"     , TEXTS_sv,    /*  21/ 54 Swedish */
+        "sr"     , TEXTS_sr,    /*  11/ 97 Serbian */
+        "sr_ZZ"  , TEXTS_sr_ZZ, /*  14/118 Serbian (ZZ) */
+        "sv"     , TEXTS_sv,    /*  21/ 55 Swedish */
         "sw"     , TEXTS_sw,    /*   9/ 18 Swahili */
         "ta_IN"  , TEXTS_ta_IN, /*   2/ 12 Tamil (India) */
         "ta_LK"  , TEXTS_ta_LK, /*   2/ 12 Tamil (Sri Lanka) */
-        "ta_SG"  , TEXTS_ta_SG, /*   1/  4 Tamil (Singapore) */
+        "ta_SG"  , TEXTS_ta_SG, /*   1/  5 Tamil (Singapore) */
         "te_IN"  , TEXTS_te_IN, /*   2/ 12 Telugu (India) */
         "th"     , TEXTS_th,    /*   2/ 12 Thai */
-        "tl"     , TEXTS_tl,    /*   7/  9 Tagalog */
-        "tr"     , TEXTS_tr,    /*   7/ 18 Turkish */
-        "uk"     , TEXTS_uk,    /*  11/ 88 Ukrainian */
-        "vi"     , TEXTS_vi,    /*   8/ 14 Vietnamese */
-        "zu"     , TEXTS_zu,    /*   8/ 11 Zulu */
-        "zz"     , TEXTS_zz,    /*  19/112 Alphabet */
+        "tl"     , TEXTS_tl,    /*   7/  8 Tagalog */
+        "tr"     , TEXTS_tr,    /*  11/ 18 Turkish */
+        "uk"     , TEXTS_uk,    /*  11/ 91 Ukrainian */
+        "uz_UZ"  , TEXTS_uz_UZ, /*  11/ 18 Uzbek (Uzbekistan) */
+        "vi"     , TEXTS_vi,    /*   8/ 15 Vietnamese */
+        "zu"     , TEXTS_zu,    /*   8/ 10 Zulu */
+        "zz"     , TEXTS_zz,    /*  19/120 Alphabet */
     };
 
     static {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java b/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java
deleted file mode 100644
index 7743d47..0000000
--- a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 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.internal;
-
-import com.android.inputmethod.keyboard.Key;
-
-import java.util.HashMap;
-
-public final class KeysCache {
-    private final HashMap<Key, Key> mMap = new HashMap<>();
-
-    public void clear() {
-        mMap.clear();
-    }
-
-    public Key get(final Key key) {
-        final Key existingKey = mMap.get(key);
-        if (existingKey != null) {
-            // Reuse the existing element that equals to "key" without adding "key" to the map.
-            return existingKey;
-        }
-        mMap.put(key, key);
-        return key;
-    }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java b/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java
deleted file mode 100644
index 6400a24..0000000
--- a/java/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2014 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.internal;
-
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * This class determines that the language name on the spacebar should be displayed in what format.
- */
-public final class LanguageOnSpacebarHelper {
-    public static final int FORMAT_TYPE_NONE = 0;
-    public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1;
-    public static final int FORMAT_TYPE_FULL_LOCALE = 2;
-
-    private List<InputMethodSubtype> mEnabledSubtypes = Collections.emptyList();
-    private boolean mIsSystemLanguageSameAsInputLanguage;
-
-    public int getLanguageOnSpacebarFormatType(final InputMethodSubtype subtype) {
-        if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
-            return FORMAT_TYPE_FULL_LOCALE;
-        }
-        // Only this subtype is enabled and equals to the system locale.
-        if (mEnabledSubtypes.size() < 2 && mIsSystemLanguageSameAsInputLanguage) {
-            return FORMAT_TYPE_NONE;
-        }
-        final String keyboardLanguage = SubtypeLocaleUtils.getSubtypeLocale(subtype).getLanguage();
-        final String keyboardLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
-        int sameLanguageAndLayoutCount = 0;
-        for (final InputMethodSubtype ims : mEnabledSubtypes) {
-            final String language = SubtypeLocaleUtils.getSubtypeLocale(ims).getLanguage();
-            if (keyboardLanguage.equals(language) && keyboardLayout.equals(
-                    SubtypeLocaleUtils.getKeyboardLayoutSetName(ims))) {
-                sameLanguageAndLayoutCount++;
-            }
-        }
-        // Display full locale name only when there are multiple subtypes that have the same
-        // locale and keyboard layout. Otherwise displaying language name is enough.
-        return sameLanguageAndLayoutCount > 1 ? FORMAT_TYPE_FULL_LOCALE
-                : FORMAT_TYPE_LANGUAGE_ONLY;
-    }
-
-    public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
-        mEnabledSubtypes = enabledSubtypes;
-    }
-
-    public void updateIsSystemLanguageSameAsInputLanguage(final boolean isSame) {
-        mIsSystemLanguageSameAsInputLanguage = isSame;
-    }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
index c1f3749..d927cc3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
@@ -28,7 +28,8 @@
  */
 @UsedForTesting
 public class MatrixUtils {
-    private static final String TAG = MatrixUtils.class.getSimpleName();
+    static final String TAG = MatrixUtils.class.getSimpleName();
+
     public static class MatrixOperationFailedException extends Exception {
         private static final long serialVersionUID = 4384485606788583829L;
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
index 625a0c2..0bd42fc 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java
@@ -17,17 +17,21 @@
 package com.android.inputmethod.keyboard.internal;
 
 import android.text.TextUtils;
+import android.util.SparseIntArray;
 
+import com.android.inputmethod.compat.CharacterCompat;
 import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.CollectionUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.CollectionUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * The more key specification object. The more keys are an array of {@link MoreKeySpec}.
  *
@@ -42,18 +46,22 @@
 // TODO: Should extend the key specification object.
 public final class MoreKeySpec {
     public final int mCode;
+    @Nullable
     public final String mLabel;
+    @Nullable
     public final String mOutputText;
     public final int mIconId;
 
-    public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, final Locale locale) {
-        if (TextUtils.isEmpty(moreKeySpec)) {
+    public MoreKeySpec(@Nonnull final String moreKeySpec, boolean needsToUpperCase,
+            @Nonnull final Locale locale) {
+        if (moreKeySpec.isEmpty()) {
             throw new KeySpecParser.KeySpecParserError("Empty more key spec");
         }
-        mLabel = StringUtils.toUpperCaseOfStringForLocale(
-                KeySpecParser.getLabel(moreKeySpec), needsToUpperCase, locale);
-        final int code = StringUtils.toUpperCaseOfCodeForLocale(
-                KeySpecParser.getCode(moreKeySpec), needsToUpperCase, locale);
+        final String label = KeySpecParser.getLabel(moreKeySpec);
+        mLabel = needsToUpperCase ? StringUtils.toTitleCaseOfKeyLabel(label, locale) : label;
+        final int codeInSpec = KeySpecParser.getCode(moreKeySpec);
+        final int code = needsToUpperCase ? StringUtils.toTitleCaseOfKeyCode(codeInSpec, locale)
+                : codeInSpec;
         if (code == Constants.CODE_UNSPECIFIED) {
             // Some letter, for example German Eszett (U+00DF: "ß"), has multiple characters
             // upper case representation ("SS").
@@ -61,14 +69,16 @@
             mOutputText = mLabel;
         } else {
             mCode = code;
-            mOutputText = StringUtils.toUpperCaseOfStringForLocale(
-                    KeySpecParser.getOutputText(moreKeySpec), needsToUpperCase, locale);
+            final String outputText = KeySpecParser.getOutputText(moreKeySpec);
+            mOutputText = needsToUpperCase
+                    ? StringUtils.toTitleCaseOfKeyLabel(outputText, locale) : outputText;
         }
         mIconId = KeySpecParser.getIconId(moreKeySpec);
     }
 
+    @Nonnull
     public Key buildKey(final int x, final int y, final int labelFlags,
-            final KeyboardParams params) {
+            @Nonnull final KeyboardParams params) {
         return new Key(mLabel, mIconId, mCode, mOutputText, null /* hintLabel */, labelFlags,
                 Key.BACKGROUND_TYPE_NORMAL, x, y, params.mDefaultKeyWidth, params.mDefaultRowHeight,
                 params.mHorizontalGap, params.mVerticalGap);
@@ -79,14 +89,18 @@
         int hashCode = 1;
         hashCode = 31 + mCode;
         hashCode = hashCode * 31 + mIconId;
-        hashCode = hashCode * 31 + (mLabel == null ? 0 : mLabel.hashCode());
-        hashCode = hashCode * 31 + (mOutputText == null ? 0 : mOutputText.hashCode());
+        final String label = mLabel;
+        hashCode = hashCode * 31 + (label == null ? 0 : label.hashCode());
+        final String outputText = mOutputText;
+        hashCode = hashCode * 31 + (outputText == null ? 0 : outputText.hashCode());
         return hashCode;
     }
 
     @Override
     public boolean equals(final Object o) {
-        if (this == o) return true;
+        if (this == o) {
+            return true;
+        }
         if (o instanceof MoreKeySpec) {
             final MoreKeySpec other = (MoreKeySpec)o;
             return mCode == other.mCode
@@ -105,12 +119,56 @@
                 : Constants.printableCode(mCode));
         if (StringUtils.codePointCount(label) == 1 && label.codePointAt(0) == mCode) {
             return output;
-        } else {
-            return label + "|" + output;
+        }
+        return label + "|" + output;
+    }
+
+    public static class LettersOnBaseLayout {
+        private final SparseIntArray mCodes = new SparseIntArray();
+        private final HashSet<String> mTexts = new HashSet<>();
+
+        public void addLetter(@Nonnull final Key key) {
+            final int code = key.getCode();
+            if (CharacterCompat.isAlphabetic(code)) {
+                mCodes.put(code, 0);
+            } else if (code == Constants.CODE_OUTPUT_TEXT) {
+                mTexts.add(key.getOutputText());
+            }
+        }
+
+        public boolean contains(@Nonnull final MoreKeySpec moreKey) {
+            final int code = moreKey.mCode;
+            if (CharacterCompat.isAlphabetic(code) && mCodes.indexOfKey(code) >= 0) {
+                return true;
+            } else if (code == Constants.CODE_OUTPUT_TEXT && mTexts.contains(moreKey.mOutputText)) {
+                return true;
+            }
+            return false;
         }
     }
 
-    private static final boolean DEBUG = DebugFlags.DEBUG_ENABLED;
+    @Nullable
+    public static MoreKeySpec[] removeRedundantMoreKeys(@Nullable final MoreKeySpec[] moreKeys,
+            @Nonnull final LettersOnBaseLayout lettersOnBaseLayout) {
+        if (moreKeys == null) {
+            return null;
+        }
+        final ArrayList<MoreKeySpec> filteredMoreKeys = new ArrayList<>();
+        for (final MoreKeySpec moreKey : moreKeys) {
+            if (!lettersOnBaseLayout.contains(moreKey)) {
+                filteredMoreKeys.add(moreKey);
+            }
+        }
+        final int size = filteredMoreKeys.size();
+        if (size == moreKeys.length) {
+            return moreKeys;
+        }
+        if (size == 0) {
+            return null;
+        }
+        return filteredMoreKeys.toArray(new MoreKeySpec[size]);
+    }
+
     // Constants for parsing.
     private static final char COMMA = Constants.CODE_COMMA;
     private static final char BACKSLASH = Constants.CODE_BACKSLASH;
@@ -128,7 +186,8 @@
      * @return an array of key specification text. Null if the specified <code>text</code> is empty
      * or has no key specifications.
      */
-    public static String[] splitKeySpecs(final String text) {
+    @Nullable
+    public static String[] splitKeySpecs(@Nullable final String text) {
         if (TextUtils.isEmpty(text)) {
             return null;
         }
@@ -170,9 +229,11 @@
         return list.toArray(new String[list.size()]);
     }
 
+    @Nonnull
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
-    private static String[] filterOutEmptyString(final String[] array) {
+    @Nonnull
+    private static String[] filterOutEmptyString(@Nullable final String[] array) {
         if (array == null) {
             return EMPTY_STRING_ARRAY;
         }
@@ -193,8 +254,8 @@
         return out.toArray(new String[out.size()]);
     }
 
-    public static String[] insertAdditionalMoreKeys(final String[] moreKeySpecs,
-            final String[] additionalMoreKeySpecs) {
+    public static String[] insertAdditionalMoreKeys(@Nullable final String[] moreKeySpecs,
+            @Nullable final String[] additionalMoreKeySpecs) {
         final String[] moreKeys = filterOutEmptyString(moreKeySpecs);
         final String[] additionalMoreKeys = filterOutEmptyString(additionalMoreKeySpecs);
         final int moreKeysCount = moreKeys.length;
@@ -228,11 +289,6 @@
         if (additionalCount > 0 && additionalIndex == 0) {
             // No '%' marker is found in more keys.
             // Insert all additional more keys to the head of more keys.
-            if (DEBUG && out != null) {
-                throw new RuntimeException("Internal logic error:"
-                        + " moreKeys=" + Arrays.toString(moreKeys)
-                        + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
-            }
             out = CollectionUtils.arrayAsList(additionalMoreKeys, additionalIndex, additionalCount);
             for (int i = 0; i < moreKeysCount; i++) {
                 out.add(moreKeys[i]);
@@ -240,11 +296,6 @@
         } else if (additionalIndex < additionalCount) {
             // The number of '%' markers are less than additional more keys.
             // Append remained additional more keys to the tail of more keys.
-            if (DEBUG && out != null) {
-                throw new RuntimeException("Internal logic error:"
-                        + " moreKeys=" + Arrays.toString(moreKeys)
-                        + " additionalMoreKeys=" + Arrays.toString(additionalMoreKeys));
-            }
             out = CollectionUtils.arrayAsList(moreKeys, 0, moreKeysCount);
             for (int i = additionalIndex; i < additionalCount; i++) {
                 out.add(additionalMoreKeys[additionalIndex]);
@@ -259,7 +310,7 @@
         }
     }
 
-    public static int getIntValue(final String[] moreKeys, final String key,
+    public static int getIntValue(@Nullable final String[] moreKeys, final String key,
             final int defaultValue) {
         if (moreKeys == null) {
             return defaultValue;
@@ -286,7 +337,7 @@
         return value;
     }
 
-    public static boolean getBooleanValue(final String[] moreKeys, final String key) {
+    public static boolean getBooleanValue(@Nullable final String[] moreKeys, final String key) {
         if (moreKeys == null) {
             return false;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
index 3a9aa81..8a375c6 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/NonDistinctMultitouchHelper.java
@@ -22,7 +22,7 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.KeyDetector;
 import com.android.inputmethod.keyboard.PointerTracker;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 
 public final class NonDistinctMultitouchHelper {
     private static final String TAG = NonDistinctMultitouchHelper.class.getSimpleName();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index 8e89e61e..556d74f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -95,7 +95,7 @@
     public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) {
         synchronized (mExpandableArrayOfActivePointers) {
             if (DEBUG) {
-                Log.d(TAG, "releaseAllPoniterOlderThan: " + pointer + " " + this);
+                Log.d(TAG, "releaseAllPointerOlderThan: " + pointer + " " + this);
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
@@ -144,9 +144,9 @@
         synchronized (mExpandableArrayOfActivePointers) {
             if (DEBUG) {
                 if (pointer == null) {
-                    Log.d(TAG, "releaseAllPoniters: " + this);
+                    Log.d(TAG, "releaseAllPointers: " + this);
                 } else {
-                    Log.d(TAG, "releaseAllPoniterExcept: " + pointer + " " + this);
+                    Log.d(TAG, "releaseAllPointerExcept: " + pointer + " " + this);
                 }
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
index ef4c74d..73a6f95 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/SlidingKeyInputDrawingPreview.java
@@ -23,7 +23,7 @@
 
 import com.android.inputmethod.keyboard.PointerTracker;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
+import com.android.inputmethod.latin.common.CoordinateUtils;
 
 /**
  * Draw rubber band preview graphics during sliding key input.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
index ec7b9b0..91f3558 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TimerHandler.java
@@ -22,31 +22,27 @@
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.PointerTracker;
-import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
-import com.android.inputmethod.keyboard.internal.TimerHandler.Callbacks;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
 
-// TODO: Separate this class into KeyTimerHandler and BatchInputTimerHandler or so.
-public final class TimerHandler extends LeakGuardHandlerWrapper<Callbacks> implements TimerProxy {
-    public interface Callbacks {
-        public void startWhileTypingFadeinAnimation();
-        public void startWhileTypingFadeoutAnimation();
-        public void onLongPress(PointerTracker tracker);
-    }
+import javax.annotation.Nonnull;
 
+public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy>
+        implements TimerProxy {
     private static final int MSG_TYPING_STATE_EXPIRED = 0;
     private static final int MSG_REPEAT_KEY = 1;
     private static final int MSG_LONGPRESS_KEY = 2;
     private static final int MSG_LONGPRESS_SHIFT_KEY = 3;
     private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 4;
     private static final int MSG_UPDATE_BATCH_INPUT = 5;
+    private static final int MSG_DISMISS_KEY_PREVIEW = 6;
+    private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 7;
 
     private final int mIgnoreAltCodeKeyTimeout;
     private final int mGestureRecognitionUpdateTime;
 
-    public TimerHandler(final Callbacks ownerInstance, final int ignoreAltCodeKeyTimeout,
-            final int gestureRecognitionUpdateTime) {
+    public TimerHandler(@Nonnull final DrawingProxy ownerInstance,
+            final int ignoreAltCodeKeyTimeout, final int gestureRecognitionUpdateTime) {
         super(ownerInstance);
         mIgnoreAltCodeKeyTimeout = ignoreAltCodeKeyTimeout;
         mGestureRecognitionUpdateTime = gestureRecognitionUpdateTime;
@@ -54,32 +50,40 @@
 
     @Override
     public void handleMessage(final Message msg) {
-        final Callbacks callbacks = getOwnerInstance();
-        if (callbacks == null) {
+        final DrawingProxy drawingProxy = getOwnerInstance();
+        if (drawingProxy == null) {
             return;
         }
-        final PointerTracker tracker = (PointerTracker) msg.obj;
         switch (msg.what) {
         case MSG_TYPING_STATE_EXPIRED:
-            callbacks.startWhileTypingFadeinAnimation();
+            drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_IN);
             break;
         case MSG_REPEAT_KEY:
-            tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */);
+            final PointerTracker tracker1 = (PointerTracker) msg.obj;
+            tracker1.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */);
             break;
         case MSG_LONGPRESS_KEY:
         case MSG_LONGPRESS_SHIFT_KEY:
             cancelLongPressTimers();
-            callbacks.onLongPress(tracker);
+            final PointerTracker tracker2 = (PointerTracker) msg.obj;
+            tracker2.onLongPressed();
             break;
         case MSG_UPDATE_BATCH_INPUT:
-            tracker.updateBatchInputByTimer(SystemClock.uptimeMillis());
-            startUpdateBatchInputTimer(tracker);
+            final PointerTracker tracker3 = (PointerTracker) msg.obj;
+            tracker3.updateBatchInputByTimer(SystemClock.uptimeMillis());
+            startUpdateBatchInputTimer(tracker3);
+            break;
+        case MSG_DISMISS_KEY_PREVIEW:
+            drawingProxy.onKeyReleased((Key) msg.obj, false /* withAnimation */);
+            break;
+        case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
+            drawingProxy.dismissGestureFloatingPreviewTextWithoutDelay();
             break;
         }
     }
 
     @Override
-    public void startKeyRepeatTimerOf(final PointerTracker tracker, final int repeatCount,
+    public void startKeyRepeatTimerOf(@Nonnull final PointerTracker tracker, final int repeatCount,
             final int delay) {
         final Key key = tracker.getKey();
         if (key == null || delay == 0) {
@@ -103,7 +107,7 @@
     }
 
     @Override
-    public void startLongPressTimerOf(final PointerTracker tracker, final int delay) {
+    public void startLongPressTimerOf(@Nonnull final PointerTracker tracker, final int delay) {
         final Key key = tracker.getKey();
         if (key == null) {
             return;
@@ -116,13 +120,13 @@
     }
 
     @Override
-    public void cancelLongPressTimerOf(final PointerTracker tracker) {
+    public void cancelLongPressTimersOf(@Nonnull final PointerTracker tracker) {
         removeMessages(MSG_LONGPRESS_KEY, tracker);
         removeMessages(MSG_LONGPRESS_SHIFT_KEY, tracker);
     }
 
     @Override
-    public void cancelLongPressShiftKeyTimers() {
+    public void cancelLongPressShiftKeyTimer() {
         removeMessages(MSG_LONGPRESS_SHIFT_KEY);
     }
 
@@ -132,15 +136,15 @@
     }
 
     @Override
-    public void startTypingStateTimer(final Key typedKey) {
+    public void startTypingStateTimer(@Nonnull final Key typedKey) {
         if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) {
             return;
         }
 
         final boolean isTyping = isTypingState();
         removeMessages(MSG_TYPING_STATE_EXPIRED);
-        final Callbacks callbacks = getOwnerInstance();
-        if (callbacks == null) {
+        final DrawingProxy drawingProxy = getOwnerInstance();
+        if (drawingProxy == null) {
             return;
         }
 
@@ -148,7 +152,7 @@
         final int typedCode = typedKey.getCode();
         if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) {
             if (isTyping) {
-                callbacks.startWhileTypingFadeinAnimation();
+                drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_IN);
             }
             return;
         }
@@ -158,7 +162,7 @@
         if (isTyping) {
             return;
         }
-        callbacks.startWhileTypingFadeoutAnimation();
+        drawingProxy.startWhileTypingAnimation(DrawingProxy.FADE_OUT);
     }
 
     @Override
@@ -183,9 +187,9 @@
     }
 
     @Override
-    public void cancelKeyTimersOf(final PointerTracker tracker) {
+    public void cancelKeyTimersOf(@Nonnull final PointerTracker tracker) {
         cancelKeyRepeatTimerOf(tracker);
-        cancelLongPressTimerOf(tracker);
+        cancelLongPressTimersOf(tracker);
     }
 
     public void cancelAllKeyTimers() {
@@ -194,7 +198,7 @@
     }
 
     @Override
-    public void startUpdateBatchInputTimer(final PointerTracker tracker) {
+    public void startUpdateBatchInputTimer(@Nonnull final PointerTracker tracker) {
         if (mGestureRecognitionUpdateTime <= 0) {
             return;
         }
@@ -204,7 +208,7 @@
     }
 
     @Override
-    public void cancelUpdateBatchInputTimer(final PointerTracker tracker) {
+    public void cancelUpdateBatchInputTimer(@Nonnull final PointerTracker tracker) {
         removeMessages(MSG_UPDATE_BATCH_INPUT, tracker);
     }
 
@@ -213,8 +217,18 @@
         removeMessages(MSG_UPDATE_BATCH_INPUT);
     }
 
+    public void postDismissKeyPreview(@Nonnull final Key key, final long delay) {
+        sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, key), delay);
+    }
+
+    public void postDismissGestureFloatingPreviewText(final long delay) {
+        sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay);
+    }
+
     public void cancelAllMessages() {
         cancelAllKeyTimers();
         cancelAllUpdateBatchInputTimers();
+        removeMessages(MSG_DISMISS_KEY_PREVIEW);
+        removeMessages(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT);
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TimerProxy.java b/java/src/com/android/inputmethod/keyboard/internal/TimerProxy.java
new file mode 100644
index 0000000..0ce3de8
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/TimerProxy.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.PointerTracker;
+
+import javax.annotation.Nonnull;
+
+public interface TimerProxy {
+    /**
+     * Start a timer to detect if a user is typing keys.
+     * @param typedKey the key that is typed.
+     */
+    public void startTypingStateTimer(@Nonnull Key typedKey);
+
+    /**
+     * Check if a user is key typing.
+     * @return true if a user is in typing.
+     */
+    public boolean isTypingState();
+
+    /**
+     * Start a timer to simulate repeated key presses while a user keep pressing a key.
+     * @param tracker the {@link PointerTracker} that points the key to be repeated.
+     * @param repeatCount the number of times that the key is repeating. Starting from 1.
+     * @param delay the interval delay to the next key repeat, in millisecond.
+     */
+    public void startKeyRepeatTimerOf(@Nonnull PointerTracker tracker, int repeatCount, int delay);
+
+    /**
+     * Start a timer to detect a long pressed key.
+     * If a key pointed by <code>tracker</code> is a shift key, start another timer to detect
+     * long pressed shift key.
+     * @param tracker the {@link PointerTracker} that starts long pressing.
+     * @param delay the delay to fire the long press timer, in millisecond.
+     */
+    public void startLongPressTimerOf(@Nonnull PointerTracker tracker, int delay);
+
+    /**
+     * Cancel timers for detecting a long pressed key and a long press shift key.
+     * @param tracker cancel long press timers of this {@link PointerTracker}.
+     */
+    public void cancelLongPressTimersOf(@Nonnull PointerTracker tracker);
+
+    /**
+     * Cancel a timer for detecting a long pressed shift key.
+     */
+    public void cancelLongPressShiftKeyTimer();
+
+    /**
+     * Cancel timers for detecting repeated key press, long pressed key, and long pressed shift key.
+     * @param tracker the {@link PointerTracker} that starts timers to be canceled.
+     */
+    public void cancelKeyTimersOf(@Nonnull PointerTracker tracker);
+
+    /**
+     * Start a timer to detect double tapped shift key.
+     */
+    public void startDoubleTapShiftKeyTimer();
+
+    /**
+     * Cancel a timer of detecting double tapped shift key.
+     */
+    public void cancelDoubleTapShiftKeyTimer();
+
+    /**
+     * Check if a timer of detecting double tapped shift key is running.
+     * @return true if detecting double tapped shift key is on going.
+     */
+    public boolean isInDoubleTapShiftKeyTimeout();
+
+    /**
+     * Start a timer to fire updating batch input while <code>tracker</code> is on hold.
+     * @param tracker the {@link PointerTracker} that stops moving.
+     */
+    public void startUpdateBatchInputTimer(@Nonnull PointerTracker tracker);
+
+    /**
+     * Cancel a timer of firing updating batch input.
+     * @param tracker the {@link PointerTracker} that resumes moving or ends gesture input.
+     */
+    public void cancelUpdateBatchInputTimer(@Nonnull PointerTracker tracker);
+
+    /**
+     * Cancel all timers of firing updating batch input.
+     */
+    public void cancelAllUpdateBatchInputTimers();
+
+    public static class Adapter implements TimerProxy {
+        @Override
+        public void startTypingStateTimer(@Nonnull Key typedKey) {}
+        @Override
+        public boolean isTypingState() { return false; }
+        @Override
+        public void startKeyRepeatTimerOf(@Nonnull PointerTracker tracker, int repeatCount,
+                int delay) {}
+        @Override
+        public void startLongPressTimerOf(@Nonnull PointerTracker tracker, int delay) {}
+        @Override
+        public void cancelLongPressTimersOf(@Nonnull PointerTracker tracker) {}
+        @Override
+        public void cancelLongPressShiftKeyTimer() {}
+        @Override
+        public void cancelKeyTimersOf(@Nonnull PointerTracker tracker) {}
+        @Override
+        public void startDoubleTapShiftKeyTimer() {}
+        @Override
+        public void cancelDoubleTapShiftKeyTimer() {}
+        @Override
+        public boolean isInDoubleTapShiftKeyTimeout() { return false; }
+        @Override
+        public void startUpdateBatchInputTimer(@Nonnull PointerTracker tracker) {}
+        @Override
+        public void cancelUpdateBatchInputTimer(@Nonnull PointerTracker tracker) {}
+        @Override
+        public void cancelAllUpdateBatchInputTimers() {}
+    }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
index fef97cc..d8f0114 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/TouchPositionCorrection.java
@@ -80,6 +80,7 @@
         return mRadii.length;
     }
 
+    @SuppressWarnings({ "static-method", "unused" })
     public float getX(final int row) {
         return 0.0f;
         // Touch position correction data for X coordinate is obsolete.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/UniqueKeysCache.java b/java/src/com/android/inputmethod/keyboard/internal/UniqueKeysCache.java
new file mode 100644
index 0000000..5b329dc
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/UniqueKeysCache.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import com.android.inputmethod.keyboard.Key;
+
+import java.util.HashMap;
+
+import javax.annotation.Nonnull;
+
+public abstract class UniqueKeysCache {
+    public abstract void setEnabled(boolean enabled);
+    public abstract void clear();
+    public abstract @Nonnull Key getUniqueKey(@Nonnull Key key);
+
+    @Nonnull
+    public static final UniqueKeysCache NO_CACHE = new UniqueKeysCache() {
+        @Override
+        public void setEnabled(boolean enabled) {}
+
+        @Override
+        public void clear() {}
+
+        @Override
+        public Key getUniqueKey(Key key) { return key; }
+    };
+
+    @Nonnull
+    public static UniqueKeysCache newInstance() {
+        return new UniqueKeysCacheImpl();
+    }
+
+    private static final class UniqueKeysCacheImpl extends UniqueKeysCache {
+        private final HashMap<Key, Key> mCache;
+
+        private boolean mEnabled;
+
+        UniqueKeysCacheImpl() {
+            mCache = new HashMap<>();
+        }
+
+        @Override
+        public void setEnabled(final boolean enabled) {
+            mEnabled = enabled;
+        }
+
+        @Override
+        public void clear() {
+            mCache.clear();
+        }
+
+        @Override
+        public Key getUniqueKey(final Key key) {
+            if (!mEnabled) {
+                return key;
+            }
+            final Key existingKey = mCache.get(key);
+            if (existingKey != null) {
+                // Reuse the existing object that equals to "key" without adding "key" to
+                // the cache.
+                return existingKey;
+            }
+            mCache.put(key, key);
+            return key;
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index fd6c24d..f8d02d6 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.latin;
 
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
 
 import java.io.File;
 
@@ -62,4 +62,9 @@
     public void deleteUnderlyingFile() {
         FileUtils.deleteRecursively(new File(mFilename));
     }
+
+    @Override
+    public String toString() {
+        return String.format("%s (offset=%d, length=%d)", mFilename, mOffset, mLength);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
index eb8b34c..60d2573 100644
--- a/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
+++ b/java/src/com/android/inputmethod/latin/AudioAndHapticFeedbackManager.java
@@ -22,6 +22,7 @@
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.settings.SettingsValues;
 
 /**
diff --git a/java/src/com/android/inputmethod/latin/BackupAgent.java b/java/src/com/android/inputmethod/latin/BackupAgent.java
index 1f04461..b2d92b3 100644
--- a/java/src/com/android/inputmethod/latin/BackupAgent.java
+++ b/java/src/com/android/inputmethod/latin/BackupAgent.java
@@ -17,15 +17,41 @@
 package com.android.inputmethod.latin;
 
 import android.app.backup.BackupAgentHelper;
+import android.app.backup.BackupDataInput;
 import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.SharedPreferences;
+import android.os.ParcelFileDescriptor;
+
+import com.android.inputmethod.latin.settings.LocalSettingsConstants;
+
+import java.io.IOException;
 
 /**
- * Backs up the Latin IME shared preferences.
+ * Backup/restore agent for LatinIME.
+ * Currently it backs up the default shared preferences.
  */
 public final class BackupAgent extends BackupAgentHelper {
+    private static final String PREF_SUFFIX = "_preferences";
+
     @Override
     public void onCreate() {
         addHelper("shared_pref", new SharedPreferencesBackupHelper(this,
-                getPackageName() + "_preferences"));
+                getPackageName() + PREF_SUFFIX));
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        // Let the restore operation go through
+        super.onRestore(data, appVersionCode, newState);
+
+        // Remove the preferences that we don't want restored.
+        final SharedPreferences.Editor prefEditor = getSharedPreferences(
+                getPackageName() + PREF_SUFFIX, MODE_PRIVATE).edit();
+        for (final String key : LocalSettingsConstants.PREFS_TO_SKIP_RESTORING) {
+            prefEditor.remove(key);
+        }
+        // Flush the changes to disk.
+        prefEditor.commit();
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 693e1cd..9a3ac67 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -21,8 +21,12 @@
 import android.util.SparseArray;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.FileUtils;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
@@ -30,10 +34,8 @@
 import com.android.inputmethod.latin.makedict.WordProperty;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
 import com.android.inputmethod.latin.utils.JniUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -42,6 +44,8 @@
 import java.util.Locale;
 import java.util.Map;
 
+import javax.annotation.Nonnull;
+
 /**
  * Implements a static, compacted, binary dictionary of standard words.
  */
@@ -53,6 +57,9 @@
     // Must be equal to CONFIDENCE_TO_AUTO_COMMIT in native/jni/src/defines.h
     private static final int CONFIDENCE_TO_AUTO_COMMIT = 1000000;
 
+    public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
+    public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 3;
+
     @UsedForTesting
     public static final String UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
     @UsedForTesting
@@ -67,9 +74,9 @@
     // Format to get unigram flags from native side via getWordPropertyNative().
     private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5;
     private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
-    private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1;
-    private static final int FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX = 2;
-    private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+    private static final int FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX = 1;
+    private static final int FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX = 2;
+    private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3; // DEPRECATED
     private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
 
     // Format to get probability and historical info from native side via getWordPropertyNative().
@@ -83,7 +90,6 @@
     public static final String DIR_NAME_SUFFIX_FOR_RECORD_MIGRATION = ".migrating";
 
     private long mNativeDict;
-    private final Locale mLocale;
     private final long mDictSize;
     private final String mDictFilePath;
     private final boolean mUseFullEditDistance;
@@ -117,8 +123,7 @@
     public BinaryDictionary(final String filename, final long offset, final long length,
             final boolean useFullEditDistance, final Locale locale, final String dictType,
             final boolean isUpdatable) {
-        super(dictType);
-        mLocale = locale;
+        super(dictType, locale);
         mDictSize = length;
         mDictFilePath = filename;
         mIsUpdatable = isUpdatable;
@@ -138,8 +143,7 @@
     public BinaryDictionary(final String filename, final boolean useFullEditDistance,
             final Locale locale, final String dictType, final long formatVersion,
             final Map<String, String> attributeMap) {
-        super(dictType);
-        mLocale = locale;
+        super(dictType, locale);
         mDictSize = 0;
         mDictFilePath = filename;
         // On memory dictionary is always updatable.
@@ -180,36 +184,41 @@
             boolean[] isBeginningOfSentenceArray, int[] word);
     private static native void getWordPropertyNative(long dict, int[] word,
             boolean isBeginningOfSentence, int[] outCodePoints, boolean[] outFlags,
-            int[] outProbabilityInfo, ArrayList<int[]> outBigramTargets,
-            ArrayList<int[]> outBigramProbabilityInfo, ArrayList<int[]> outShortcutTargets,
-            ArrayList<Integer> outShortcutProbabilities);
+            int[] outProbabilityInfo, ArrayList<int[][]> outNgramPrevWordsArray,
+            ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray,
+            ArrayList<int[]> outNgramTargets, ArrayList<int[]> outNgramProbabilityInfo,
+            ArrayList<int[]> outShortcutTargets, ArrayList<Integer> outShortcutProbabilities);
     private static native int getNextWordNative(long dict, int token, int[] outCodePoints,
             boolean[] outIsBeginningOfSentence);
     private static native void getSuggestionsNative(long dict, long proximityInfo,
             long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times,
             int[] pointerIds, int[] inputCodePoints, int inputSize, int[] suggestOptions,
             int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray,
-            int[] outputSuggestionCount, int[] outputCodePoints, int[] outputScores,
-            int[] outputIndices, int[] outputTypes, int[] outputAutoCommitFirstWordConfidence,
-            float[] inOutLanguageWeight);
+            int prevWordCount, int[] outputSuggestionCount, int[] outputCodePoints,
+            int[] outputScores, int[] outputIndices, int[] outputTypes,
+            int[] outputAutoCommitFirstWordConfidence,
+            float[] inOutWeightOfLangModelVsSpatialModel);
     private static native boolean addUnigramEntryNative(long dict, int[] word, int probability,
             int[] shortcutTarget, int shortcutProbability, boolean isBeginningOfSentence,
-            boolean isNotAWord, boolean isBlacklisted, int timestamp);
+            boolean isNotAWord, boolean isPossiblyOffensive, int timestamp);
     private static native boolean removeUnigramEntryNative(long dict, int[] word);
     private static native boolean addNgramEntryNative(long dict,
             int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray,
             int[] word, int probability, int timestamp);
     private static native boolean removeNgramEntryNative(long dict,
             int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray, int[] word);
-    private static native int addMultipleDictionaryEntriesNative(long dict,
-            LanguageModelParam[] languageModelParams, int startIndex);
+    private static native boolean updateEntriesForWordWithNgramContextNative(long dict,
+            int[][] prevWordCodePointArrays, boolean[] isBeginningOfSentenceArray,
+            int[] word, boolean isValidWord, int count, int timestamp);
+    private static native int updateEntriesForInputEventsNative(long dict,
+            WordInputEventForPersonalization[] inputEvents, int startIndex);
     private static native String getPropertyNative(long dict, String query);
     private static native boolean isCorruptedNative(long dict);
     private static native boolean migrateNative(long dict, String dictFilePath,
             long newFormatVersion);
 
     // TODO: Move native dict into session
-    private final void loadDictionary(final String path, final long startOffset,
+    private void loadDictionary(final String path, final long startOffset,
             final long length, final boolean isUpdatable) {
         mHasUpdated = false;
         mNativeDict = openNative(path, startOffset, length, isUpdatable);
@@ -256,23 +265,25 @@
     }
 
     @Override
-    public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+    public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+            final NgramContext ngramContext, final long proximityInfoHandle,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final int sessionId, final float[] inOutLanguageWeight) {
+            final int sessionId, final float weightForLocale,
+            final float[] inOutWeightOfLangModelVsSpatialModel) {
         if (!isValidDictionary()) {
             return null;
         }
         final DicTraverseSession session = getTraverseSession(sessionId);
         Arrays.fill(session.mInputCodePoints, Constants.NOT_A_CODE);
-        prevWordsInfo.outputToArray(session.mPrevWordCodePointArrays,
+        ngramContext.outputToArray(session.mPrevWordCodePointArrays,
                 session.mIsBeginningOfSentenceArray);
-        final InputPointers inputPointers = composer.getInputPointers();
-        final boolean isGesture = composer.isBatchMode();
+        final InputPointers inputPointers = composedData.mInputPointers;
+        final boolean isGesture = composedData.mIsBatchMode;
         final int inputSize;
         if (!isGesture) {
-            inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
-                    session.mInputCodePoints);
+            inputSize =
+                    composedData.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
+                        session.mInputCodePoints);
             if (inputSize < 0) {
                 return null;
             }
@@ -283,41 +294,45 @@
         session.mNativeSuggestOptions.setIsGesture(isGesture);
         session.mNativeSuggestOptions.setBlockOffensiveWords(
                 settingsValuesForSuggestion.mBlockPotentiallyOffensive);
-        session.mNativeSuggestOptions.setSpaceAwareGestureEnabled(
-                settingsValuesForSuggestion.mSpaceAwareGestureEnabled);
-        session.mNativeSuggestOptions.setAdditionalFeaturesOptions(
-                settingsValuesForSuggestion.mAdditionalFeaturesSettingValues);
-        if (inOutLanguageWeight != null) {
-            session.mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
+        session.mNativeSuggestOptions.setWeightForLocale(weightForLocale);
+        if (inOutWeightOfLangModelVsSpatialModel != null) {
+            session.mInputOutputWeightOfLangModelVsSpatialModel[0] =
+                    inOutWeightOfLangModelVsSpatialModel[0];
         } else {
-            session.mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
+            session.mInputOutputWeightOfLangModelVsSpatialModel[0] =
+                    Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL;
         }
         // TOOD: Pass multiple previous words information for n-gram.
-        getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
+        getSuggestionsNative(mNativeDict, proximityInfoHandle,
                 getTraverseSession(sessionId).getSession(), inputPointers.getXCoordinates(),
                 inputPointers.getYCoordinates(), inputPointers.getTimes(),
                 inputPointers.getPointerIds(), session.mInputCodePoints, inputSize,
                 session.mNativeSuggestOptions.getOptions(), session.mPrevWordCodePointArrays,
-                session.mIsBeginningOfSentenceArray, session.mOutputSuggestionCount,
-                session.mOutputCodePoints, session.mOutputScores, session.mSpaceIndices,
-                session.mOutputTypes, session.mOutputAutoCommitFirstWordConfidence,
-                session.mInputOutputLanguageWeight);
-        if (inOutLanguageWeight != null) {
-            inOutLanguageWeight[0] = session.mInputOutputLanguageWeight[0];
+                session.mIsBeginningOfSentenceArray, ngramContext.getPrevWordCount(),
+                session.mOutputSuggestionCount, session.mOutputCodePoints, session.mOutputScores,
+                session.mSpaceIndices, session.mOutputTypes,
+                session.mOutputAutoCommitFirstWordConfidence,
+                session.mInputOutputWeightOfLangModelVsSpatialModel);
+        if (inOutWeightOfLangModelVsSpatialModel != null) {
+            inOutWeightOfLangModelVsSpatialModel[0] =
+                    session.mInputOutputWeightOfLangModelVsSpatialModel[0];
         }
         final int count = session.mOutputSuggestionCount[0];
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
         for (int j = 0; j < count; ++j) {
-            final int start = j * Constants.DICTIONARY_MAX_WORD_LENGTH;
+            final int start = j * DICTIONARY_MAX_WORD_LENGTH;
             int len = 0;
-            while (len < Constants.DICTIONARY_MAX_WORD_LENGTH
+            while (len < DICTIONARY_MAX_WORD_LENGTH
                     && session.mOutputCodePoints[start + len] != 0) {
                 ++len;
             }
             if (len > 0) {
                 suggestions.add(new SuggestedWordInfo(
                         new String(session.mOutputCodePoints, start, len),
-                        session.mOutputScores[j], session.mOutputTypes[j], this /* sourceDict */,
+                        "" /* prevWordsContext */,
+                        (int)(session.mOutputScores[j] * weightForLocale),
+                        session.mOutputTypes[j],
+                        this /* sourceDict */,
                         session.mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
                         session.mOutputAutoCommitFirstWordConfidence[0]));
             }
@@ -340,31 +355,34 @@
 
     @Override
     public int getFrequency(final String word) {
-        if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
-        int[] codePoints = StringUtils.toCodePointArray(word);
+        if (TextUtils.isEmpty(word)) {
+            return NOT_A_PROBABILITY;
+        }
+        final int[] codePoints = StringUtils.toCodePointArray(word);
         return getProbabilityNative(mNativeDict, codePoints);
     }
 
     @Override
     public int getMaxFrequencyOfExactMatches(final String word) {
-        if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
-        int[] codePoints = StringUtils.toCodePointArray(word);
+        if (TextUtils.isEmpty(word)) {
+            return NOT_A_PROBABILITY;
+        }
+        final int[] codePoints = StringUtils.toCodePointArray(word);
         return getMaxProbabilityOfExactMatchesNative(mNativeDict, codePoints);
     }
 
     @UsedForTesting
-    public boolean isValidNgram(final PrevWordsInfo prevWordsInfo, final String word) {
-        return getNgramProbability(prevWordsInfo, word) != NOT_A_PROBABILITY;
+    public boolean isValidNgram(final NgramContext ngramContext, final String word) {
+        return getNgramProbability(ngramContext, word) != NOT_A_PROBABILITY;
     }
 
-    public int getNgramProbability(final PrevWordsInfo prevWordsInfo, final String word) {
-        if (!prevWordsInfo.isValid() || TextUtils.isEmpty(word)) {
+    public int getNgramProbability(final NgramContext ngramContext, final String word) {
+        if (!ngramContext.isValid() || TextUtils.isEmpty(word)) {
             return NOT_A_PROBABILITY;
         }
-        final int[][] prevWordCodePointArrays = new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
-        final boolean[] isBeginningOfSentenceArray =
-                new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        prevWordsInfo.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
+        final int[][] prevWordCodePointArrays = new int[ngramContext.getPrevWordCount()][];
+        final boolean[] isBeginningOfSentenceArray = new boolean[ngramContext.getPrevWordCount()];
+        ngramContext.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
         final int[] wordCodePoints = StringUtils.toCodePointArray(word);
         return getNgramProbabilityNative(mNativeDict, prevWordCodePointArrays,
                 isBeginningOfSentenceArray, wordCodePoints);
@@ -375,25 +393,28 @@
             return null;
         }
         final int[] codePoints = StringUtils.toCodePointArray(word);
-        final int[] outCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+        final int[] outCodePoints = new int[DICTIONARY_MAX_WORD_LENGTH];
         final boolean[] outFlags = new boolean[FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT];
         final int[] outProbabilityInfo =
                 new int[FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT];
-        final ArrayList<int[]> outBigramTargets = new ArrayList<>();
-        final ArrayList<int[]> outBigramProbabilityInfo = new ArrayList<>();
+        final ArrayList<int[][]> outNgramPrevWordsArray = new ArrayList<>();
+        final ArrayList<boolean[]> outNgramPrevWordIsBeginningOfSentenceArray =
+                new ArrayList<>();
+        final ArrayList<int[]> outNgramTargets = new ArrayList<>();
+        final ArrayList<int[]> outNgramProbabilityInfo = new ArrayList<>();
         final ArrayList<int[]> outShortcutTargets = new ArrayList<>();
         final ArrayList<Integer> outShortcutProbabilities = new ArrayList<>();
         getWordPropertyNative(mNativeDict, codePoints, isBeginningOfSentence, outCodePoints,
-                outFlags, outProbabilityInfo, outBigramTargets, outBigramProbabilityInfo,
-                outShortcutTargets, outShortcutProbabilities);
+                outFlags, outProbabilityInfo, outNgramPrevWordsArray,
+                outNgramPrevWordIsBeginningOfSentenceArray, outNgramTargets,
+                outNgramProbabilityInfo, outShortcutTargets, outShortcutProbabilities);
         return new WordProperty(codePoints,
                 outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
-                outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX],
-                outFlags[FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX],
-                outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_IS_POSSIBLY_OFFENSIVE_INDEX],
+                outFlags[FORMAT_WORD_PROPERTY_HAS_NGRAMS_INDEX],
                 outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
-                outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
-                outShortcutProbabilities);
+                outNgramPrevWordsArray, outNgramPrevWordIsBeginningOfSentenceArray,
+                outNgramTargets, outNgramProbabilityInfo);
     }
 
     public static class GetNextWordPropertyResult {
@@ -411,7 +432,7 @@
      * If token is 0, this method newly starts iterating the dictionary.
      */
     public GetNextWordPropertyResult getNextWordProperty(final int token) {
-        final int[] codePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+        final int[] codePoints = new int[DICTIONARY_MAX_WORD_LENGTH];
         final boolean[] isBeginningOfSentence = new boolean[1];
         final int nextToken = getNextWordNative(mNativeDict, token, codePoints,
                 isBeginningOfSentence);
@@ -421,18 +442,16 @@
     }
 
     // Add a unigram entry to binary dictionary with unigram attributes in native code.
-    public boolean addUnigramEntry(final String word, final int probability,
-            final String shortcutTarget, final int shortcutProbability,
-            final boolean isBeginningOfSentence, final boolean isNotAWord,
-            final boolean isBlacklisted, final int timestamp) {
+    public boolean addUnigramEntry(
+            final String word, final int probability, final boolean isBeginningOfSentence,
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
         if (word == null || (word.isEmpty() && !isBeginningOfSentence)) {
             return false;
         }
         final int[] codePoints = StringUtils.toCodePointArray(word);
-        final int[] shortcutTargetCodePoints = (shortcutTarget != null) ?
-                StringUtils.toCodePointArray(shortcutTarget) : null;
-        if (!addUnigramEntryNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints,
-                shortcutProbability, isBeginningOfSentence, isNotAWord, isBlacklisted, timestamp)) {
+        if (!addUnigramEntryNative(mNativeDict, codePoints, probability,
+                null /* shortcutTargetCodePoints */, 0 /* shortcutProbability */,
+                isBeginningOfSentence, isNotAWord, isPossiblyOffensive, timestamp)) {
             return false;
         }
         mHasUpdated = true;
@@ -453,15 +472,14 @@
     }
 
     // Add an n-gram entry to the binary dictionary with timestamp in native code.
-    public boolean addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word,
+    public boolean addNgramEntry(final NgramContext ngramContext, final String word,
             final int probability, final int timestamp) {
-        if (!prevWordsInfo.isValid() || TextUtils.isEmpty(word)) {
+        if (!ngramContext.isValid() || TextUtils.isEmpty(word)) {
             return false;
         }
-        final int[][] prevWordCodePointArrays = new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
-        final boolean[] isBeginningOfSentenceArray =
-                new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        prevWordsInfo.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
+        final int[][] prevWordCodePointArrays = new int[ngramContext.getPrevWordCount()][];
+        final boolean[] isBeginningOfSentenceArray = new boolean[ngramContext.getPrevWordCount()];
+        ngramContext.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
         final int[] wordCodePoints = StringUtils.toCodePointArray(word);
         if (!addNgramEntryNative(mNativeDict, prevWordCodePointArrays,
                 isBeginningOfSentenceArray, wordCodePoints, probability, timestamp)) {
@@ -471,35 +489,38 @@
         return true;
     }
 
-    // Remove an n-gram entry from the binary dictionary in native code.
-    public boolean removeNgramEntry(final PrevWordsInfo prevWordsInfo, final String word) {
-        if (!prevWordsInfo.isValid() || TextUtils.isEmpty(word)) {
+    // Update entries for the word occurrence with the ngramContext.
+    public boolean updateEntriesForWordWithNgramContext(@Nonnull final NgramContext ngramContext,
+            final String word, final boolean isValidWord, final int count, final int timestamp) {
+        if (TextUtils.isEmpty(word)) {
             return false;
         }
-        final int[][] prevWordCodePointArrays = new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
-        final boolean[] isBeginningOfSentenceArray =
-                new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        prevWordsInfo.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
+        final int[][] prevWordCodePointArrays = new int[ngramContext.getPrevWordCount()][];
+        final boolean[] isBeginningOfSentenceArray = new boolean[ngramContext.getPrevWordCount()];
+        ngramContext.outputToArray(prevWordCodePointArrays, isBeginningOfSentenceArray);
         final int[] wordCodePoints = StringUtils.toCodePointArray(word);
-        if (!removeNgramEntryNative(mNativeDict, prevWordCodePointArrays,
-                isBeginningOfSentenceArray, wordCodePoints)) {
+        if (!updateEntriesForWordWithNgramContextNative(mNativeDict, prevWordCodePointArrays,
+                isBeginningOfSentenceArray, wordCodePoints, isValidWord, count, timestamp)) {
             return false;
         }
         mHasUpdated = true;
         return true;
     }
 
-    public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) {
-        if (!isValidDictionary()) return;
-        int processedParamCount = 0;
-        while (processedParamCount < languageModelParams.length) {
+    @UsedForTesting
+    public void updateEntriesForInputEvents(final WordInputEventForPersonalization[] inputEvents) {
+        if (!isValidDictionary()) {
+            return;
+        }
+        int processedEventCount = 0;
+        while (processedEventCount < inputEvents.length) {
             if (needsToRunGC(true /* mindsBlockByGC */)) {
                 flushWithGC();
             }
-            processedParamCount = addMultipleDictionaryEntriesNative(mNativeDict,
-                    languageModelParams, processedParamCount);
+            processedEventCount = updateEntriesForInputEventsNative(mNativeDict, inputEvents,
+                    processedEventCount);
             mHasUpdated = true;
-            if (processedParamCount <= 0) {
+            if (processedEventCount <= 0) {
                 return;
             }
         }
@@ -517,7 +538,9 @@
 
     // Flush to dict file if the dictionary has been updated.
     public boolean flush() {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         if (mHasUpdated) {
             if (!flushNative(mNativeDict, mDictFilePath)) {
                 return false;
@@ -537,7 +560,9 @@
 
     // Run GC and flush to dict file.
     public boolean flushWithGC() {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         if (!flushWithGCNative(mNativeDict, mDictFilePath)) {
             return false;
         }
@@ -552,7 +577,9 @@
      * @return whether GC is needed to run or not.
      */
     public boolean needsToRunGC(final boolean mindsBlockByGC) {
-        if (!isValidDictionary()) return false;
+        if (!isValidDictionary()) {
+            return false;
+        }
         return needsToRunGCNative(mNativeDict, mindsBlockByGC);
     }
 
@@ -596,8 +623,10 @@
     }
 
     @UsedForTesting
-    public String getPropertyForTest(final String query) {
-        if (!isValidDictionary()) return "";
+    public String getPropertyForGettingStats(final String query) {
+        if (!isValidDictionary()) {
+            return "";
+        }
         return getPropertyNative(mNativeDict, query);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 10b1f1b..bc62f3a 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -29,6 +29,7 @@
 
 import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
 import com.android.inputmethod.dictionarypack.MD5Calculator;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
 import com.android.inputmethod.latin.utils.DictionaryInfoUtils.DictionaryInfo;
 import com.android.inputmethod.latin.utils.FileTransforms;
@@ -67,6 +68,11 @@
     private static final byte[] MAGIC_NUMBER_VERSION_2 =
             new byte[] { (byte)0x9B, (byte)0xC1, (byte)0x3A, (byte)0xFE };
 
+    private static final boolean SHOULD_VERIFY_MAGIC_NUMBER =
+            DecoderSpecificConstants.SHOULD_VERIFY_MAGIC_NUMBER;
+    private static final boolean SHOULD_VERIFY_CHECKSUM =
+            DecoderSpecificConstants.SHOULD_VERIFY_CHECKSUM;
+
     private static final String DICTIONARY_PROJECTION[] = { "id" };
 
     private static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt";
@@ -302,13 +308,18 @@
                 checkMagicAndCopyFileTo(bufferedInputStream, bufferedOutputStream);
                 bufferedOutputStream.flush();
                 bufferedOutputStream.close();
-                final String actualRawChecksum = MD5Calculator.checksum(
-                        new BufferedInputStream(new FileInputStream(outputFile)));
-                Log.i(TAG, "Computed checksum for downloaded dictionary. Expected = " + rawChecksum
-                        + " ; actual = " + actualRawChecksum);
-                if (!TextUtils.isEmpty(rawChecksum) && !rawChecksum.equals(actualRawChecksum)) {
-                    throw new IOException("Could not decode the file correctly : checksum differs");
+
+                if (SHOULD_VERIFY_CHECKSUM) {
+                    final String actualRawChecksum = MD5Calculator.checksum(
+                            new BufferedInputStream(new FileInputStream(outputFile)));
+                    Log.i(TAG, "Computed checksum for downloaded dictionary. Expected = "
+                            + rawChecksum + " ; actual = " + actualRawChecksum);
+                    if (!TextUtils.isEmpty(rawChecksum) && !rawChecksum.equals(actualRawChecksum)) {
+                        throw new IOException(
+                                "Could not decode the file correctly : checksum differs");
+                    }
                 }
+
                 final File finalFile = new File(finalFileName);
                 finalFile.delete();
                 if (!outputFile.renameTo(finalFile)) {
@@ -444,9 +455,11 @@
         if (readMagicNumberSize < length) {
             throw new IOException("Less bytes to read than the magic number length");
         }
-        if (!Arrays.equals(MAGIC_NUMBER_VERSION_2, magicNumberBuffer)) {
-            if (!Arrays.equals(MAGIC_NUMBER_VERSION_1, magicNumberBuffer)) {
-                throw new IOException("Wrong magic number for downloaded file");
+        if (SHOULD_VERIFY_MAGIC_NUMBER) {
+            if (!Arrays.equals(MAGIC_NUMBER_VERSION_2, magicNumberBuffer)) {
+                if (!Arrays.equals(MAGIC_NUMBER_VERSION_1, magicNumberBuffer)) {
+                    throw new IOException("Wrong magic number for downloaded file");
+                }
             }
         }
         output.write(magicNumberBuffer);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 867c186..5f2a112 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -21,11 +21,12 @@
 import android.content.res.AssetFileDescriptor;
 import android.util.Log;
 
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
 import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
 
 import java.io.File;
 import java.io.IOException;
@@ -54,6 +55,9 @@
      */
     private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs";
 
+    private static final boolean SHOULD_USE_DICT_VERSION =
+            DecoderSpecificConstants.SHOULD_USE_DICT_VERSION;
+
     // Name of the category for the main dictionary
     public static final String MAIN_DICTIONARY_CATEGORY = "main";
     public static final String ID_CATEGORY_SEPARATOR = ":";
@@ -87,10 +91,15 @@
      */
     public static AssetFileAddress loadFallbackResource(final Context context,
             final int fallbackResId) {
-        final AssetFileDescriptor afd = context.getResources().openRawResourceFd(fallbackResId);
+        AssetFileDescriptor afd = null;
+        try {
+            afd = context.getResources().openRawResourceFd(fallbackResId);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Resource not found: " + fallbackResId);
+            return null;
+        }
         if (afd == null) {
-            Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId="
-                    + fallbackResId);
+            Log.e(TAG, "Resource cannot be opened: " + fallbackResId);
             return null;
         }
         try {
@@ -99,8 +108,7 @@
         } finally {
             try {
                 afd.close();
-            } catch (IOException e) {
-                // Ignored
+            } catch (IOException ignored) {
             }
         }
     }
@@ -121,12 +129,11 @@
                 // reason some dictionaries have been installed BUT the dictionary pack can't be
                 // found anymore it's safer to actually supply installed dictionaries.
                 return true;
-            } else {
-                // The default is true here for the same reasons as above. We got the dictionary
-                // pack but if we don't have any settings for it it means the user has never been
-                // to the settings yet. So by default, the main dictionaries should be on.
-                return mDictPreferences.getBoolean(dictId, true);
             }
+            // The default is true here for the same reasons as above. We got the dictionary
+            // pack but if we don't have any settings for it it means the user has never been
+            // to the settings yet. So by default, the main dictionaries should be on.
+            return mDictPreferences.getBoolean(dictId, true);
         }
     }
 
@@ -224,7 +231,11 @@
     // ## HACK ## we prevent usage of a dictionary before version 18. The reason for this is, since
     // those do not include whitelist entries, the new code with an old version of the dictionary
     // would lose whitelist functionality.
-    private static boolean hackCanUseDictionaryFile(final Locale locale, final File file) {
+    private static boolean hackCanUseDictionaryFile(final File file) {
+        if (!SHOULD_USE_DICT_VERSION) {
+            return true;
+        }
+
         try {
             // Read the version of the file
             final DictionaryHeader header = BinaryDictionaryUtils.getHeader(file);
@@ -262,11 +273,14 @@
      * @return The list of addresses of valid dictionary files, or null.
      */
     public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale,
-            final Context context) {
+            final Context context, boolean notifyDictionaryPackForUpdates) {
 
-        final boolean hasDefaultWordList = DictionaryFactory.isDictionaryAvailable(context, locale);
-        BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context,
-                hasDefaultWordList);
+        final boolean hasDefaultWordList = DictionaryInfoUtils.isDictionaryAvailable(
+                context, locale);
+        if (notifyDictionaryPackForUpdates) {
+            BinaryDictionaryFileDumper.cacheWordListsFromContentProvider(locale, context,
+                    hasDefaultWordList);
+        }
         final File[] cachedWordLists = getCachedWordLists(locale.toString(), context);
         final String mainDictId = DictionaryInfoUtils.getMainDictId(locale);
         final DictPackSettings dictPackSettings = new DictPackSettings(context);
@@ -276,7 +290,7 @@
         // cachedWordLists may not be null, see doc for getCachedDictionaryList
         for (final File f : cachedWordLists) {
             final String wordListId = DictionaryInfoUtils.getWordListIdFromFileName(f.getName());
-            final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f);
+            final boolean canUse = f.canRead() && hackCanUseDictionaryFile(f);
             if (canUse && DictionaryInfoUtils.isMainWordListId(wordListId)) {
                 foundMainDict = true;
             }
@@ -285,7 +299,8 @@
                 final AssetFileAddress afa = AssetFileAddress.makeFromFileName(f.getPath());
                 if (null != afa) fileList.add(afa);
             } else {
-                Log.e(TAG, "Found a cached dictionary file but cannot read or use it");
+                Log.e(TAG, "Found a cached dictionary file for " + locale.toString()
+                        + " but cannot read or use it");
             }
         }
 
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
deleted file mode 100644
index 43af66e..0000000
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-public final class Constants {
-    public static final class Color {
-        /**
-         * The alpha value for fully opaque.
-         */
-        public final static int ALPHA_OPAQUE = 255;
-    }
-
-    public static final class ImeOption {
-        /**
-         * The private IME option used to indicate that no microphone should be shown for a given
-         * text field. For instance, this is specified by the search dialog when the dialog is
-         * already showing a voice search button.
-         *
-         * @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed.
-         */
-        @SuppressWarnings("dep-ann")
-        public static final String NO_MICROPHONE_COMPAT = "nm";
-
-        /**
-         * The private IME option used to indicate that no microphone should be shown for a given
-         * text field. For instance, this is specified by the search dialog when the dialog is
-         * already showing a voice search button.
-         */
-        public static final String NO_MICROPHONE = "noMicrophoneKey";
-
-        /**
-         * The private IME option used to indicate that no settings key should be shown for a given
-         * text field.
-         */
-        public static final String NO_SETTINGS_KEY = "noSettingsKey";
-
-        /**
-         * The private IME option used to indicate that the given text field needs ASCII code points
-         * input.
-         *
-         * @deprecated Use EditorInfo#IME_FLAG_FORCE_ASCII.
-         */
-        @SuppressWarnings("dep-ann")
-        public static final String FORCE_ASCII = "forceAscii";
-
-        private ImeOption() {
-            // This utility class is not publicly instantiable.
-        }
-    }
-
-    public static final class Subtype {
-        /**
-         * The subtype mode used to indicate that the subtype is a keyboard.
-         */
-        public static final String KEYBOARD_MODE = "keyboard";
-
-        public static final class ExtraValue {
-            /**
-             * The subtype extra value used to indicate that this subtype is capable of
-             * entering ASCII characters.
-             */
-            public static final String ASCII_CAPABLE = "AsciiCapable";
-
-            /**
-             * The subtype extra value used to indicate that this subtype is enabled
-             * when the default subtype is not marked as ascii capable.
-             */
-            public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
-                    "EnabledWhenDefaultIsNotAsciiCapable";
-
-            /**
-             * The subtype extra value used to indicate that this subtype is capable of
-             * entering emoji characters.
-             */
-            public static final String EMOJI_CAPABLE = "EmojiCapable";
-
-            /**
-             * The subtype extra value used to indicate that this subtype requires a network
-             * connection to work.
-             */
-            public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
-
-            /**
-             * The subtype extra value used to indicate that the display name of this subtype
-             * contains a "%s" for printf-like replacement and it should be replaced by
-             * this extra value.
-             * This extra value is supported on JellyBean and later.
-             */
-            public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
-                    "UntranslatableReplacementStringInSubtypeName";
-
-            /**
-             * The subtype extra value used to indicate this subtype keyboard layout set name.
-             * This extra value is private to LatinIME.
-             */
-            public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
-
-            /**
-             * The subtype extra value used to indicate that this subtype is an additional subtype
-             * that the user defined. This extra value is private to LatinIME.
-             */
-            public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
-
-            /**
-             * The subtype extra value used to specify the combining rules.
-             */
-            public static final String COMBINING_RULES = "CombiningRules";
-
-            private ExtraValue() {
-                // This utility class is not publicly instantiable.
-            }
-        }
-
-        private Subtype() {
-            // This utility class is not publicly instantiable.
-        }
-    }
-
-    public static final class TextUtils {
-        /**
-         * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
-         * characters.  This value may be used with
-         * {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
-         * {@link android.text.TextUtils#CAP_MODE_WORDS}, and
-         * {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
-         */
-        // TODO: Straighten this out. It's bizarre to have to use android.text.TextUtils.CAP_MODE_*
-        // except for OFF that is in Constants.TextUtils.
-        public static final int CAP_MODE_OFF = 0;
-
-        private TextUtils() {
-            // This utility class is not publicly instantiable.
-        }
-    }
-
-    public static final int NOT_A_CODE = -1;
-    public static final int NOT_A_CURSOR_POSITION = -1;
-    // TODO: replace the following constants with state in InputTransaction?
-    public static final int NOT_A_COORDINATE = -1;
-    public static final int SUGGESTION_STRIP_COORDINATE = -2;
-    public static final int SPELL_CHECKER_COORDINATE = -3;
-    public static final int EXTERNAL_KEYBOARD_COORDINATE = -4;
-
-    // A hint on how many characters to cache from the TextView. A good value of this is given by
-    // how many characters we need to be able to almost always find the caps mode.
-    public static final int EDITOR_CONTENTS_CACHE_SIZE = 1024;
-    // How many characters we accept for the recapitalization functionality. This needs to be
-    // large enough for all reasonable purposes, but avoid purposeful attacks. 100k sounds about
-    // right for this.
-    public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100;
-
-    // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
-    public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
-
-    // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify
-    // MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions.
-    public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 2;
-
-    // Key events coming any faster than this are long-presses.
-    public static final int LONG_PRESS_MILLISECONDS = 200;
-    // TODO: Set this value appropriately.
-    public static final int GET_SUGGESTED_WORDS_TIMEOUT = 200;
-    // How many continuous deletes at which to start deleting at a higher speed.
-    public static final int DELETE_ACCELERATE_AT = 20;
-
-    public static final String WORD_SEPARATOR = " ";
-
-    public static boolean isValidCoordinate(final int coordinate) {
-        // Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
-        // and {@link SPELL_CHECKER_COORDINATE}.
-        return coordinate >= 0;
-    }
-
-    /**
-     * Custom request code used in
-     * {@link com.android.inputmethod.keyboard.KeyboardActionListener#onCustomRequest(int)}.
-     */
-    // The code to show input method picker.
-    public static final int CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER = 1;
-
-    /**
-     * Some common keys code. Must be positive.
-     */
-    public static final int CODE_ENTER = '\n';
-    public static final int CODE_TAB = '\t';
-    public static final int CODE_SPACE = ' ';
-    public static final int CODE_PERIOD = '.';
-    public static final int CODE_COMMA = ',';
-    public static final int CODE_DASH = '-';
-    public static final int CODE_SINGLE_QUOTE = '\'';
-    public static final int CODE_DOUBLE_QUOTE = '"';
-    public static final int CODE_QUESTION_MARK = '?';
-    public static final int CODE_EXCLAMATION_MARK = '!';
-    public static final int CODE_SLASH = '/';
-    public static final int CODE_BACKSLASH = '\\';
-    public static final int CODE_VERTICAL_BAR = '|';
-    public static final int CODE_COMMERCIAL_AT = '@';
-    public static final int CODE_PLUS = '+';
-    public static final int CODE_PERCENT = '%';
-    public static final int CODE_CLOSING_PARENTHESIS = ')';
-    public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
-    public static final int CODE_CLOSING_CURLY_BRACKET = '}';
-    public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
-    public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿
-    public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡
-
-    public static final String REGEXP_PERIOD = "\\.";
-    public static final String STRING_SPACE = " ";
-    public static final String STRING_PERIOD_AND_SPACE = ". ";
-
-    /**
-     * Special keys code. Must be negative.
-     * These should be aligned with {@link KeyboardCodesSet#ID_TO_NAME},
-     * {@link KeyboardCodesSet#DEFAULT}, and {@link KeyboardCodesSet#RTL}.
-     */
-    public static final int CODE_SHIFT = -1;
-    public static final int CODE_CAPSLOCK = -2;
-    public static final int CODE_SWITCH_ALPHA_SYMBOL = -3;
-    public static final int CODE_OUTPUT_TEXT = -4;
-    public static final int CODE_DELETE = -5;
-    public static final int CODE_SETTINGS = -6;
-    public static final int CODE_SHORTCUT = -7;
-    public static final int CODE_ACTION_NEXT = -8;
-    public static final int CODE_ACTION_PREVIOUS = -9;
-    public static final int CODE_LANGUAGE_SWITCH = -10;
-    public static final int CODE_EMOJI = -11;
-    public static final int CODE_SHIFT_ENTER = -12;
-    public static final int CODE_SYMBOL_SHIFT = -13;
-    public static final int CODE_ALPHA_FROM_EMOJI = -14;
-    // Code value representing the code is not specified.
-    public static final int CODE_UNSPECIFIED = -15;
-
-    public static boolean isLetterCode(final int code) {
-        return code >= CODE_SPACE;
-    }
-
-    public static String printableCode(final int code) {
-        switch (code) {
-        case CODE_SHIFT: return "shift";
-        case CODE_CAPSLOCK: return "capslock";
-        case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
-        case CODE_OUTPUT_TEXT: return "text";
-        case CODE_DELETE: return "delete";
-        case CODE_SETTINGS: return "settings";
-        case CODE_SHORTCUT: return "shortcut";
-        case CODE_ACTION_NEXT: return "actionNext";
-        case CODE_ACTION_PREVIOUS: return "actionPrevious";
-        case CODE_LANGUAGE_SWITCH: return "languageSwitch";
-        case CODE_EMOJI: return "emoji";
-        case CODE_SHIFT_ENTER: return "shiftEnter";
-        case CODE_ALPHA_FROM_EMOJI: return "alpha";
-        case CODE_UNSPECIFIED: return "unspec";
-        case CODE_TAB: return "tab";
-        case CODE_ENTER: return "enter";
-        case CODE_SPACE: return "space";
-        default:
-            if (code < CODE_SPACE) return String.format("\\u%02X", code);
-            if (code < 0x100) return String.format("%c", code);
-            if (code < 0x10000) return String.format("\\u%04X", code);
-            return String.format("\\U%05X", code);
-        }
-    }
-
-    public static String printableCodes(final int[] codes) {
-        final StringBuilder sb = new StringBuilder();
-        boolean addDelimiter = false;
-        for (final int code : codes) {
-            if (code == NOT_A_CODE) break;
-            if (addDelimiter) sb.append(", ");
-            sb.append(printableCode(code));
-            addDelimiter = true;
-        }
-        return "[" + sb + "]";
-    }
-
-    public static final int MAX_INT_BIT_COUNT = 32;
-
-    /**
-     * Screen metrics (a.k.a. Device form factor) constants of
-     * {@link R.integer#config_screen_metrics}.
-     */
-    public static final int SCREEN_METRICS_SMALL_PHONE = 0;
-    public static final int SCREEN_METRICS_LARGE_PHONE = 1;
-    public static final int SCREEN_METRICS_LARGE_TABLET = 2;
-    public static final int SCREEN_METRICS_SMALL_TABLET = 3;
-
-    /**
-     * Default capacity of gesture points container.
-     * This constant is used by {@link BatchInputArbiter} and etc. to preallocate regions that
-     * contain gesture event points.
-     */
-    public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
-
-    private Constants() {
-        // This utility class is not publicly instantiable.
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 162a209..15a14e5 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -16,34 +16,26 @@
 
 package com.android.inputmethod.latin;
 
-import android.content.ContentResolver;
 import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
 import android.net.Uri;
-import android.os.SystemClock;
-import android.provider.BaseColumns;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Contacts;
-import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.annotations.ExternallyReferenced;
+import com.android.inputmethod.latin.ContactsManager.ContactsChangedListener;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.personalization.AccountUtils;
-import com.android.inputmethod.latin.utils.ExecutorUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
-public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
+import javax.annotation.Nullable;
 
-    private static final String[] PROJECTION = {BaseColumns._ID, Contacts.DISPLAY_NAME};
-    private static final String[] PROJECTION_ID_ONLY = {BaseColumns._ID};
-
+public class ContactsBinaryDictionary extends ExpandableBinaryDictionary
+        implements ContactsChangedListener {
     private static final String TAG = ContactsBinaryDictionary.class.getSimpleName();
     private static final String NAME = "contacts";
 
@@ -51,72 +43,39 @@
     private static final boolean DEBUG_DUMP = false;
 
     /**
-     * Frequency for contacts information into the dictionary
-     */
-    private static final int FREQUENCY_FOR_CONTACTS = 40;
-    private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
-
-    /** The maximum number of contacts that this dictionary supports. */
-    private static final int MAX_CONTACT_COUNT = 10000;
-
-    private static final int INDEX_NAME = 1;
-
-    /** The number of contacts in the most recent dictionary rebuild. */
-    private int mContactCountAtLastRebuild = 0;
-
-    /** The hash code of ArrayList of contacts names in the most recent dictionary rebuild. */
-    private int mHashCodeAtLastRebuild = 0;
-
-    private ContentObserver mObserver;
-
-    /**
      * Whether to use "firstname lastname" in bigram predictions.
      */
     private final boolean mUseFirstLastBigrams;
+    private final ContactsManager mContactsManager;
 
     protected ContactsBinaryDictionary(final Context context, final Locale locale,
             final File dictFile, final String name) {
         super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_CONTACTS,
                 dictFile);
-        mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
-        registerObserver(context);
+        mUseFirstLastBigrams = ContactsDictionaryUtils.useFirstLastBigramsForLocale(locale);
+        mContactsManager = new ContactsManager(context);
+        mContactsManager.registerForUpdates(this /* listener */);
         reloadDictionaryIfRequired();
     }
 
-    @UsedForTesting
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @ExternallyReferenced
     public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
-            final File dictFile, final String dictNamePrefix) {
+            final File dictFile, final String dictNamePrefix, @Nullable final String account) {
         return new ContactsBinaryDictionary(context, locale, dictFile, dictNamePrefix + NAME);
     }
 
-    private synchronized void registerObserver(final Context context) {
-        if (mObserver != null) return;
-        ContentResolver cres = context.getContentResolver();
-        cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver =
-                new ContentObserver(null) {
-                    @Override
-                    public void onChange(boolean self) {
-                        ExecutorUtils.getExecutor("Check Contacts").execute(new Runnable() {
-                            @Override
-                            public void run() {
-                                if (haveContentsChanged()) {
-                                    setNeedsToRecreate();
-                                }
-                            }
-                        });
-                    }
-                });
-    }
-
     @Override
     public synchronized void close() {
-        if (mObserver != null) {
-            mContext.getContentResolver().unregisterContentObserver(mObserver);
-            mObserver = null;
-        }
+        mContactsManager.close();
         super.close();
     }
 
+    /**
+     * Typically called whenever the dictionary is created for the first time or
+     * recreated when we think that there are updates to the dictionary.
+     * This is called asynchronously.
+     */
     @Override
     public void loadInitialContentsLocked() {
         loadDeviceAccountsEmailAddressesLocked();
@@ -125,6 +84,9 @@
         loadDictionaryForUriLocked(Contacts.CONTENT_URI);
     }
 
+    /**
+     * Loads device accounts to the dictionary.
+     */
     private void loadDeviceAccountsEmailAddressesLocked() {
         final List<String> accountVocabulary =
                 AccountUtils.getDeviceAccountsEmailAddresses(mContext);
@@ -136,80 +98,25 @@
                 Log.d(TAG, "loadAccountVocabulary: " + word);
             }
             runGCIfRequiredLocked(true /* mindsBlockByGC */);
-            addUnigramLocked(word, FREQUENCY_FOR_CONTACTS, null /* shortcut */,
-                    0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */,
+            addUnigramLocked(word, ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS,
+                    false /* isNotAWord */, false /* isPossiblyOffensive */,
                     BinaryDictionary.NOT_A_VALID_TIMESTAMP);
         }
     }
 
+    /**
+     * Loads data within content providers to the dictionary.
+     */
     private void loadDictionaryForUriLocked(final Uri uri) {
-        Cursor cursor = null;
-        try {
-            cursor = mContext.getContentResolver().query(uri, PROJECTION, null, null, null);
-            if (null == cursor) {
-                return;
-            }
-            if (cursor.moveToFirst()) {
-                mContactCountAtLastRebuild = getContactCount();
-                addWordsLocked(cursor);
-            }
-        } catch (final SQLiteException e) {
-            Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
-        } catch (final IllegalStateException e) {
-            Log.e(TAG, "Contacts DB is having problems", e);
-        } finally {
-            if (null != cursor) {
-                cursor.close();
-            }
+        final ArrayList<String> validNames = mContactsManager.getValidNames(uri);
+        for (final String name : validNames) {
+            addNameLocked(name);
         }
-    }
-
-    private boolean useFirstLastBigramsForLocale(final Locale locale) {
-        // TODO: Add firstname/lastname bigram rules for other languages.
-        if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
-            return true;
+        if (uri.equals(Contacts.CONTENT_URI)) {
+            // Since we were able to add content successfully, update the local
+            // state of the manager.
+            mContactsManager.updateLocalState(validNames);
         }
-        return false;
-    }
-
-    private void addWordsLocked(final Cursor cursor) {
-        int count = 0;
-        final ArrayList<String> names = new ArrayList<>();
-        while (!cursor.isAfterLast() && count < MAX_CONTACT_COUNT) {
-            String name = cursor.getString(INDEX_NAME);
-            if (isValidName(name)) {
-                names.add(name);
-                addNameLocked(name);
-                ++count;
-            } else {
-                if (DEBUG_DUMP) {
-                    Log.d(TAG, "Invalid name: " + name);
-                }
-            }
-            cursor.moveToNext();
-        }
-        mHashCodeAtLastRebuild = names.hashCode();
-    }
-
-    private int getContactCount() {
-        // TODO: consider switching to a rawQuery("select count(*)...") on the database if
-        // performance is a bottleneck.
-        Cursor cursor = null;
-        try {
-            cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION_ID_ONLY,
-                    null, null, null);
-            if (null == cursor) {
-                return 0;
-            }
-            return cursor.getCount();
-        } catch (final SQLiteException e) {
-            Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
-        } finally {
-            if (null != cursor) {
-                cursor.close();
-            }
-        }
-        return 0;
     }
 
     /**
@@ -218,11 +125,12 @@
      */
     private void addNameLocked(final String name) {
         int len = StringUtils.codePointCount(name);
-        PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
+        NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext(
+                BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM);
         // TODO: Better tokenization for non-Latin writing systems
         for (int i = 0; i < len; i++) {
             if (Character.isLetter(name.codePointAt(i))) {
-                int end = getWordEndPosition(name, len, i);
+                int end = ContactsDictionaryUtils.getWordEndPosition(name, len, i);
                 String word = name.substring(i, end);
                 if (DEBUG_DUMP) {
                     Log.d(TAG, "addName word = " + word);
@@ -233,93 +141,29 @@
                 final int wordLen = StringUtils.codePointCount(word);
                 if (wordLen <= MAX_WORD_LENGTH && wordLen > 1) {
                     if (DEBUG) {
-                        Log.d(TAG, "addName " + name + ", " + word + ", "  + prevWordsInfo);
+                        Log.d(TAG, "addName " + name + ", " + word + ", "  + ngramContext);
                     }
                     runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                    addUnigramLocked(word, FREQUENCY_FOR_CONTACTS,
-                            null /* shortcut */, 0 /* shortcutFreq */, false /* isNotAWord */,
-                            false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    if (!prevWordsInfo.isValid() && mUseFirstLastBigrams) {
+                    addUnigramLocked(word,
+                            ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS, false /* isNotAWord */,
+                            false /* isPossiblyOffensive */,
+                            BinaryDictionary.NOT_A_VALID_TIMESTAMP);
+                    if (ngramContext.isValid() && mUseFirstLastBigrams) {
                         runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                        addNgramEntryLocked(prevWordsInfo, word, FREQUENCY_FOR_CONTACTS_BIGRAM,
+                        addNgramEntryLocked(ngramContext,
+                                word,
+                                ContactsDictionaryConstants.FREQUENCY_FOR_CONTACTS_BIGRAM,
                                 BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                     }
-                    prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(
-                            new PrevWordsInfo.WordInfo(word));
+                    ngramContext = ngramContext.getNextNgramContext(
+                            new NgramContext.WordInfo(word));
                 }
             }
         }
     }
 
-    /**
-     * Returns the index of the last letter in the word, starting from position startIndex.
-     */
-    private static int getWordEndPosition(final String string, final int len,
-            final int startIndex) {
-        int end;
-        int cp = 0;
-        for (end = startIndex + 1; end < len; end += Character.charCount(cp)) {
-            cp = string.codePointAt(end);
-            if (!(cp == Constants.CODE_DASH || cp == Constants.CODE_SINGLE_QUOTE
-                    || Character.isLetter(cp))) {
-                break;
-            }
-        }
-        return end;
-    }
-
-    private boolean haveContentsChanged() {
-        final long startTime = SystemClock.uptimeMillis();
-        final int contactCount = getContactCount();
-        if (contactCount > MAX_CONTACT_COUNT) {
-            // If there are too many contacts then return false. In this rare case it is impossible
-            // to include all of them anyways and the cost of rebuilding the dictionary is too high.
-            // TODO: Sort and check only the MAX_CONTACT_COUNT most recent contacts?
-            return false;
-        }
-        if (contactCount != mContactCountAtLastRebuild) {
-            if (DEBUG) {
-                Log.d(TAG, "Contact count changed: " + mContactCountAtLastRebuild + " to "
-                        + contactCount);
-            }
-            return true;
-        }
-        // Check all contacts since it's not possible to find out which names have changed.
-        // This is needed because it's possible to receive extraneous onChange events even when no
-        // name has changed.
-        final Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION,
-                null, null, null);
-        if (null == cursor) {
-            return false;
-        }
-        final ArrayList<String> names = new ArrayList<>();
-        try {
-            if (cursor.moveToFirst()) {
-                while (!cursor.isAfterLast()) {
-                    String name = cursor.getString(INDEX_NAME);
-                    if (isValidName(name)) {
-                        names.add(name);
-                    }
-                    cursor.moveToNext();
-                }
-            }
-            if (names.hashCode() != mHashCodeAtLastRebuild) {
-                return true;
-            }
-        } finally {
-            cursor.close();
-        }
-        if (DEBUG) {
-            Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
-                    + " ms)");
-        }
-        return false;
-    }
-
-    private static boolean isValidName(final String name) {
-        if (name != null && -1 == name.indexOf(Constants.CODE_COMMERCIAL_AT)) {
-            return true;
-        }
-        return false;
+    @Override
+    public void onContactsChange() {
+        setNeedsToRecreate();
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
new file mode 100644
index 0000000..5eb9b16
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.SystemClock;
+import android.provider.ContactsContract.Contacts;
+import android.util.Log;
+
+import com.android.inputmethod.latin.ContactsManager.ContactsChangedListener;
+import com.android.inputmethod.latin.utils.ExecutorUtils;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * A content observer that listens to updates to content provider {@link Contacts#CONTENT_URI}.
+ */
+public class ContactsContentObserver implements Runnable {
+    private static final String TAG = ContactsContentObserver.class.getSimpleName();
+    private static final boolean DEBUG = false;
+    private static AtomicBoolean sRunning = new AtomicBoolean(false);
+
+    private final Context mContext;
+    private final ContactsManager mManager;
+
+    private ContentObserver mContentObserver;
+    private ContactsChangedListener mContactsChangedListener;
+
+    public ContactsContentObserver(final ContactsManager manager, final Context context) {
+        mManager = manager;
+        mContext = context;
+    }
+
+    public void registerObserver(final ContactsChangedListener listener) {
+        if (DEBUG) {
+            Log.d(TAG, "Registered Contacts Content Observer");
+        }
+        mContactsChangedListener = listener;
+        mContentObserver = new ContentObserver(null /* handler */) {
+            @Override
+            public void onChange(boolean self) {
+                ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD)
+                        .execute(ContactsContentObserver.this);
+            }
+        };
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        contentResolver.registerContentObserver(Contacts.CONTENT_URI, true, mContentObserver);
+    }
+
+    @Override
+    public void run() {
+        if (!sRunning.compareAndSet(false /* expect */, true /* update */)) {
+            if (DEBUG) {
+                Log.d(TAG, "run() : Already running. Don't waste time checking again.");
+            }
+            return;
+        }
+        if (haveContentsChanged()) {
+            if (DEBUG) {
+                Log.d(TAG, "run() : Contacts have changed. Notifying listeners.");
+            }
+            mContactsChangedListener.onContactsChange();
+        }
+        sRunning.set(false);
+    }
+
+    boolean haveContentsChanged() {
+        final long startTime = SystemClock.uptimeMillis();
+        final int contactCount = mManager.getContactCount();
+        if (contactCount > ContactsDictionaryConstants.MAX_CONTACT_COUNT) {
+            // If there are too many contacts then return false. In this rare case it is impossible
+            // to include all of them anyways and the cost of rebuilding the dictionary is too high.
+            // TODO: Sort and check only the MAX_CONTACT_COUNT most recent contacts?
+            return false;
+        }
+        if (contactCount != mManager.getContactCountAtLastRebuild()) {
+            if (DEBUG) {
+                Log.d(TAG, "Contact count changed: " + mManager.getContactCountAtLastRebuild()
+                        + " to " + contactCount);
+            }
+            return true;
+        }
+        final ArrayList<String> names = mManager.getValidNames(Contacts.CONTENT_URI);
+        if (names.hashCode() != mManager.getHashCodeAtLastRebuild()) {
+            return true;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
+                    + " ms)");
+        }
+        return false;
+    }
+
+    public void unregister() {
+        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionaryConstants.java b/java/src/com/android/inputmethod/latin/ContactsDictionaryConstants.java
new file mode 100644
index 0000000..8d8faca
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionaryConstants.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.provider.BaseColumns;
+import android.provider.ContactsContract.Contacts;
+
+/**
+ * Constants related to Contacts Content Provider.
+ */
+public class ContactsDictionaryConstants {
+    /**
+     * Projections for {@link Contacts.CONTENT_URI}
+     */
+    public static final String[] PROJECTION = { BaseColumns._ID, Contacts.DISPLAY_NAME };
+    public static final String[] PROJECTION_ID_ONLY = { BaseColumns._ID };
+
+    /**
+     * Frequency for contacts information into the dictionary
+     */
+    public static final int FREQUENCY_FOR_CONTACTS = 40;
+    public static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90;
+
+    /**
+     *  The maximum number of contacts that this dictionary supports.
+     */
+    public static final int MAX_CONTACT_COUNT = 10000;
+
+    /**
+     * Index of the column for 'name' in content providers:
+     * Contacts & ContactsContract.Profile.
+     */
+    public static final int NAME_INDEX = 1;
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionaryUtils.java b/java/src/com/android/inputmethod/latin/ContactsDictionaryUtils.java
new file mode 100644
index 0000000..b773884
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ContactsDictionaryUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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;
+
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+/**
+ * Utility methods related contacts dictionary.
+ */
+public class ContactsDictionaryUtils {
+
+    /**
+     * Returns the index of the last letter in the word, starting from position startIndex.
+     */
+    public static int getWordEndPosition(final String string, final int len,
+            final int startIndex) {
+        int end;
+        int cp = 0;
+        for (end = startIndex + 1; end < len; end += Character.charCount(cp)) {
+            cp = string.codePointAt(end);
+            if (cp != Constants.CODE_DASH && cp != Constants.CODE_SINGLE_QUOTE
+                   && !Character.isLetter(cp)) {
+                break;
+            }
+        }
+        return end;
+    }
+
+    /**
+     * Returns true if the locale supports using first name and last name as bigrams.
+     */
+    public static boolean useFirstLastBigramsForLocale(final Locale locale) {
+        // TODO: Add firstname/lastname bigram rules for other languages.
+        if (locale != null && locale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/ContactsManager.java b/java/src/com/android/inputmethod/latin/ContactsManager.java
new file mode 100644
index 0000000..1fadc6f
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ContactsManager.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.util.Log;
+
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Manages all interactions with Contacts DB.
+ *
+ * The manager provides an API for listening to meaning full updates by keeping a
+ * measure of the current state of the content provider.
+ */
+public class ContactsManager {
+    private static final String TAG = ContactsManager.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    /**
+     * Interface to implement for classes interested in getting notified for updates
+     * to Contacts content provider.
+     */
+    public static interface ContactsChangedListener {
+        public void onContactsChange();
+    }
+
+    /**
+     * The number of contacts observed in the most recent instance of
+     * contacts content provider.
+     */
+    private AtomicInteger mContactCountAtLastRebuild = new AtomicInteger(0);
+
+    /**
+     * The hash code of list of valid contacts names in the most recent dictionary
+     * rebuild.
+     */
+    private AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
+
+    private final Context mContext;
+    private final ContactsContentObserver mObserver;
+
+    public ContactsManager(final Context context) {
+        mContext = context;
+        mObserver = new ContactsContentObserver(this /* ContactsManager */, context);
+    }
+
+    // TODO: This was synchronized in previous version. Why?
+    public void registerForUpdates(final ContactsChangedListener listener) {
+        mObserver.registerObserver(listener);
+    }
+
+    public int getContactCountAtLastRebuild() {
+        return mContactCountAtLastRebuild.get();
+    }
+
+    public int getHashCodeAtLastRebuild() {
+        return mHashCodeAtLastRebuild.get();
+    }
+
+    /**
+     * Returns all the valid names in the Contacts DB. Callers should also
+     * call {@link #updateLocalState(ArrayList)} after they are done with result
+     * so that the manager can cache local state for determining updates.
+     */
+    public ArrayList<String> getValidNames(final Uri uri) {
+        final ArrayList<String> names = new ArrayList<>();
+        // Check all contacts since it's not possible to find out which names have changed.
+        // This is needed because it's possible to receive extraneous onChange events even when no
+        // name has changed.
+        final Cursor cursor = mContext.getContentResolver().query(uri,
+                ContactsDictionaryConstants.PROJECTION, null, null, null);
+        if (cursor != null) {
+            try {
+                if (cursor.moveToFirst()) {
+                    while (!cursor.isAfterLast()) {
+                        final String name = cursor.getString(
+                                ContactsDictionaryConstants.NAME_INDEX);
+                        if (isValidName(name)) {
+                            names.add(name);
+                        }
+                        cursor.moveToNext();
+                    }
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+        return names;
+    }
+
+    /**
+     * Returns the number of contacts in contacts content provider.
+     */
+    public int getContactCount() {
+        // TODO: consider switching to a rawQuery("select count(*)...") on the database if
+        // performance is a bottleneck.
+        Cursor cursor = null;
+        try {
+            cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
+                    ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
+            if (null == cursor) {
+                return 0;
+            }
+            return cursor.getCount();
+        } catch (final SQLiteException e) {
+            Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
+        } finally {
+            if (null != cursor) {
+                cursor.close();
+            }
+        }
+        return 0;
+    }
+
+    private static boolean isValidName(final String name) {
+        if (name != null && -1 == name.indexOf(Constants.CODE_COMMERCIAL_AT)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Updates the local state of the manager. This should be called when the callers
+     * are done with all the updates of the content provider successfully.
+     */
+    public void updateLocalState(final ArrayList<String> names) {
+        mContactCountAtLastRebuild.set(getContactCount());
+        mHashCodeAtLastRebuild.set(names.hashCode());
+    }
+
+    /**
+     * Performs any necessary cleanup.
+     */
+    public void close() {
+        mObserver.unregister();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index b341f62..6816f12 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -16,7 +16,8 @@
 
 package com.android.inputmethod.latin;
 
-import com.android.inputmethod.latin.settings.NativeSuggestOptions;
+import com.android.inputmethod.latin.common.NativeSuggestOptions;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.utils.JniUtils;
 
 import java.util.Locale;
@@ -27,20 +28,21 @@
     }
     // Must be equal to MAX_RESULTS in native/jni/src/defines.h
     private static final int MAX_RESULTS = 18;
-    public final int[] mInputCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+    public final int[] mInputCodePoints =
+            new int[DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH];
     public final int[][] mPrevWordCodePointArrays =
-            new int[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
+            new int[DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
     public final boolean[] mIsBeginningOfSentenceArray =
-            new boolean[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+            new boolean[DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
     public final int[] mOutputSuggestionCount = new int[1];
     public final int[] mOutputCodePoints =
-            new int[Constants.DICTIONARY_MAX_WORD_LENGTH * MAX_RESULTS];
+            new int[DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH * MAX_RESULTS];
     public final int[] mSpaceIndices = new int[MAX_RESULTS];
     public final int[] mOutputScores = new int[MAX_RESULTS];
     public final int[] mOutputTypes = new int[MAX_RESULTS];
     // Only one result is ever used
     public final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
-    public final float[] mInputOutputLanguageWeight = new float[1];
+    public final float[] mInputOutputWeightOfLangModelVsSpatialModel = new float[1];
 
     public final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
 
@@ -70,7 +72,7 @@
                 mNativeDicTraverseSession, dictionary, previousWord, previousWordLength);
     }
 
-    private final long createNativeDicTraverseSession(String locale, long dictSize) {
+    private static long createNativeDicTraverseSession(String locale, long dictSize) {
         return setDicTraverseSessionNative(locale, dictSize);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 560ced9..16dcb32 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -17,11 +17,14 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 
 import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Arrays;
+import java.util.HashSet;
 
 /**
  * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key
@@ -29,25 +32,24 @@
  */
 public abstract class Dictionary {
     public static final int NOT_A_PROBABILITY = -1;
-    public static final float NOT_A_LANGUAGE_WEIGHT = -1.0f;
+    public static final float NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL = -1.0f;
 
     // The following types do not actually come from real dictionary instances, so we create
     // corresponding instances.
     public static final String TYPE_USER_TYPED = "user_typed";
-    public static final Dictionary DICTIONARY_USER_TYPED = new PhonyDictionary(TYPE_USER_TYPED);
+    public static final PhonyDictionary DICTIONARY_USER_TYPED = new PhonyDictionary(TYPE_USER_TYPED);
 
     public static final String TYPE_APPLICATION_DEFINED = "application_defined";
-    public static final Dictionary DICTIONARY_APPLICATION_DEFINED =
+    public static final PhonyDictionary DICTIONARY_APPLICATION_DEFINED =
             new PhonyDictionary(TYPE_APPLICATION_DEFINED);
 
     public static final String TYPE_HARDCODED = "hardcoded"; // punctuation signs and such
-    public static final Dictionary DICTIONARY_HARDCODED =
+    public static final PhonyDictionary DICTIONARY_HARDCODED =
             new PhonyDictionary(TYPE_HARDCODED);
 
     // Spawned by resuming suggestions. Comes from a span that was in the TextView.
     public static final String TYPE_RESUMED = "resumed";
-    public static final Dictionary DICTIONARY_RESUMED =
-            new PhonyDictionary(TYPE_RESUMED);
+    public static final PhonyDictionary DICTIONARY_RESUMED = new PhonyDictionary(TYPE_RESUMED);
 
     // The following types of dictionary have actual functional instances. We don't need final
     // phony dictionary instances for them.
@@ -57,33 +59,44 @@
     public static final String TYPE_USER = "user";
     // User history dictionary internal to LatinIME.
     public static final String TYPE_USER_HISTORY = "history";
-    // Personalization dictionary.
-    public static final String TYPE_PERSONALIZATION = "personalization";
-    // Contextual dictionary.
-    public static final String TYPE_CONTEXTUAL = "contextual";
     public final String mDictType;
+    // The locale for this dictionary. May be null if unknown (phony dictionary for example).
+    public final Locale mLocale;
 
-    public Dictionary(final String dictType) {
+    /**
+     * Set out of the dictionary types listed above that are based on data specific to the user,
+     * e.g., the user's contacts.
+     */
+    private static final HashSet<String> sUserSpecificDictionaryTypes = new HashSet<>(Arrays.asList(
+            TYPE_USER_TYPED,
+            TYPE_USER,
+            TYPE_CONTACTS,
+            TYPE_USER_HISTORY));
+
+    public Dictionary(final String dictType, final Locale locale) {
         mDictType = dictType;
+        mLocale = locale;
     }
 
     /**
-     * Searches for suggestions for a given context. For the moment the context is only the
-     * previous word.
-     * @param composer the key sequence to match with coordinate info, as a WordComposer
-     * @param prevWordsInfo the information of previous words.
-     * @param proximityInfo the object for key proximity. May be ignored by some implementations.
+     * Searches for suggestions for a given context.
+     * @param composedData the key sequence to match with coordinate info
+     * @param ngramContext the context for n-gram.
+     * @param proximityInfoHandle the handle for key proximity. Is ignored by some implementations.
      * @param settingsValuesForSuggestion the settings values used for the suggestion.
      * @param sessionId the session id.
-     * @param inOutLanguageWeight the language weight used for generating suggestions.
-     * inOutLanguageWeight is a float array that has only one element. This can be updated when the
-     * different language weight is used.
+     * @param weightForLocale the weight given to this locale, to multiply the output scores for
+     * multilingual input.
+     * @param inOutWeightOfLangModelVsSpatialModel the weight of the language model as a ratio of
+     * the spatial model, used for generating suggestions. inOutWeightOfLangModelVsSpatialModel is
+     * a float array that has only one element. This can be updated when a different value is used.
      * @return the list of suggestions (possibly null if none)
      */
-    abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+    abstract public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+            final NgramContext ngramContext, final long proximityInfoHandle,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final int sessionId, final float[] inOutLanguageWeight);
+            final int sessionId, final float weightForLocale,
+            final float[] inOutWeightOfLangModelVsSpatialModel);
 
     /**
      * Checks if the given word has to be treated as a valid word. Please note that some
@@ -100,10 +113,18 @@
      */
     abstract public boolean isInDictionary(final String word);
 
+    /**
+     * Get the frequency of the word.
+     * @param word the word to get the frequency of.
+     */
     public int getFrequency(final String word) {
         return NOT_A_PROBABILITY;
     }
 
+    /**
+     * Get the maximum frequency of the word.
+     * @param word the word to get the maximum frequency of.
+     */
     public int getMaxFrequencyOfExactMatches(final String word) {
         return NOT_A_PROBABILITY;
     }
@@ -156,20 +177,30 @@
     }
 
     /**
+     * Whether this dictionary is based on data specific to the user, e.g., the user's contacts.
+     * @return Whether this dictionary is specific to the user.
+     */
+    public boolean isUserSpecific() {
+        return sUserSpecificDictionaryTypes.contains(mDictType);
+    }
+
+    /**
      * Not a true dictionary. A placeholder used to indicate suggestions that don't come from any
      * real dictionary.
      */
-    private static class PhonyDictionary extends Dictionary {
-        // This class is not publicly instantiable.
-        private PhonyDictionary(final String type) {
-            super(type);
+    @UsedForTesting
+    static class PhonyDictionary extends Dictionary {
+        @UsedForTesting
+        PhonyDictionary(final String type) {
+            super(type, null);
         }
 
         @Override
-        public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-                final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+        public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+                final NgramContext ngramContext, final long proximityInfoHandle,
                 final SettingsValuesForSuggestion settingsValuesForSuggestion,
-                final int sessionId, final float[] inOutLanguageWeight) {
+                final int sessionId, final float weightForLocale,
+                final float[] inOutWeightOfLangModelVsSpatialModel) {
             return null;
         }
 
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 2b4c54d..96575f6 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -18,13 +18,14 @@
 
 import android.util.Log;
 
-import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Locale;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -34,13 +35,14 @@
     private final String TAG = DictionaryCollection.class.getSimpleName();
     protected final CopyOnWriteArrayList<Dictionary> mDictionaries;
 
-    public DictionaryCollection(final String dictType) {
-        super(dictType);
+    public DictionaryCollection(final String dictType, final Locale locale) {
+        super(dictType, locale);
         mDictionaries = new CopyOnWriteArrayList<>();
     }
 
-    public DictionaryCollection(final String dictType, final Dictionary... dictionaries) {
-        super(dictType);
+    public DictionaryCollection(final String dictType, final Locale locale,
+            final Dictionary... dictionaries) {
+        super(dictType, locale);
         if (null == dictionaries) {
             mDictionaries = new CopyOnWriteArrayList<>();
         } else {
@@ -49,30 +51,32 @@
         }
     }
 
-    public DictionaryCollection(final String dictType, final Collection<Dictionary> dictionaries) {
-        super(dictType);
+    public DictionaryCollection(final String dictType, final Locale locale,
+            final Collection<Dictionary> dictionaries) {
+        super(dictType, locale);
         mDictionaries = new CopyOnWriteArrayList<>(dictionaries);
         mDictionaries.removeAll(Collections.singleton(null));
     }
 
     @Override
-    public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+    public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+            final NgramContext ngramContext, final long proximityInfoHandle,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final int sessionId, final float[] inOutLanguageWeight) {
+            final int sessionId, final float weightForLocale,
+            final float[] inOutWeightOfLangModelVsSpatialModel) {
         final CopyOnWriteArrayList<Dictionary> dictionaries = mDictionaries;
         if (dictionaries.isEmpty()) return null;
         // To avoid creating unnecessary objects, we get the list out of the first
         // dictionary and add the rest to it if not null, hence the get(0)
-        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composer,
-                prevWordsInfo, proximityInfo, settingsValuesForSuggestion, sessionId,
-                inOutLanguageWeight);
+        ArrayList<SuggestedWordInfo> suggestions = dictionaries.get(0).getSuggestions(composedData,
+                ngramContext, proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+                weightForLocale, inOutWeightOfLangModelVsSpatialModel);
         if (null == suggestions) suggestions = new ArrayList<>();
         final int length = dictionaries.size();
         for (int i = 1; i < length; ++ i) {
-            final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(composer,
-                    prevWordsInfo, proximityInfo, settingsValuesForSuggestion, sessionId,
-                    inOutLanguageWeight);
+            final ArrayList<SuggestedWordInfo> sugg = dictionaries.get(i).getSuggestions(
+                    composedData, ngramContext, proximityInfoHandle, settingsValuesForSuggestion,
+                    sessionId, weightForLocale, inOutWeightOfLangModelVsSpatialModel);
             if (null != sugg) suggestions.addAll(sugg);
         }
         return suggestions;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index fd1f51d..d5dff10 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -17,644 +17,160 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.personalization.ContextualDictionary;
-import com.android.inputmethod.latin.personalization.PersonalizationDataChunk;
-import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
-import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.common.ComposedData;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.DistracterFilter;
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingIsInDictionary;
-import com.android.inputmethod.latin.utils.ExecutorUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
 import com.android.inputmethod.latin.utils.SuggestionResults;
 
 import java.io.File;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-// TODO: Consolidate dictionaries in native code.
-public class DictionaryFacilitator {
-    public static final String TAG = DictionaryFacilitator.class.getSimpleName();
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
-    // HACK: This threshold is being used when adding a capitalized entry in the User History
-    // dictionary.
-    private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
+/**
+ * Interface that facilitates interaction with different kinds of dictionaries. Provides APIs to
+ * instantiate and select the correct dictionaries (based on language or account), update entries
+ * and fetch suggestions. Currently AndroidSpellCheckerService and LatinIME both use
+ * DictionaryFacilitator as a client for interacting with dictionaries.
+ */
+public interface DictionaryFacilitator {
 
-    private Dictionaries mDictionaries = new Dictionaries();
-    private boolean mIsUserDictEnabled = false;
-    private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
-    // To synchronize assigning mDictionaries to ensure closing dictionaries.
-    private final Object mLock = new Object();
-    private final DistracterFilter mDistracterFilter;
+    public static final String[] ALL_DICTIONARY_TYPES = new String[] {
+            Dictionary.TYPE_MAIN,
+            Dictionary.TYPE_USER_HISTORY,
+            Dictionary.TYPE_USER,
+            Dictionary.TYPE_CONTACTS};
 
-    private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS =
-            new String[] {
-                Dictionary.TYPE_MAIN,
-                Dictionary.TYPE_USER_HISTORY,
-                Dictionary.TYPE_PERSONALIZATION,
-                Dictionary.TYPE_USER,
-                Dictionary.TYPE_CONTACTS,
-                Dictionary.TYPE_CONTEXTUAL
-            };
-
-    public static final Map<String, Class<? extends ExpandableBinaryDictionary>>
-            DICT_TYPE_TO_CLASS = new HashMap<>();
-
-    static {
-        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER_HISTORY, UserHistoryDictionary.class);
-        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_PERSONALIZATION, PersonalizationDictionary.class);
-        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER, UserBinaryDictionary.class);
-        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTACTS, ContactsBinaryDictionary.class);
-        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTEXTUAL, ContextualDictionary.class);
-    }
-
-    private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
-    private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
-            new Class[] { Context.class, Locale.class, File.class, String.class };
-
-    private static final String[] SUB_DICT_TYPES =
-            Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS, 1 /* start */,
-                    DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS.length);
+    public static final String[] DYNAMIC_DICTIONARY_TYPES = new String[] {
+            Dictionary.TYPE_USER_HISTORY,
+            Dictionary.TYPE_USER,
+            Dictionary.TYPE_CONTACTS};
 
     /**
-     * Class contains dictionaries for a locale.
+     * {@link Dictionary#TYPE_USER} is deprecated, except for the spelling service.
      */
-    private static class Dictionaries {
-        public final Locale mLocale;
-        private Dictionary mMainDict;
-        public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap =
-                new ConcurrentHashMap<>();
+    public static final String[] DICTIONARY_TYPES_FOR_SPELLING = new String[] {
+            Dictionary.TYPE_MAIN,
+            Dictionary.TYPE_USER_HISTORY,
+            Dictionary.TYPE_USER,
+            Dictionary.TYPE_CONTACTS};
 
-        public Dictionaries() {
-            mLocale = null;
-        }
+    /**
+     * {@link Dictionary#TYPE_USER} is deprecated, except for the spelling service.
+     */
+    public static final String[] DICTIONARY_TYPES_FOR_SUGGESTIONS = new String[] {
+            Dictionary.TYPE_MAIN,
+            Dictionary.TYPE_USER_HISTORY,
+            Dictionary.TYPE_CONTACTS};
 
-        public Dictionaries(final Locale locale, final Dictionary mainDict,
-                final Map<String, ExpandableBinaryDictionary> subDicts) {
-            mLocale = locale;
-            // Main dictionary can be asynchronously loaded.
-            setMainDict(mainDict);
-            for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) {
-                setSubDict(entry.getKey(), entry.getValue());
-            }
-        }
+    /**
+     * Returns whether this facilitator is exactly for this locale.
+     *
+     * @param locale the locale to test against
+     */
+    boolean isForLocale(final Locale locale);
 
-        private void setSubDict(final String dictType, final ExpandableBinaryDictionary dict) {
-            if (dict != null) {
-                mSubDictMap.put(dictType, dict);
-            }
-        }
+    /**
+     * Returns whether this facilitator is exactly for this account.
+     *
+     * @param account the account to test against.
+     */
+    boolean isForAccount(@Nullable final String account);
 
-        public void setMainDict(final Dictionary mainDict) {
-            // Close old dictionary if exists. Main dictionary can be assigned multiple times.
-            final Dictionary oldDict = mMainDict;
-            mMainDict = mainDict;
-            if (oldDict != null && mainDict != oldDict) {
-                oldDict.close();
-            }
-        }
-
-        public Dictionary getDict(final String dictType) {
-            if (Dictionary.TYPE_MAIN.equals(dictType)) {
-                return mMainDict;
-            } else {
-                return getSubDict(dictType);
-            }
-        }
-
-        public ExpandableBinaryDictionary getSubDict(final String dictType) {
-            return mSubDictMap.get(dictType);
-        }
-
-        public boolean hasDict(final String dictType) {
-            if (Dictionary.TYPE_MAIN.equals(dictType)) {
-                return mMainDict != null;
-            } else {
-                return mSubDictMap.containsKey(dictType);
-            }
-        }
-
-        public void closeDict(final String dictType) {
-            final Dictionary dict;
-            if (Dictionary.TYPE_MAIN.equals(dictType)) {
-                dict = mMainDict;
-            } else {
-                dict = mSubDictMap.remove(dictType);
-            }
-            if (dict != null) {
-                dict.close();
-            }
-        }
+    interface DictionaryInitializationListener {
+        void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable);
     }
 
-    public interface DictionaryInitializationListener {
-        public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable);
-    }
+    /**
+     * Called every time {@link LatinIME} starts on a new text field.
+     * Dot not affect {@link AndroidSpellCheckerService}.
+     *
+     * WARNING: The service methods that call start/finish are very spammy.
+     */
+    void onStartInput();
 
-    public DictionaryFacilitator() {
-        mDistracterFilter = DistracterFilter.EMPTY_DISTRACTER_FILTER;
-    }
+    /**
+     * Called every time the {@link LatinIME} finishes with the current text field.
+     * May be followed by {@link #onStartInput} again in another text field,
+     * or it may be done for a while.
+     * Dot not affect {@link AndroidSpellCheckerService}.
+     *
+     * WARNING: The service methods that call start/finish are very spammy.
+     */
+    void onFinishInput();
 
-    public DictionaryFacilitator(final DistracterFilter distracterFilter) {
-        mDistracterFilter = distracterFilter;
-    }
+    boolean isActive();
 
-    public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
-        mDistracterFilter.updateEnabledSubtypes(enabledSubtypes);
-    }
+    Locale getLocale();
 
-    public Locale getLocale() {
-        return mDictionaries.mLocale;
-    }
-
-    private static ExpandableBinaryDictionary getSubDict(final String dictType,
-            final Context context, final Locale locale, final File dictFile,
-            final String dictNamePrefix) {
-        final Class<? extends ExpandableBinaryDictionary> dictClass =
-                DICT_TYPE_TO_CLASS.get(dictType);
-        if (dictClass == null) {
-            return null;
-        }
-        try {
-            final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME,
-                    DICT_FACTORY_METHOD_ARG_TYPES);
-            final Object dict = factoryMethod.invoke(null /* obj */,
-                    new Object[] { context, locale, dictFile, dictNamePrefix });
-            return (ExpandableBinaryDictionary) dict;
-        } catch (final NoSuchMethodException | SecurityException | IllegalAccessException
-                | IllegalArgumentException | InvocationTargetException e) {
-            Log.e(TAG, "Cannot create dictionary: " + dictType, e);
-            return null;
-        }
-    }
-
-    public void resetDictionaries(final Context context, final Locale newLocale,
-            final boolean useContactsDict, final boolean usePersonalizedDicts,
+    void resetDictionaries(
+            final Context context,
+            final Locale newLocale,
+            final boolean useContactsDict,
+            final boolean usePersonalizedDicts,
             final boolean forceReloadMainDictionary,
-            final DictionaryInitializationListener listener) {
-        resetDictionariesWithDictNamePrefix(context, newLocale, useContactsDict,
-                usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
-    }
-
-    public void resetDictionariesWithDictNamePrefix(final Context context, final Locale newLocale,
-            final boolean useContactsDict, final boolean usePersonalizedDicts,
-            final boolean forceReloadMainDictionary,
-            final DictionaryInitializationListener listener,
-            final String dictNamePrefix) {
-        final boolean localeHasBeenChanged = !newLocale.equals(mDictionaries.mLocale);
-        // We always try to have the main dictionary. Other dictionaries can be unused.
-        final boolean reloadMainDictionary = localeHasBeenChanged || forceReloadMainDictionary;
-        // TODO: Make subDictTypesToUse configurable by resource or a static final list.
-        final HashSet<String> subDictTypesToUse = new HashSet<>();
-        if (useContactsDict) {
-            subDictTypesToUse.add(Dictionary.TYPE_CONTACTS);
-        }
-        subDictTypesToUse.add(Dictionary.TYPE_USER);
-        if (usePersonalizedDicts) {
-            subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY);
-            subDictTypesToUse.add(Dictionary.TYPE_PERSONALIZATION);
-            subDictTypesToUse.add(Dictionary.TYPE_CONTEXTUAL);
-        }
-
-        final Dictionary newMainDict;
-        if (reloadMainDictionary) {
-            // The main dictionary will be asynchronously loaded.
-            newMainDict = null;
-        } else {
-            newMainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
-        }
-
-        final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
-        for (final String dictType : SUB_DICT_TYPES) {
-            if (!subDictTypesToUse.contains(dictType)) {
-                // This dictionary will not be used.
-                continue;
-            }
-            final ExpandableBinaryDictionary dict;
-            if (!localeHasBeenChanged && mDictionaries.hasDict(dictType)) {
-                // Continue to use current dictionary.
-                dict = mDictionaries.getSubDict(dictType);
-            } else {
-                // Start to use new dictionary.
-                dict = getSubDict(dictType, context, newLocale, null /* dictFile */,
-                        dictNamePrefix);
-            }
-            subDicts.put(dictType, dict);
-        }
-
-        // Replace Dictionaries.
-        final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict, subDicts);
-        final Dictionaries oldDictionaries;
-        synchronized (mLock) {
-            oldDictionaries = mDictionaries;
-            mDictionaries = newDictionaries;
-            mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
-            if (reloadMainDictionary) {
-                asyncReloadMainDictionary(context, newLocale, listener);
-            }
-        }
-        if (listener != null) {
-            listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
-        }
-        // Clean up old dictionaries.
-        if (reloadMainDictionary) {
-            oldDictionaries.closeDict(Dictionary.TYPE_MAIN);
-        }
-        for (final String dictType : SUB_DICT_TYPES) {
-            if (localeHasBeenChanged || !subDictTypesToUse.contains(dictType)) {
-                oldDictionaries.closeDict(dictType);
-            }
-        }
-        oldDictionaries.mSubDictMap.clear();
-    }
-
-    private void asyncReloadMainDictionary(final Context context, final Locale locale,
-            final DictionaryInitializationListener listener) {
-        final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
-        mLatchForWaitingLoadingMainDictionary = latchForWaitingLoadingMainDictionary;
-        ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
-            @Override
-            public void run() {
-                final Dictionary mainDict =
-                        DictionaryFactory.createMainDictionaryFromManager(context, locale);
-                synchronized (mLock) {
-                    if (locale.equals(mDictionaries.mLocale)) {
-                        mDictionaries.setMainDict(mainDict);
-                    } else {
-                        // Dictionary facilitator has been reset for another locale.
-                        mainDict.close();
-                    }
-                }
-                if (listener != null) {
-                    listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
-                }
-                latchForWaitingLoadingMainDictionary.countDown();
-            }
-        });
-    }
+            @Nullable final String account,
+            final String dictNamePrefix,
+            @Nullable final DictionaryInitializationListener listener);
 
     @UsedForTesting
-    public void resetDictionariesForTesting(final Context context, final Locale locale,
-            final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
-            final Map<String, Map<String, String>> additionalDictAttributes) {
-        Dictionary mainDictionary = null;
-        final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
+    void resetDictionariesForTesting(
+            final Context context,
+            final Locale locale,
+            final ArrayList<String> dictionaryTypes,
+            final HashMap<String, File> dictionaryFiles,
+            final Map<String, Map<String, String>> additionalDictAttributes,
+            @Nullable final String account);
 
-        for (final String dictType : dictionaryTypes) {
-            if (dictType.equals(Dictionary.TYPE_MAIN)) {
-                mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context, locale);
-            } else {
-                final File dictFile = dictionaryFiles.get(dictType);
-                final ExpandableBinaryDictionary dict = getSubDict(
-                        dictType, context, locale, dictFile, "" /* dictNamePrefix */);
-                if (additionalDictAttributes.containsKey(dictType)) {
-                    dict.clearAndFlushDictionaryWithAdditionalAttributes(
-                            additionalDictAttributes.get(dictType));
-                }
-                if (dict == null) {
-                    throw new RuntimeException("Unknown dictionary type: " + dictType);
-                }
-                dict.reloadDictionaryIfRequired();
-                dict.waitAllTasksForTests();
-                subDicts.put(dictType, dict);
-            }
-        }
-        mDictionaries = new Dictionaries(locale, mainDictionary, subDicts);
-    }
-
-    public void closeDictionaries() {
-        final Dictionaries dictionaries;
-        synchronized (mLock) {
-            dictionaries = mDictionaries;
-            mDictionaries = new Dictionaries();
-        }
-        for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
-            dictionaries.closeDict(dictType);
-        }
-        mDistracterFilter.close();
-    }
+    void closeDictionaries();
 
     @UsedForTesting
-    public ExpandableBinaryDictionary getSubDictForTesting(final String dictName) {
-        return mDictionaries.getSubDict(dictName);
-    }
+    ExpandableBinaryDictionary getSubDictForTesting(final String dictName);
 
-    // The main dictionary could have been loaded asynchronously.  Don't cache the return value
-    // of this method.
-    public boolean hasInitializedMainDictionary() {
-        final Dictionary mainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
-        return mainDict != null && mainDict.isInitialized();
-    }
+    // The main dictionaries are loaded asynchronously. Don't cache the return value
+    // of these methods.
+    boolean hasAtLeastOneInitializedMainDictionary();
 
-    public boolean hasPersonalizationDictionary() {
-        return mDictionaries.hasDict(Dictionary.TYPE_PERSONALIZATION);
-    }
+    boolean hasAtLeastOneUninitializedMainDictionary();
 
-    public void flushPersonalizationDictionary() {
-        final ExpandableBinaryDictionary personalizationDict =
-                mDictionaries.getSubDict(Dictionary.TYPE_PERSONALIZATION);
-        if (personalizationDict != null) {
-            personalizationDict.asyncFlushBinaryDictionary();
-        }
-    }
-
-    public void waitForLoadingMainDictionary(final long timeout, final TimeUnit unit)
-            throws InterruptedException {
-        mLatchForWaitingLoadingMainDictionary.await(timeout, unit);
-    }
+    void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit)
+            throws InterruptedException;
 
     @UsedForTesting
-    public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
-            throws InterruptedException {
-        waitForLoadingMainDictionary(timeout, unit);
-        final Map<String, ExpandableBinaryDictionary> dictMap = mDictionaries.mSubDictMap;
-        for (final ExpandableBinaryDictionary dict : dictMap.values()) {
-            dict.waitAllTasksForTests();
-        }
-    }
+    void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
+            throws InterruptedException;
 
-    public boolean isUserDictionaryEnabled() {
-        return mIsUserDictEnabled;
-    }
+    void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
+            @Nonnull final NgramContext ngramContext, final long timeStampInSeconds,
+            final boolean blockPotentiallyOffensive);
 
-    public void addWordToUserDictionary(final Context context, final String word) {
-        final Locale locale = getLocale();
-        if (locale == null) {
-            return;
-        }
-        UserBinaryDictionary.addWordToUserDictionary(context, locale, word);
-    }
-
-    public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
-            final PrevWordsInfo prevWordsInfo, final int timeStampInSeconds,
-            final boolean blockPotentiallyOffensive) {
-        final Dictionaries dictionaries = mDictionaries;
-        final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
-        PrevWordsInfo prevWordsInfoForCurrentWord = prevWordsInfo;
-        for (int i = 0; i < words.length; i++) {
-            final String currentWord = words[i];
-            final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
-            addWordToUserHistory(dictionaries, prevWordsInfoForCurrentWord, currentWord,
-                    wasCurrentWordAutoCapitalized, timeStampInSeconds, blockPotentiallyOffensive);
-            prevWordsInfoForCurrentWord =
-                    prevWordsInfoForCurrentWord.getNextPrevWordsInfo(new WordInfo(currentWord));
-        }
-    }
-
-    private void addWordToUserHistory(final Dictionaries dictionaries,
-            final PrevWordsInfo prevWordsInfo, final String word, final boolean wasAutoCapitalized,
-            final int timeStampInSeconds, final boolean blockPotentiallyOffensive) {
-        final ExpandableBinaryDictionary userHistoryDictionary =
-                dictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
-        if (userHistoryDictionary == null) {
-            return;
-        }
-        final int maxFreq = getFrequency(word);
-        if (maxFreq == 0 && blockPotentiallyOffensive) {
-            return;
-        }
-        final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
-        final String secondWord;
-        if (wasAutoCapitalized) {
-            if (isValidWord(word, false /* ignoreCase */)
-                    && !isValidWord(lowerCasedWord, false /* ignoreCase */)) {
-                // If the word was auto-capitalized and exists only as a capitalized word in the
-                // dictionary, then we must not downcase it before registering it. For example,
-                // the name of the contacts in start-of-sentence position would come here with the
-                // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version
-                // of that contact's name which would end up popping in suggestions.
-                secondWord = word;
-            } else {
-                // If however the word is not in the dictionary, or exists as a lower-case word
-                // only, then we consider that was a lower-case word that had been auto-capitalized.
-                secondWord = lowerCasedWord;
-            }
-        } else {
-            // HACK: We'd like to avoid adding the capitalized form of common words to the User
-            // History dictionary in order to avoid suggesting them until the dictionary
-            // consolidation is done.
-            // TODO: Remove this hack when ready.
-            final int lowerCaseFreqInMainDict = dictionaries.hasDict(Dictionary.TYPE_MAIN) ?
-                    dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) :
-                            Dictionary.NOT_A_PROBABILITY;
-            if (maxFreq < lowerCaseFreqInMainDict
-                    && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
-                // Use lower cased word as the word can be a distracter of the popular word.
-                secondWord = lowerCasedWord;
-            } else {
-                secondWord = word;
-            }
-        }
-        // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
-        // We don't add words with 0-frequency (assuming they would be profanity etc.).
-        final boolean isValid = maxFreq > 0;
-        UserHistoryDictionary.addToDictionary(userHistoryDictionary, prevWordsInfo, secondWord,
-                isValid, timeStampInSeconds,
-                new DistracterFilterCheckingIsInDictionary(
-                        mDistracterFilter, userHistoryDictionary));
-    }
-
-    private void removeWord(final String dictName, final String word) {
-        final ExpandableBinaryDictionary dictionary = mDictionaries.getSubDict(dictName);
-        if (dictionary != null) {
-            dictionary.removeUnigramEntryDynamically(word);
-        }
-    }
-
-    public void removeWordFromPersonalizedDicts(final String word) {
-        removeWord(Dictionary.TYPE_USER_HISTORY, word);
-        removeWord(Dictionary.TYPE_PERSONALIZATION, word);
-        removeWord(Dictionary.TYPE_CONTEXTUAL, word);
-    }
+    void unlearnFromUserHistory(final String word,
+            @Nonnull final NgramContext ngramContext, final long timeStampInSeconds,
+            final int eventType);
 
     // TODO: Revise the way to fusion suggestion results.
-    public SuggestionResults getSuggestionResults(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
-            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) {
-        final Dictionaries dictionaries = mDictionaries;
-        final SuggestionResults suggestionResults = new SuggestionResults(
-                dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS,
-                prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence);
-        final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
-        for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
-            final Dictionary dictionary = dictionaries.getDict(dictType);
-            if (null == dictionary) continue;
-            final ArrayList<SuggestedWordInfo> dictionarySuggestions =
-                    dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
-                            settingsValuesForSuggestion, sessionId, languageWeight);
-            if (null == dictionarySuggestions) continue;
-            suggestionResults.addAll(dictionarySuggestions);
-            if (null != suggestionResults.mRawSuggestions) {
-                suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
-            }
-        }
-        return suggestionResults;
-    }
+    @Nonnull SuggestionResults getSuggestionResults(final ComposedData composedData,
+            final NgramContext ngramContext, @Nonnull final Keyboard keyboard,
+            final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId,
+            final int inputStyle);
 
-    public boolean isValidWord(final String word, final boolean ignoreCase) {
-        if (TextUtils.isEmpty(word)) {
-            return false;
-        }
-        final Dictionaries dictionaries = mDictionaries;
-        if (dictionaries.mLocale == null) {
-            return false;
-        }
-        final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
-        for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
-            final Dictionary dictionary = dictionaries.getDict(dictType);
-            // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
-            // would be immutable once it's finished initializing, but concretely a null test is
-            // probably good enough for the time being.
-            if (null == dictionary) continue;
-            if (dictionary.isValidWord(word)
-                    || (ignoreCase && dictionary.isValidWord(lowerCasedWord))) {
-                return true;
-            }
-        }
-        return false;
-    }
+    boolean isValidSpellingWord(final String word);
 
-    private int getFrequencyInternal(final String word,
-            final boolean isGettingMaxFrequencyOfExactMatches) {
-        if (TextUtils.isEmpty(word)) {
-            return Dictionary.NOT_A_PROBABILITY;
-        }
-        int maxFreq = Dictionary.NOT_A_PROBABILITY;
-        final Dictionaries dictionaries = mDictionaries;
-        for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
-            final Dictionary dictionary = dictionaries.getDict(dictType);
-            if (dictionary == null) continue;
-            final int tempFreq;
-            if (isGettingMaxFrequencyOfExactMatches) {
-                tempFreq = dictionary.getMaxFrequencyOfExactMatches(word);
-            } else {
-                tempFreq = dictionary.getFrequency(word);
-            }
-            if (tempFreq >= maxFreq) {
-                maxFreq = tempFreq;
-            }
-        }
-        return maxFreq;
-    }
+    boolean isValidSuggestionWord(final String word);
 
-    public int getFrequency(final String word) {
-        return getFrequencyInternal(word, false /* isGettingMaxFrequencyOfExactMatches */);
-    }
+    void clearUserHistoryDictionary(final Context context);
 
-    public int getMaxFrequencyOfExactMatches(final String word) {
-        return getFrequencyInternal(word, true /* isGettingMaxFrequencyOfExactMatches */);
-    }
+    String dump(final Context context);
 
-    private void clearSubDictionary(final String dictName) {
-        final ExpandableBinaryDictionary dictionary = mDictionaries.getSubDict(dictName);
-        if (dictionary != null) {
-            dictionary.clear();
-        }
-    }
+    void dumpDictionaryForDebug(final String dictName);
 
-    public void clearUserHistoryDictionary() {
-        clearSubDictionary(Dictionary.TYPE_USER_HISTORY);
-    }
-
-    // This method gets called only when the IME receives a notification to remove the
-    // personalization dictionary.
-    public void clearPersonalizationDictionary() {
-        clearSubDictionary(Dictionary.TYPE_PERSONALIZATION);
-    }
-
-    public void clearContextualDictionary() {
-        clearSubDictionary(Dictionary.TYPE_CONTEXTUAL);
-    }
-
-    public void addEntriesToPersonalizationDictionary(
-            final PersonalizationDataChunk personalizationDataChunk,
-            final SpacingAndPunctuations spacingAndPunctuations,
-            final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
-        final ExpandableBinaryDictionary personalizationDict =
-                mDictionaries.getSubDict(Dictionary.TYPE_PERSONALIZATION);
-        if (personalizationDict == null) {
-            if (callback != null) {
-                callback.onFinished();
-            }
-            return;
-        }
-        final ArrayList<LanguageModelParam> languageModelParams =
-                LanguageModelParam.createLanguageModelParamsFrom(
-                        personalizationDataChunk.mTokens,
-                        personalizationDataChunk.mTimestampInSeconds,
-                        this /* dictionaryFacilitator */, spacingAndPunctuations,
-                        new DistracterFilterCheckingIsInDictionary(
-                                mDistracterFilter, personalizationDict));
-        if (languageModelParams == null || languageModelParams.isEmpty()) {
-            if (callback != null) {
-                callback.onFinished();
-            }
-            return;
-        }
-        personalizationDict.addMultipleDictionaryEntriesDynamically(languageModelParams, callback);
-    }
-
-    public void addPhraseToContextualDictionary(final String[] phrase, final int probability,
-            final int bigramProbabilityForWords, final int bigramProbabilityForPhrases) {
-        final ExpandableBinaryDictionary contextualDict =
-                mDictionaries.getSubDict(Dictionary.TYPE_CONTEXTUAL);
-        if (contextualDict == null) {
-            return;
-        }
-        PrevWordsInfo prevWordsInfo = PrevWordsInfo.BEGINNING_OF_SENTENCE;
-        for (int i = 0; i < phrase.length; i++) {
-            final String[] subPhrase = Arrays.copyOfRange(phrase, i /* start */, phrase.length);
-            final String subPhraseStr = TextUtils.join(Constants.WORD_SEPARATOR, subPhrase);
-            contextualDict.addUnigramEntryWithCheckingDistracter(
-                    subPhraseStr, probability, null /* shortcutTarget */,
-                    Dictionary.NOT_A_PROBABILITY /* shortcutFreq */,
-                    false /* isNotAWord */, false /* isBlacklisted */,
-                    BinaryDictionary.NOT_A_VALID_TIMESTAMP,
-                    DistracterFilter.EMPTY_DISTRACTER_FILTER);
-            contextualDict.addNgramEntry(prevWordsInfo, subPhraseStr,
-                    bigramProbabilityForPhrases, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-
-            if (i < phrase.length - 1) {
-                contextualDict.addUnigramEntryWithCheckingDistracter(
-                        phrase[i], probability, null /* shortcutTarget */,
-                        Dictionary.NOT_A_PROBABILITY /* shortcutFreq */,
-                        false /* isNotAWord */, false /* isBlacklisted */,
-                        BinaryDictionary.NOT_A_VALID_TIMESTAMP,
-                        DistracterFilter.EMPTY_DISTRACTER_FILTER);
-                contextualDict.addNgramEntry(prevWordsInfo, phrase[i],
-                        bigramProbabilityForWords, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-            }
-            prevWordsInfo =
-                    prevWordsInfo.getNextPrevWordsInfo(new PrevWordsInfo.WordInfo(phrase[i]));
-        }
-    }
-
-    public void dumpDictionaryForDebug(final String dictName) {
-        final ExpandableBinaryDictionary dictToDump = mDictionaries.getSubDict(dictName);
-        if (dictToDump == null) {
-            Log.e(TAG, "Cannot dump " + dictName + ". "
-                    + "The dictionary is not being used for suggestion or cannot be dumped.");
-            return;
-        }
-        dictToDump.dumpAllWordsForDebug();
-    }
+    @Nonnull List<DictionaryStats> getDictionaryStats(final Context context);
 }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
new file mode 100644
index 0000000..9ce92da
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
@@ -0,0 +1,661 @@
+/*
+7 * 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;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
+import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
+import com.android.inputmethod.latin.utils.ExecutorUtils;
+import com.android.inputmethod.latin.utils.SuggestionResults;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Facilitates interaction with different kinds of dictionaries. Provides APIs
+ * to instantiate and select the correct dictionaries (based on language or account),
+ * update entries and fetch suggestions.
+ *
+ * Currently AndroidSpellCheckerService and LatinIME both use DictionaryFacilitator as
+ * a client for interacting with dictionaries.
+ */
+public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
+    // TODO: Consolidate dictionaries in native code.
+    public static final String TAG = DictionaryFacilitatorImpl.class.getSimpleName();
+
+    // HACK: This threshold is being used when adding a capitalized entry in the User History
+    // dictionary.
+    private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
+
+    private DictionaryGroup mDictionaryGroup = new DictionaryGroup();
+    private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
+    // To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
+    private final Object mLock = new Object();
+
+    public static final Map<String, Class<? extends ExpandableBinaryDictionary>>
+            DICT_TYPE_TO_CLASS = new HashMap<>();
+
+    static {
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER_HISTORY, UserHistoryDictionary.class);
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER, UserBinaryDictionary.class);
+        DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTACTS, ContactsBinaryDictionary.class);
+    }
+
+    private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
+    private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
+            new Class[] { Context.class, Locale.class, File.class, String.class, String.class };
+
+    @Override
+    public boolean isForLocale(final Locale locale) {
+        return locale != null && locale.equals(mDictionaryGroup.mLocale);
+    }
+
+    /**
+     * Returns whether this facilitator is exactly for this account.
+     *
+     * @param account the account to test against.
+     */
+    public boolean isForAccount(@Nullable final String account) {
+        return TextUtils.equals(mDictionaryGroup.mAccount, account);
+    }
+
+    /**
+     * A group of dictionaries that work together for a single language.
+     */
+    private static class DictionaryGroup {
+        // TODO: Add null analysis annotations.
+        // TODO: Run evaluation to determine a reasonable value for these constants. The current
+        // values are ad-hoc and chosen without any particular care or methodology.
+        public static final float WEIGHT_FOR_MOST_PROBABLE_LANGUAGE = 1.0f;
+        public static final float WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.95f;
+        public static final float WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE = 0.6f;
+
+        /**
+         * The locale associated with the dictionary group.
+         */
+        @Nullable public final Locale mLocale;
+
+        /**
+         * The user account associated with the dictionary group.
+         */
+        @Nullable public final String mAccount;
+
+        @Nullable private Dictionary mMainDict;
+        // Confidence that the most probable language is actually the language the user is
+        // typing in. For now, this is simply the number of times a word from this language
+        // has been committed in a row.
+        private int mConfidence = 0;
+
+        public float mWeightForTypingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
+        public float mWeightForGesturingInLocale = WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
+        public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap =
+                new ConcurrentHashMap<>();
+
+        public DictionaryGroup() {
+            this(null /* locale */, null /* mainDict */, null /* account */,
+                    Collections.<String, ExpandableBinaryDictionary>emptyMap() /* subDicts */);
+        }
+
+        public DictionaryGroup(@Nullable final Locale locale,
+                @Nullable final Dictionary mainDict,
+                @Nullable final String account,
+                final Map<String, ExpandableBinaryDictionary> subDicts) {
+            mLocale = locale;
+            mAccount = account;
+            // The main dictionary can be asynchronously loaded.
+            setMainDict(mainDict);
+            for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) {
+                setSubDict(entry.getKey(), entry.getValue());
+            }
+        }
+
+        private void setSubDict(final String dictType, final ExpandableBinaryDictionary dict) {
+            if (dict != null) {
+                mSubDictMap.put(dictType, dict);
+            }
+        }
+
+        public void setMainDict(final Dictionary mainDict) {
+            // Close old dictionary if exists. Main dictionary can be assigned multiple times.
+            final Dictionary oldDict = mMainDict;
+            mMainDict = mainDict;
+            if (oldDict != null && mainDict != oldDict) {
+                oldDict.close();
+            }
+        }
+
+        public Dictionary getDict(final String dictType) {
+            if (Dictionary.TYPE_MAIN.equals(dictType)) {
+                return mMainDict;
+            }
+            return getSubDict(dictType);
+        }
+
+        public ExpandableBinaryDictionary getSubDict(final String dictType) {
+            return mSubDictMap.get(dictType);
+        }
+
+        public boolean hasDict(final String dictType, @Nullable final String account) {
+            if (Dictionary.TYPE_MAIN.equals(dictType)) {
+                return mMainDict != null;
+            }
+            if (Dictionary.TYPE_USER_HISTORY.equals(dictType) &&
+                    !TextUtils.equals(account, mAccount)) {
+                // If the dictionary type is user history, & if the account doesn't match,
+                // return immediately. If the account matches, continue looking it up in the
+                // sub dictionary map.
+                return false;
+            }
+            return mSubDictMap.containsKey(dictType);
+        }
+
+        public void closeDict(final String dictType) {
+            final Dictionary dict;
+            if (Dictionary.TYPE_MAIN.equals(dictType)) {
+                dict = mMainDict;
+            } else {
+                dict = mSubDictMap.remove(dictType);
+            }
+            if (dict != null) {
+                dict.close();
+            }
+        }
+    }
+
+    public DictionaryFacilitatorImpl() {
+    }
+
+    @Override
+    public void onStartInput() {
+    }
+
+    @Override
+    public void onFinishInput() {
+    }
+
+    @Override
+    public boolean isActive() {
+        return mDictionaryGroup.mLocale != null;
+    }
+
+    @Override
+    public Locale getLocale() {
+        return mDictionaryGroup.mLocale;
+    }
+
+    @Nullable
+    private static ExpandableBinaryDictionary getSubDict(final String dictType,
+            final Context context, final Locale locale, final File dictFile,
+            final String dictNamePrefix, @Nullable final String account) {
+        final Class<? extends ExpandableBinaryDictionary> dictClass =
+                DICT_TYPE_TO_CLASS.get(dictType);
+        if (dictClass == null) {
+            return null;
+        }
+        try {
+            final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME,
+                    DICT_FACTORY_METHOD_ARG_TYPES);
+            final Object dict = factoryMethod.invoke(null /* obj */,
+                    new Object[] { context, locale, dictFile, dictNamePrefix, account });
+            return (ExpandableBinaryDictionary) dict;
+        } catch (final NoSuchMethodException | SecurityException | IllegalAccessException
+                | IllegalArgumentException | InvocationTargetException e) {
+            Log.e(TAG, "Cannot create dictionary: " + dictType, e);
+            return null;
+        }
+    }
+
+    @Nullable
+    static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup dictionaryGroup,
+            final Locale locale) {
+        return locale.equals(dictionaryGroup.mLocale) ? dictionaryGroup : null;
+    }
+
+    @Override
+    public void resetDictionaries(
+            final Context context,
+            final Locale newLocale,
+            final boolean useContactsDict,
+            final boolean usePersonalizedDicts,
+            final boolean forceReloadMainDictionary,
+            @Nullable final String account,
+            final String dictNamePrefix,
+            @Nullable final DictionaryInitializationListener listener) {
+        final HashMap<Locale, ArrayList<String>> existingDictionariesToCleanup = new HashMap<>();
+        // TODO: Make subDictTypesToUse configurable by resource or a static final list.
+        final HashSet<String> subDictTypesToUse = new HashSet<>();
+        subDictTypesToUse.add(Dictionary.TYPE_USER);
+        if (useContactsDict) {
+            subDictTypesToUse.add(Dictionary.TYPE_CONTACTS);
+        }
+        if (usePersonalizedDicts) {
+            subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY);
+        }
+
+        // Gather all dictionaries. We'll remove them from the list to clean up later.
+        final ArrayList<String> dictTypeForLocale = new ArrayList<>();
+        existingDictionariesToCleanup.put(newLocale, dictTypeForLocale);
+        final DictionaryGroup currentDictionaryGroupForLocale =
+                findDictionaryGroupWithLocale(mDictionaryGroup, newLocale);
+        if (currentDictionaryGroupForLocale != null) {
+            for (final String dictType : DYNAMIC_DICTIONARY_TYPES) {
+                if (currentDictionaryGroupForLocale.hasDict(dictType, account)) {
+                    dictTypeForLocale.add(dictType);
+                }
+            }
+            if (currentDictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
+                dictTypeForLocale.add(Dictionary.TYPE_MAIN);
+            }
+        }
+
+        final DictionaryGroup dictionaryGroupForLocale =
+                findDictionaryGroupWithLocale(mDictionaryGroup, newLocale);
+        final ArrayList<String> dictTypesToCleanupForLocale =
+                existingDictionariesToCleanup.get(newLocale);
+        final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
+
+        final Dictionary mainDict;
+        if (forceReloadMainDictionary || noExistingDictsForThisLocale
+                || !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
+            mainDict = null;
+        } else {
+            mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN);
+            dictTypesToCleanupForLocale.remove(Dictionary.TYPE_MAIN);
+        }
+
+        final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
+        for (final String subDictType : subDictTypesToUse) {
+            final ExpandableBinaryDictionary subDict;
+            if (noExistingDictsForThisLocale
+                    || !dictionaryGroupForLocale.hasDict(subDictType, account)) {
+                // Create a new dictionary.
+                subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */,
+                        dictNamePrefix, account);
+            } else {
+                // Reuse the existing dictionary, and don't close it at the end
+                subDict = dictionaryGroupForLocale.getSubDict(subDictType);
+                dictTypesToCleanupForLocale.remove(subDictType);
+            }
+            subDicts.put(subDictType, subDict);
+        }
+        DictionaryGroup newDictionaryGroup =
+                new DictionaryGroup(newLocale, mainDict, account, subDicts);
+
+        // Replace Dictionaries.
+        final DictionaryGroup oldDictionaryGroup;
+        synchronized (mLock) {
+            oldDictionaryGroup = mDictionaryGroup;
+            mDictionaryGroup = newDictionaryGroup;
+            if (hasAtLeastOneUninitializedMainDictionary()) {
+                asyncReloadUninitializedMainDictionaries(context, newLocale, listener);
+            }
+        }
+        if (listener != null) {
+            listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary());
+        }
+
+        // Clean up old dictionaries.
+        for (final Locale localeToCleanUp : existingDictionariesToCleanup.keySet()) {
+            final ArrayList<String> dictTypesToCleanUp =
+                    existingDictionariesToCleanup.get(localeToCleanUp);
+            final DictionaryGroup dictionarySetToCleanup =
+                    findDictionaryGroupWithLocale(oldDictionaryGroup, localeToCleanUp);
+            for (final String dictType : dictTypesToCleanUp) {
+                dictionarySetToCleanup.closeDict(dictType);
+            }
+        }
+    }
+
+    private void asyncReloadUninitializedMainDictionaries(final Context context,
+            final Locale locale, final DictionaryInitializationListener listener) {
+        final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
+        mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary;
+        ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(new Runnable() {
+            @Override
+            public void run() {
+                doReloadUninitializedMainDictionaries(
+                        context, locale, listener, latchForWaitingLoadingMainDictionary);
+            }
+        });
+    }
+
+    void doReloadUninitializedMainDictionaries(final Context context, final Locale locale,
+            final DictionaryInitializationListener listener,
+            final CountDownLatch latchForWaitingLoadingMainDictionary) {
+        final DictionaryGroup dictionaryGroup =
+                findDictionaryGroupWithLocale(mDictionaryGroup, locale);
+        if (null == dictionaryGroup) {
+            // This should never happen, but better safe than crashy
+            Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
+            return;
+        }
+        final Dictionary mainDict =
+                DictionaryFactory.createMainDictionaryFromManager(context, locale);
+        synchronized (mLock) {
+            if (locale.equals(dictionaryGroup.mLocale)) {
+                dictionaryGroup.setMainDict(mainDict);
+            } else {
+                // Dictionary facilitator has been reset for another locale.
+                mainDict.close();
+            }
+        }
+        if (listener != null) {
+            listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary());
+        }
+        latchForWaitingLoadingMainDictionary.countDown();
+    }
+
+    @UsedForTesting
+    public void resetDictionariesForTesting(final Context context, final Locale locale,
+            final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
+            final Map<String, Map<String, String>> additionalDictAttributes,
+            @Nullable final String account) {
+        Dictionary mainDictionary = null;
+        final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
+
+        for (final String dictType : dictionaryTypes) {
+            if (dictType.equals(Dictionary.TYPE_MAIN)) {
+                mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context,
+                        locale);
+            } else {
+                final File dictFile = dictionaryFiles.get(dictType);
+                final ExpandableBinaryDictionary dict = getSubDict(
+                        dictType, context, locale, dictFile, "" /* dictNamePrefix */, account);
+                if (additionalDictAttributes.containsKey(dictType)) {
+                    dict.clearAndFlushDictionaryWithAdditionalAttributes(
+                            additionalDictAttributes.get(dictType));
+                }
+                if (dict == null) {
+                    throw new RuntimeException("Unknown dictionary type: " + dictType);
+                }
+                dict.reloadDictionaryIfRequired();
+                dict.waitAllTasksForTests();
+                subDicts.put(dictType, dict);
+            }
+        }
+        mDictionaryGroup = new DictionaryGroup(locale, mainDictionary, account, subDicts);
+    }
+
+    public void closeDictionaries() {
+        final DictionaryGroup dictionaryGroupToClose;
+        synchronized (mLock) {
+            dictionaryGroupToClose = mDictionaryGroup;
+            mDictionaryGroup = new DictionaryGroup();
+        }
+        for (final String dictType : ALL_DICTIONARY_TYPES) {
+            dictionaryGroupToClose.closeDict(dictType);
+        }
+    }
+
+    @UsedForTesting
+    public ExpandableBinaryDictionary getSubDictForTesting(final String dictName) {
+        return mDictionaryGroup.getSubDict(dictName);
+    }
+
+    // The main dictionaries are loaded asynchronously.  Don't cache the return value
+    // of these methods.
+    public boolean hasAtLeastOneInitializedMainDictionary() {
+        final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN);
+        if (mainDict != null && mainDict.isInitialized()) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean hasAtLeastOneUninitializedMainDictionary() {
+        final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN);
+        if (mainDict == null || !mainDict.isInitialized()) {
+            return true;
+        }
+        return false;
+    }
+
+    public void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit)
+            throws InterruptedException {
+        mLatchForWaitingLoadingMainDictionaries.await(timeout, unit);
+    }
+
+    @UsedForTesting
+    public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
+            throws InterruptedException {
+        waitForLoadingMainDictionaries(timeout, unit);
+        for (final ExpandableBinaryDictionary dict : mDictionaryGroup.mSubDictMap.values()) {
+            dict.waitAllTasksForTests();
+        }
+    }
+
+    public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
+            @Nonnull final NgramContext ngramContext, final long timeStampInSeconds,
+            final boolean blockPotentiallyOffensive) {
+        final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
+        NgramContext ngramContextForCurrentWord = ngramContext;
+        for (int i = 0; i < words.length; i++) {
+            final String currentWord = words[i];
+            final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
+            addWordToUserHistory(mDictionaryGroup, ngramContextForCurrentWord, currentWord,
+                    wasCurrentWordAutoCapitalized, (int) timeStampInSeconds,
+                    blockPotentiallyOffensive);
+            ngramContextForCurrentWord =
+                    ngramContextForCurrentWord.getNextNgramContext(new WordInfo(currentWord));
+        }
+    }
+
+    private void addWordToUserHistory(final DictionaryGroup dictionaryGroup,
+            final NgramContext ngramContext, final String word, final boolean wasAutoCapitalized,
+            final int timeStampInSeconds, final boolean blockPotentiallyOffensive) {
+        final ExpandableBinaryDictionary userHistoryDictionary =
+                dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY);
+        if (userHistoryDictionary == null || !isForLocale(userHistoryDictionary.mLocale)) {
+            return;
+        }
+        final int maxFreq = getFrequency(word);
+        if (maxFreq == 0 && blockPotentiallyOffensive) {
+            return;
+        }
+        final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale);
+        final String secondWord;
+        if (wasAutoCapitalized) {
+            if (isValidSuggestionWord(word) && !isValidSuggestionWord(lowerCasedWord)) {
+                // If the word was auto-capitalized and exists only as a capitalized word in the
+                // dictionary, then we must not downcase it before registering it. For example,
+                // the name of the contacts in start-of-sentence position would come here with the
+                // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version
+                // of that contact's name which would end up popping in suggestions.
+                secondWord = word;
+            } else {
+                // If however the word is not in the dictionary, or exists as a lower-case word
+                // only, then we consider that was a lower-case word that had been auto-capitalized.
+                secondWord = lowerCasedWord;
+            }
+        } else {
+            // HACK: We'd like to avoid adding the capitalized form of common words to the User
+            // History dictionary in order to avoid suggesting them until the dictionary
+            // consolidation is done.
+            // TODO: Remove this hack when ready.
+            final int lowerCaseFreqInMainDict = dictionaryGroup.hasDict(Dictionary.TYPE_MAIN,
+                    null /* account */) ?
+                    dictionaryGroup.getDict(Dictionary.TYPE_MAIN).getFrequency(lowerCasedWord) :
+                    Dictionary.NOT_A_PROBABILITY;
+            if (maxFreq < lowerCaseFreqInMainDict
+                    && lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
+                // Use lower cased word as the word can be a distracter of the popular word.
+                secondWord = lowerCasedWord;
+            } else {
+                secondWord = word;
+            }
+        }
+        // We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
+        // We don't add words with 0-frequency (assuming they would be profanity etc.).
+        final boolean isValid = maxFreq > 0;
+        UserHistoryDictionary.addToDictionary(userHistoryDictionary, ngramContext, secondWord,
+                isValid, timeStampInSeconds);
+    }
+
+    private void removeWord(final String dictName, final String word) {
+        final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
+        if (dictionary != null) {
+            dictionary.removeUnigramEntryDynamically(word);
+        }
+    }
+
+    @Override
+    public void unlearnFromUserHistory(final String word,
+            @Nonnull final NgramContext ngramContext, final long timeStampInSeconds,
+            final int eventType) {
+        // TODO: Decide whether or not to remove the word on EVENT_BACKSPACE.
+        if (eventType != Constants.EVENT_BACKSPACE) {
+            removeWord(Dictionary.TYPE_USER_HISTORY, word);
+        }
+    }
+
+    // TODO: Revise the way to fusion suggestion results.
+    @Override
+    @Nonnull public SuggestionResults getSuggestionResults(ComposedData composedData,
+            NgramContext ngramContext, @Nonnull final Keyboard keyboard,
+            SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId,
+            int inputStyle) {
+        long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo();
+        final SuggestionResults suggestionResults = new SuggestionResults(
+                SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(),
+                false /* firstSuggestionExceedsConfidenceThreshold */);
+        final float[] weightOfLangModelVsSpatialModel =
+                new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL };
+        for (final String dictType : DICTIONARY_TYPES_FOR_SUGGESTIONS) {
+            final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
+            if (null == dictionary) continue;
+            final float weightForLocale = composedData.mIsBatchMode
+                    ? mDictionaryGroup.mWeightForGesturingInLocale
+                    : mDictionaryGroup.mWeightForTypingInLocale;
+            final ArrayList<SuggestedWordInfo> dictionarySuggestions =
+                    dictionary.getSuggestions(composedData, ngramContext,
+                            proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+                            weightForLocale, weightOfLangModelVsSpatialModel);
+            if (null == dictionarySuggestions) continue;
+            suggestionResults.addAll(dictionarySuggestions);
+            if (null != suggestionResults.mRawSuggestions) {
+                suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
+            }
+        }
+        return suggestionResults;
+    }
+
+    public boolean isValidSpellingWord(final String word) {
+        return isValidWord(word, DICTIONARY_TYPES_FOR_SPELLING);
+    }
+
+    public boolean isValidSuggestionWord(final String word) {
+        return isValidWord(word, DICTIONARY_TYPES_FOR_SUGGESTIONS);
+    }
+
+    private boolean isValidWord(final String word, final String[] dictionariesToCheck) {
+        if (TextUtils.isEmpty(word)) {
+            return false;
+        }
+        if (mDictionaryGroup.mLocale == null) {
+            return false;
+        }
+        for (final String dictType : dictionariesToCheck) {
+            final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
+            // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
+            // would be immutable once it's finished initializing, but concretely a null test is
+            // probably good enough for the time being.
+            if (null == dictionary) continue;
+            if (dictionary.isValidWord(word)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private int getFrequency(final String word) {
+        if (TextUtils.isEmpty(word)) {
+            return Dictionary.NOT_A_PROBABILITY;
+        }
+        int maxFreq = Dictionary.NOT_A_PROBABILITY;
+        for (final String dictType : ALL_DICTIONARY_TYPES) {
+            final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
+            if (dictionary == null) continue;
+            final int tempFreq = dictionary.getFrequency(word);
+            if (tempFreq >= maxFreq) {
+                maxFreq = tempFreq;
+            }
+        }
+        return maxFreq;
+    }
+
+    private void clearSubDictionary(final String dictName) {
+        final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
+        if (dictionary != null) {
+            dictionary.clear();
+        }
+    }
+
+    @Override
+    public void clearUserHistoryDictionary(final Context context) {
+        clearSubDictionary(Dictionary.TYPE_USER_HISTORY);
+    }
+
+    @Override
+    public void dumpDictionaryForDebug(final String dictName) {
+        final ExpandableBinaryDictionary dictToDump = mDictionaryGroup.getSubDict(dictName);
+        if (dictToDump == null) {
+            Log.e(TAG, "Cannot dump " + dictName + ". "
+                    + "The dictionary is not being used for suggestion or cannot be dumped.");
+            return;
+        }
+        dictToDump.dumpAllWordsForDebug();
+    }
+
+    @Override
+    @Nonnull public List<DictionaryStats> getDictionaryStats(final Context context) {
+        final ArrayList<DictionaryStats> statsOfEnabledSubDicts = new ArrayList<>();
+        for (final String dictType : DYNAMIC_DICTIONARY_TYPES) {
+            final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictType);
+            if (dictionary == null) continue;
+            statsOfEnabledSubDicts.add(dictionary.getDictionaryStats());
+        }
+        return statsOfEnabledSubDicts;
+    }
+
+    @Override
+    public String dump(final Context context) {
+        return "";
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java
new file mode 100644
index 0000000..cbaf6ea
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+import android.content.Context;
+import android.util.Log;
+
+/**
+ * Cache for dictionary facilitators of multiple locales.
+ * This class automatically creates and releases up to 3 facilitator instances using LRU policy.
+ */
+public class DictionaryFacilitatorLruCache {
+    private static final String TAG = "DictionaryFacilitatorLruCache";
+    private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
+    private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
+
+    private final Context mContext;
+    private final String mDictionaryNamePrefix;
+    private final Object mLock = new Object();
+    private final DictionaryFacilitator mDictionaryFacilitator;
+    private boolean mUseContactsDictionary;
+    private Locale mLocale;
+
+    public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) {
+        mContext = context;
+        mDictionaryNamePrefix = dictionaryNamePrefix;
+        mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(
+                true /* isNeededForSpellChecking */);
+    }
+
+    private static void waitForLoadingMainDictionary(
+            final DictionaryFacilitator dictionaryFacilitator) {
+        for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
+            try {
+                dictionaryFacilitator.waitForLoadingMainDictionaries(
+                        WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
+                return;
+            } catch (final InterruptedException e) {
+                Log.i(TAG, "Interrupted during waiting for loading main dictionary.", e);
+                if (i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT - 1) {
+                    Log.i(TAG, "Retry", e);
+                } else {
+                    Log.w(TAG, "Give up retrying. Retried "
+                            + MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT + " times.", e);
+                }
+            }
+        }
+    }
+
+    private void resetDictionariesForLocaleLocked() {
+        // Nothing to do if the locale is null.  This would be the case before any get() calls.
+        if (mLocale != null) {
+          // Note: Given that personalized dictionaries are not used here; we can pass null account.
+          mDictionaryFacilitator.resetDictionaries(mContext, mLocale,
+              mUseContactsDictionary, false /* usePersonalizedDicts */,
+              false /* forceReloadMainDictionary */, null /* account */,
+              mDictionaryNamePrefix, null /* listener */);
+        }
+    }
+
+    public void setUseContactsDictionary(final boolean useContactsDictionary) {
+        synchronized (mLock) {
+            if (mUseContactsDictionary == useContactsDictionary) {
+                // The value has not been changed.
+                return;
+            }
+            mUseContactsDictionary = useContactsDictionary;
+            resetDictionariesForLocaleLocked();
+            waitForLoadingMainDictionary(mDictionaryFacilitator);
+        }
+    }
+
+    public DictionaryFacilitator get(final Locale locale) {
+        synchronized (mLock) {
+            if (!mDictionaryFacilitator.isForLocale(locale)) {
+                mLocale = locale;
+                resetDictionariesForLocaleLocked();
+            }
+            waitForLoadingMainDictionary(mDictionaryFacilitator);
+            return mDictionaryFacilitator;
+        }
+    }
+
+    public void closeDictionaries() {
+        synchronized (mLock) {
+            mDictionaryFacilitator.closeDictionaries();
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 59de4f8..5dd02bd 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -19,10 +19,8 @@
 import android.content.ContentProviderClient;
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
 
 import java.io.File;
@@ -43,25 +41,24 @@
      * locale. If none is found, it falls back to the built-in dictionary - if any.
      * @param context application context for reading resources
      * @param locale the locale for which to create the dictionary
-     * @param useFullEditDistance whether to use the full edit distance in suggestions
      * @return an initialized instance of DictionaryCollection
      */
     public static DictionaryCollection createMainDictionaryFromManager(final Context context,
-            final Locale locale, final boolean useFullEditDistance) {
+            final Locale locale) {
         if (null == locale) {
             Log.e(TAG, "No locale defined for dictionary");
-            return new DictionaryCollection(Dictionary.TYPE_MAIN,
+            return new DictionaryCollection(Dictionary.TYPE_MAIN, locale,
                     createReadOnlyBinaryDictionary(context, locale));
         }
 
         final LinkedList<Dictionary> dictList = new LinkedList<>();
         final ArrayList<AssetFileAddress> assetFileList =
-                BinaryDictionaryGetter.getDictionaryFiles(locale, context);
+                BinaryDictionaryGetter.getDictionaryFiles(locale, context, true);
         if (null != assetFileList) {
             for (final AssetFileAddress f : assetFileList) {
                 final ReadOnlyBinaryDictionary readOnlyBinaryDictionary =
                         new ReadOnlyBinaryDictionary(f.mFilename, f.mOffset, f.mLength,
-                                useFullEditDistance, locale, Dictionary.TYPE_MAIN);
+                                false /* useFullEditDistance */, locale, Dictionary.TYPE_MAIN);
                 if (readOnlyBinaryDictionary.isValidDictionary()) {
                     dictList.add(readOnlyBinaryDictionary);
                 } else {
@@ -75,7 +72,7 @@
         // If the list is empty, that means we should not use any dictionary (for example, the user
         // explicitly disabled the main dictionary), so the following is okay. dictList is never
         // null, but if for some reason it is, DictionaryCollection handles it gracefully.
-        return new DictionaryCollection(Dictionary.TYPE_MAIN, dictList);
+        return new DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList);
     }
 
     /**
@@ -83,7 +80,7 @@
      * @param context The context to contact the dictionary provider, if possible.
      * @param f A file address to the dictionary to kill.
      */
-    private static void killDictionary(final Context context, final AssetFileAddress f) {
+    public static void killDictionary(final Context context, final AssetFileAddress f) {
         if (f.pointsToPhysicalFile()) {
             f.deleteUnderlyingFile();
             // Warn the dictionary provider if the dictionary came from there.
@@ -101,49 +98,33 @@
             }
             final String wordlistId =
                     DictionaryInfoUtils.getWordListIdFromFileName(new File(f.mFilename).getName());
-            if (null != wordlistId) {
-                // TODO: this is a reasonable last resort, but it is suboptimal.
-                // The following will remove the entry for this dictionary with the dictionary
-                // provider. When the metadata is downloaded again, we will try downloading it
-                // again.
-                // However, in the practice that will mean the user will find themselves without
-                // the new dictionary. That's fine for languages where it's included in the APK,
-                // but for other languages it will leave the user without a dictionary at all until
-                // the next update, which may be a few days away.
-                // Ideally, we would trigger a new download right away, and use increasing retry
-                // delays for this particular id/version combination.
-                // Then again, this is expected to only ever happen in case of human mistake. If
-                // the wrong file is on the server, the following is still doing the right thing.
-                // If it's a file left over from the last version however, it's not great.
-                BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider(
-                        providerClient,
-                        context.getString(R.string.dictionary_pack_client_id),
-                        wordlistId);
-            }
+            // TODO: this is a reasonable last resort, but it is suboptimal.
+            // The following will remove the entry for this dictionary with the dictionary
+            // provider. When the metadata is downloaded again, we will try downloading it
+            // again.
+            // However, in the practice that will mean the user will find themselves without
+            // the new dictionary. That's fine for languages where it's included in the APK,
+            // but for other languages it will leave the user without a dictionary at all until
+            // the next update, which may be a few days away.
+            // Ideally, we would trigger a new download right away, and use increasing retry
+            // delays for this particular id/version combination.
+            // Then again, this is expected to only ever happen in case of human mistake. If
+            // the wrong file is on the server, the following is still doing the right thing.
+            // If it's a file left over from the last version however, it's not great.
+            BinaryDictionaryFileDumper.reportBrokenFileToDictionaryProvider(
+                    providerClient,
+                    context.getString(R.string.dictionary_pack_client_id),
+                    wordlistId);
         }
     }
 
     /**
-     * Initializes a main dictionary collection from a dictionary pack, with default flags.
-     *
-     * This searches for a content provider providing a dictionary pack for the specified
-     * locale. If none is found, it falls back to the built-in dictionary, if any.
-     * @param context application context for reading resources
-     * @param locale the locale for which to create the dictionary
-     * @return an initialized instance of DictionaryCollection
-     */
-    public static DictionaryCollection createMainDictionaryFromManager(final Context context,
-            final Locale locale) {
-        return createMainDictionaryFromManager(context, locale, false /* useFullEditDistance */);
-    }
-
-    /**
      * Initializes a read-only binary dictionary from a raw resource file
      * @param context application context for reading resources
      * @param locale the locale to use for the resource
      * @return an initialized instance of ReadOnlyBinaryDictionary
      */
-    protected static ReadOnlyBinaryDictionary createReadOnlyBinaryDictionary(final Context context,
+    private static ReadOnlyBinaryDictionary createReadOnlyBinaryDictionary(final Context context,
             final Locale locale) {
         AssetFileDescriptor afd = null;
         try {
@@ -177,36 +158,4 @@
             }
         }
     }
-
-    /**
-     * Create a dictionary from passed data. This is intended for unit tests only.
-     * @param dictionaryList the list of files to read, with their offsets and lengths
-     * @param useFullEditDistance whether to use the full edit distance in suggestions
-     * @return the created dictionary, or null.
-     */
-    @UsedForTesting
-    public static Dictionary createDictionaryForTest(final AssetFileAddress[] dictionaryList,
-            final boolean useFullEditDistance, Locale locale) {
-        final DictionaryCollection dictionaryCollection =
-                new DictionaryCollection(Dictionary.TYPE_MAIN);
-        for (final AssetFileAddress address : dictionaryList) {
-            final ReadOnlyBinaryDictionary readOnlyBinaryDictionary = new ReadOnlyBinaryDictionary(
-                    address.mFilename, address.mOffset, address.mLength, useFullEditDistance,
-                    locale, Dictionary.TYPE_MAIN);
-            dictionaryCollection.addDictionary(readOnlyBinaryDictionary);
-        }
-        return dictionaryCollection;
-    }
-
-    /**
-     * Find out whether a dictionary is available for this locale.
-     * @param context the context on which to check resources.
-     * @param locale the locale to check for.
-     * @return whether a (non-placeholder) dictionary is available or not.
-     */
-    public static boolean isDictionaryAvailable(Context context, Locale locale) {
-        final Resources res = context.getResources();
-        return 0 != DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
-                res, locale);
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/DictionaryStats.java b/java/src/com/android/inputmethod/latin/DictionaryStats.java
new file mode 100644
index 0000000..a6b37aa
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryStats.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.Locale;
+
+public class DictionaryStats {
+    public static final int NOT_AN_ENTRY_COUNT = -1;
+
+    public final Locale mLocale;
+    public final String mDictName;
+    public final String mDictFilePath;
+    public final long mDictFileSize;
+    public final int mContentVersion;
+
+    public DictionaryStats(final Locale locale, final String dictName, final File dictFile,
+            final int contentVersion) {
+        mLocale = locale;
+        mDictName = dictName;
+        mDictFilePath = (dictFile == null) ? null : dictFile.getName();
+        mDictFileSize = (dictFile == null || !dictFile.exists()) ? 0 : dictFile.length();
+        mContentVersion = contentVersion;
+    }
+
+    public String getFileSizeString() {
+        if (mDictFileSize == 0) {
+            return "0";
+        }
+        BigDecimal bytes = new BigDecimal(mDictFileSize);
+        BigDecimal kb = bytes.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP);
+        if (kb.longValue() == 0) {
+            return bytes.toString() + " bytes";
+        }
+        BigDecimal mb = kb.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP);
+        if (mb.longValue() == 0) {
+            return kb.toString() + " kb";
+        }
+        return mb.toString() + " Mb";
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder(mDictName);
+        if (mDictName.equals(Dictionary.TYPE_MAIN)) {
+            builder.append(" (");
+            builder.append(mContentVersion);
+            builder.append(")");
+        }
+        builder.append(": ");
+        builder.append(mDictFilePath);
+        builder.append(" / ");
+        builder.append(getFileSizeString());
+        return builder.toString();
+    }
+
+    public static String toString(final Iterable<DictionaryStats> stats) {
+        final StringBuilder builder = new StringBuilder("LM Stats");
+        for (DictionaryStats stat : stats) {
+            builder.append("\n    ");
+            builder.append(stat.toString());
+        }
+        return builder.toString();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java
new file mode 100644
index 0000000..9b27111
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2014, 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;
+
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.inputmethod.keyboard.KeyboardSwitcher;
+import com.android.inputmethod.latin.settings.Settings;
+
+/**
+ * A class for detecting Emoji-Alt physical key.
+ */
+final class EmojiAltPhysicalKeyDetector {
+    private static final String TAG = "EmojiAltPhysicalKeyDetector";
+
+    private final RichInputConnection mRichInputConnection;
+
+    // True if the Alt key has been used as a modifier. In this case the Alt key up isn't
+    // recognized as an emoji key.
+    private boolean mAltHasBeenUsedAsAModifier;
+
+    public EmojiAltPhysicalKeyDetector(final RichInputConnection richInputConnection) {
+        mRichInputConnection = richInputConnection;
+    }
+
+    /**
+     * Record a down key event.
+     * @param keyEvent a down key event.
+     */
+    public void onKeyDown(final KeyEvent keyEvent) {
+        if (isAltKey(keyEvent)) {
+            mAltHasBeenUsedAsAModifier = false;
+        }
+        if (containsAltModifier(keyEvent)) {
+            mAltHasBeenUsedAsAModifier = true;
+        }
+    }
+
+    /**
+     * Determine whether an up key event is a special key up or not.
+     * @param keyEvent an up key event.
+     */
+    public void onKeyUp(final KeyEvent keyEvent) {
+        if (keyEvent.isCanceled()) {
+            // This key up event was a part of key combinations and should be ignored.
+            return;
+        }
+        if (!isAltKey(keyEvent)) {
+            mAltHasBeenUsedAsAModifier |= containsAltModifier(keyEvent);
+            return;
+        }
+        if (containsAltModifier(keyEvent)) {
+            mAltHasBeenUsedAsAModifier = true;
+            return;
+        }
+        if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) {
+            return;
+        }
+        if (mAltHasBeenUsedAsAModifier) {
+            return;
+        }
+        if (!mRichInputConnection.isConnected()) {
+            Log.w(TAG, "onKeyUp() : No connection to text view");
+            return;
+        }
+        onEmojiAltKeyDetected();
+    }
+
+    private static void onEmojiAltKeyDetected() {
+        KeyboardSwitcher.getInstance().onToggleEmojiKeyboard();
+    }
+
+    private static boolean isAltKey(final KeyEvent keyEvent) {
+        final int keyCode = keyEvent.getKeyCode();
+        return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
+    }
+
+    private static boolean containsAltModifier(final KeyEvent keyEvent) {
+        final int metaState = keyEvent.getMetaState();
+        // TODO: Support multiple keyboards. Take device id into account.
+        switch (keyEvent.getKeyCode()) {
+        case KeyEvent.KEYCODE_ALT_LEFT:
+            // Return true if Left-Alt is pressed with Right-Alt pressed.
+            return (metaState & KeyEvent.META_ALT_RIGHT_ON) != 0;
+        case KeyEvent.KEYCODE_ALT_RIGHT:
+            // Return true if Right-Alt is pressed with Left-Alt pressed.
+            return (metaState & KeyEvent.META_ALT_LEFT_ON) != 0;
+        default:
+            return (metaState & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON)) != 0;
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index c11a220..1ef7061 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -20,35 +20,41 @@
 import android.util.Log;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.keyboard.ProximityInfo;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
+import com.android.inputmethod.latin.common.FileUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 import com.android.inputmethod.latin.makedict.WordProperty;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
+import com.android.inputmethod.latin.utils.AsyncResultHolder;
 import com.android.inputmethod.latin.utils.CombinedFormatUtils;
-import com.android.inputmethod.latin.utils.DistracterFilter;
 import com.android.inputmethod.latin.utils.ExecutorUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
+import com.android.inputmethod.latin.utils.WordInputEventForPersonalization;
 
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * Abstract base class for an expandable dictionary that can be created and updated dynamically
  * during runtime. When updated it automatically generates a new binary dictionary to handle future
  * queries in native code. This binary dictionary is written to internal storage.
+ *
+ * A class that extends this abstract class must have a static factory method named
+ *   getDictionary(Context context, Locale locale, File dictFile, String dictNamePrefix)
  */
 abstract public class ExpandableBinaryDictionary extends Dictionary {
     private static final boolean DEBUG = false;
@@ -61,16 +67,17 @@
 
     private static final int TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS = 100;
 
-    private static final int DEFAULT_MAX_UNIGRAM_COUNT = 10000;
-    private static final int DEFAULT_MAX_BIGRAM_COUNT = 10000;
-
     /**
      * The maximum length of a word in this dictionary.
      */
-    protected static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
+    protected static final int MAX_WORD_LENGTH =
+            DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH;
 
     private static final int DICTIONARY_FORMAT_VERSION = FormatSpec.VERSION4;
 
+    private static final WordProperty[] DEFAULT_WORD_PROPERTIES_FOR_SYNC =
+            new WordProperty[0] /* default */;
+
     /** The application context. */
     protected final Context mContext;
 
@@ -86,9 +93,6 @@
      */
     private final String mDictName;
 
-    /** Dictionary locale */
-    private final Locale mLocale;
-
     /** Dictionary file */
     private final File mDictFile;
 
@@ -110,14 +114,14 @@
      */
     protected abstract void loadInitialContentsLocked();
 
-    private boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
+    static boolean matchesExpectedBinaryDictFormatVersionForThisType(final int formatVersion) {
         return formatVersion == FormatSpec.VERSION4;
     }
 
-    private boolean needsToMigrateDictionary(final int formatVersion) {
+    private static boolean needsToMigrateDictionary(final int formatVersion) {
         // When we bump up the dictionary format version, the old version should be added to here
         // for supporting migration. Note that native code has to support reading such formats.
-        return formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING;
+        return formatVersion == FormatSpec.VERSION402;
     }
 
     public boolean isValidDictionaryLocked() {
@@ -137,10 +141,9 @@
      */
     public ExpandableBinaryDictionary(final Context context, final String dictName,
             final Locale locale, final String dictType, final File dictFile) {
-        super(dictType);
+        super(dictType, locale);
         mDictName = dictName;
         mContext = context;
-        mLocale = locale;
         mDictFile = getDictFile(context, dictName, dictFile);
         mBinaryDictionary = null;
         mIsReloading = new AtomicBoolean();
@@ -163,32 +166,10 @@
         asyncExecuteTaskWithLock(mLock.writeLock(), task);
     }
 
-    private void asyncExecuteTaskWithLock(final Lock lock, final Runnable task) {
-        asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, task);
-    }
-
-    private void asyncPreCheckAndExecuteTaskWithWriteLock(
-            final Callable<Boolean> preCheckTask, final Runnable task) {
-        asyncPreCheckAndExecuteTaskWithLock(mLock.writeLock(), preCheckTask, task);
-
-    }
-
-    // Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
-    private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
-            final Callable<Boolean> preCheckTask, final Runnable task) {
-        ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
+    private static void asyncExecuteTaskWithLock(final Lock lock, final Runnable task) {
+        ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute(new Runnable() {
             @Override
             public void run() {
-                if (preCheckTask != null) {
-                    try {
-                        if (!preCheckTask.call().booleanValue()) {
-                            return;
-                        }
-                    } catch (final Exception e) {
-                        Log.e(TAG, "The pre check task throws an exception.", e);
-                        return;
-                    }
-                }
                 lock.lock();
                 try {
                     task.run();
@@ -199,6 +180,18 @@
         });
     }
 
+    @Nullable
+    BinaryDictionary getBinaryDictionary() {
+        return mBinaryDictionary;
+    }
+
+    void closeBinaryDictionary() {
+        if (mBinaryDictionary != null) {
+            mBinaryDictionary.close();
+            mBinaryDictionary = null;
+        }
+    }
+
     /**
      * Closes and cleans up the binary dictionary.
      */
@@ -207,10 +200,7 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary != null) {
-                    mBinaryDictionary.close();
-                    mBinaryDictionary = null;
-                }
+                closeBinaryDictionary();
             }
         });
     }
@@ -224,10 +214,6 @@
         attributeMap.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, mLocale.toString());
         attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
                 String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
-        attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY,
-                String.valueOf(DEFAULT_MAX_UNIGRAM_COUNT));
-        attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY,
-                String.valueOf(DEFAULT_MAX_BIGRAM_COUNT));
         return attributeMap;
     }
 
@@ -240,14 +226,11 @@
         });
     }
 
-    private void removeBinaryDictionaryLocked() {
-        if (mBinaryDictionary != null) {
-            mBinaryDictionary.close();
-        }
+    void removeBinaryDictionaryLocked() {
+        closeBinaryDictionary();
         if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) {
             Log.e(TAG, "Can't remove a file: " + mDictFile.getName());
         }
-        mBinaryDictionary = null;
     }
 
     private void openBinaryDictionaryLocked() {
@@ -256,7 +239,7 @@
                 true /* useFullEditDistance */, mLocale, mDictType, true /* isUpdatable */);
     }
 
-    private void createOnMemoryBinaryDictionaryLocked() {
+    void createOnMemoryBinaryDictionaryLocked() {
         mBinaryDictionary = new BinaryDictionary(
                 mDictFile.getAbsolutePath(), true /* useFullEditDistance */, mLocale, mDictType,
                 DICTIONARY_FORMAT_VERSION, getHeaderAttributeMap());
@@ -275,11 +258,11 @@
     /**
      * Check whether GC is needed and run GC if required.
      */
-    protected void runGCIfRequired(final boolean mindsBlockByGC) {
+    public void runGCIfRequired(final boolean mindsBlockByGC) {
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                if (getBinaryDictionary() == null) {
                     return;
                 }
                 runGCIfRequiredLocked(mindsBlockByGC);
@@ -293,40 +276,38 @@
         }
     }
 
+    private void updateDictionaryWithWriteLock(@Nonnull final Runnable updateTask) {
+        reloadDictionaryIfRequired();
+        final Runnable task = new Runnable() {
+            @Override
+            public void run() {
+                if (getBinaryDictionary() == null) {
+                    return;
+                }
+                runGCIfRequiredLocked(true /* mindsBlockByGC */);
+                updateTask.run();
+            }
+        };
+        asyncExecuteTaskWithWriteLock(task);
+    }
+
     /**
      * Adds unigram information of a word to the dictionary. May overwrite an existing entry.
      */
-    public void addUnigramEntryWithCheckingDistracter(final String word, final int frequency,
-            final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
-            final boolean isBlacklisted, final int timestamp,
-            final DistracterFilter distracterFilter) {
-        reloadDictionaryIfRequired();
-        asyncPreCheckAndExecuteTaskWithWriteLock(
-                new Callable<Boolean>() {
-                    @Override
-                    public Boolean call() throws Exception {
-                        return !distracterFilter.isDistracterToWordsInDictionaries(
-                                PrevWordsInfo.EMPTY_PREV_WORDS_INFO, word, mLocale);
-                    }
-                },
-                new Runnable() {
-                    @Override
-                    public void run() {
-                        if (mBinaryDictionary == null) {
-                            return;
-                        }
-                        runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                        addUnigramLocked(word, frequency, shortcutTarget, shortcutFreq,
-                                isNotAWord, isBlacklisted, timestamp);
-                    }
-                });
+    public void addUnigramEntry(final String word, final int frequency,
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
+        updateDictionaryWithWriteLock(new Runnable() {
+            @Override
+            public void run() {
+                addUnigramLocked(word, frequency, isNotAWord, isPossiblyOffensive, timestamp);
+            }
+        });
     }
 
     protected void addUnigramLocked(final String word, final int frequency,
-            final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord,
-            final boolean isBlacklisted, final int timestamp) {
-        if (!mBinaryDictionary.addUnigramEntry(word, frequency, shortcutTarget, shortcutFreq,
-                false /* isBeginningOfSentence */, isNotAWord, isBlacklisted, timestamp)) {
+            final boolean isNotAWord, final boolean isPossiblyOffensive, final int timestamp) {
+        if (!mBinaryDictionary.addUnigramEntry(word, frequency,
+                false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive, timestamp)) {
             Log.e(TAG, "Cannot add unigram entry. word: " + word);
         }
     }
@@ -339,11 +320,12 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
                 runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                if (!mBinaryDictionary.removeUnigramEntry(word)) {
+                if (!binaryDictionary.removeUnigramEntry(word)) {
                     if (DEBUG) {
                         Log.i(TAG, "Cannot remove unigram entry: " + word);
                     }
@@ -355,75 +337,85 @@
     /**
      * Adds n-gram information of a word to the dictionary. May overwrite an existing entry.
      */
-    public void addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word,
+    public void addNgramEntry(@Nonnull final NgramContext ngramContext, final String word,
             final int frequency, final int timestamp) {
         reloadDictionaryIfRequired();
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                if (getBinaryDictionary() == null) {
                     return;
                 }
                 runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                addNgramEntryLocked(prevWordsInfo, word, frequency, timestamp);
+                addNgramEntryLocked(ngramContext, word, frequency, timestamp);
             }
         });
     }
 
-    protected void addNgramEntryLocked(final PrevWordsInfo prevWordsInfo, final String word,
+    protected void addNgramEntryLocked(@Nonnull final NgramContext ngramContext, final String word,
             final int frequency, final int timestamp) {
-        if (!mBinaryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp)) {
+        if (!mBinaryDictionary.addNgramEntry(ngramContext, word, frequency, timestamp)) {
             if (DEBUG) {
                 Log.i(TAG, "Cannot add n-gram entry.");
-                Log.i(TAG, "  PrevWordsInfo: " + prevWordsInfo + ", word: " + word);
+                Log.i(TAG, "  NgramContext: " + ngramContext + ", word: " + word);
             }
         }
     }
 
     /**
-     * Dynamically remove the n-gram entry in the dictionary.
+     * Update dictionary for the word with the ngramContext.
      */
-    @UsedForTesting
-    public void removeNgramDynamically(final PrevWordsInfo prevWordsInfo, final String word) {
-        reloadDictionaryIfRequired();
-        asyncExecuteTaskWithWriteLock(new Runnable() {
+    public void updateEntriesForWord(@Nonnull final NgramContext ngramContext,
+            final String word, final boolean isValidWord, final int count, final int timestamp) {
+        updateDictionaryWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
-                runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                if (!mBinaryDictionary.removeNgramEntry(prevWordsInfo, word)) {
+                if (!binaryDictionary.updateEntriesForWordWithNgramContext(ngramContext, word,
+                        isValidWord, count, timestamp)) {
                     if (DEBUG) {
-                        Log.i(TAG, "Cannot remove n-gram entry.");
-                        Log.i(TAG, "  PrevWordsInfo: " + prevWordsInfo + ", word: " + word);
+                        Log.e(TAG, "Cannot update counter. word: " + word
+                                + " context: " + ngramContext.toString());
                     }
                 }
             }
         });
     }
 
-    public interface AddMultipleDictionaryEntriesCallback {
+    /**
+     * Used by Sketch.
+     * {@see https://cs.corp.google.com/#android/vendor/unbundled_google/packages/LatinIMEGoogle/tools/sketch/ime-simulator/src/com/android/inputmethod/sketch/imesimulator/ImeSimulator.java&q=updateEntriesForInputEventsCallback&l=286}
+     */
+    @UsedForTesting
+    public interface UpdateEntriesForInputEventsCallback {
         public void onFinished();
     }
 
     /**
-     * Dynamically add multiple entries to the dictionary.
+     * Dynamically update entries according to input events.
+     *
+     * Used by Sketch.
+     * {@see https://cs.corp.google.com/#android/vendor/unbundled_google/packages/LatinIMEGoogle/tools/sketch/ime-simulator/src/com/android/inputmethod/sketch/imesimulator/ImeSimulator.java&q=updateEntriesForInputEventsCallback&l=286}
      */
-    public void addMultipleDictionaryEntriesDynamically(
-            final ArrayList<LanguageModelParam> languageModelParams,
-            final AddMultipleDictionaryEntriesCallback callback) {
+    @UsedForTesting
+    public void updateEntriesForInputEvents(
+            @Nonnull final ArrayList<WordInputEventForPersonalization> inputEvents,
+            final UpdateEntriesForInputEventsCallback callback) {
         reloadDictionaryIfRequired();
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
                 try {
-                    if (mBinaryDictionary == null) {
+                    final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                    if (binaryDictionary == null) {
                         return;
                     }
-                    mBinaryDictionary.addMultipleDictionaryEntries(
-                            languageModelParams.toArray(
-                                    new LanguageModelParam[languageModelParams.size()]));
+                    binaryDictionary.updateEntriesForInputEvents(
+                            inputEvents.toArray(
+                                    new WordInputEventForPersonalization[inputEvents.size()]));
                 } finally {
                     if (callback != null) {
                         callback.onFinished();
@@ -434,10 +426,10 @@
     }
 
     @Override
-    public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+    public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+            final NgramContext ngramContext, final long proximityInfoHandle,
             final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId,
-            final float[] inOutLanguageWeight) {
+            final float weightForLocale, final float[] inOutWeightOfLangModelVsSpatialModel) {
         reloadDictionaryIfRequired();
         boolean lockAcquired = false;
         try {
@@ -448,8 +440,9 @@
                     return null;
                 }
                 final ArrayList<SuggestedWordInfo> suggestions =
-                        mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
-                                settingsValuesForSuggestion, sessionId, inOutLanguageWeight);
+                        mBinaryDictionary.getSuggestions(composedData, ngramContext,
+                                proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+                                weightForLocale, inOutWeightOfLangModelVsSpatialModel);
                 if (mBinaryDictionary.isCorrupted()) {
                     Log.i(TAG, "Dictionary (" + mDictName +") is corrupted. "
                             + "Remove and regenerate it.");
@@ -519,16 +512,11 @@
     }
 
 
-    protected boolean isValidNgramLocked(final PrevWordsInfo prevWordsInfo, final String word) {
-        if (mBinaryDictionary == null) return false;
-        return mBinaryDictionary.isValidNgram(prevWordsInfo, word);
-    }
-
     /**
      * Loads the current binary dictionary from internal storage. Assumes the dictionary file
      * exists.
      */
-    private void loadBinaryDictionaryLocked() {
+    void loadBinaryDictionaryLocked() {
         if (DBG_STRESS_TEST) {
             // Test if this class does not cause problems when it takes long time to load binary
             // dictionary.
@@ -537,6 +525,7 @@
                 Thread.sleep(15000);
                 Log.w(TAG, "End stress in loading");
             } catch (InterruptedException e) {
+                Log.w("Interrupted while loading: " + mDictName, e);
             }
         }
         final BinaryDictionary oldBinaryDictionary = mBinaryDictionary;
@@ -556,7 +545,7 @@
     /**
      * Create a new binary dictionary and load initial contents.
      */
-    private void createNewDictionaryLocked() {
+    void createNewDictionaryLocked() {
         removeBinaryDictionaryLocked();
         createOnMemoryBinaryDictionaryLocked();
         loadInitialContentsLocked();
@@ -572,6 +561,14 @@
         mNeedsToRecreate = true;
     }
 
+    void clearNeedsToRecreate() {
+        mNeedsToRecreate = false;
+    }
+
+    boolean isNeededToRecreate() {
+        return mNeedsToRecreate;
+    }
+
     /**
      * Load the current binary dictionary from internal storage. If the dictionary file doesn't
      * exists or needs to be regenerated, the new dictionary file will be asynchronously generated.
@@ -593,36 +590,40 @@
     /**
      * Reloads the dictionary. Access is controlled on a per dictionary file basis.
      */
-    private final void asyncReloadDictionary() {
-        if (mIsReloading.compareAndSet(false, true)) {
-            asyncExecuteTaskWithWriteLock(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        if (!mDictFile.exists() || mNeedsToRecreate) {
-                            // If the dictionary file does not exist or contents have been updated,
-                            // generate a new one.
-                            createNewDictionaryLocked();
-                        } else if (mBinaryDictionary == null) {
-                            // Otherwise, load the existing dictionary.
-                            loadBinaryDictionaryLocked();
-                            if (mBinaryDictionary != null && !(isValidDictionaryLocked()
-                                    // TODO: remove the check below
-                                    && matchesExpectedBinaryDictFormatVersionForThisType(
-                                            mBinaryDictionary.getFormatVersion()))) {
-                                // Binary dictionary or its format version is not valid. Regenerate
-                                // the dictionary file. createNewDictionaryLocked will remove the
-                                // existing files if appropriate.
-                                createNewDictionaryLocked();
-                            }
-                        }
-                        mNeedsToRecreate = false;
-                    } finally {
-                        mIsReloading.set(false);
-                    }
-                }
-            });
+    private void asyncReloadDictionary() {
+        final AtomicBoolean isReloading = mIsReloading;
+        if (!isReloading.compareAndSet(false, true)) {
+            return;
         }
+        final File dictFile = mDictFile;
+        asyncExecuteTaskWithWriteLock(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    if (!dictFile.exists() || isNeededToRecreate()) {
+                        // If the dictionary file does not exist or contents have been updated,
+                        // generate a new one.
+                        createNewDictionaryLocked();
+                    } else if (getBinaryDictionary() == null) {
+                        // Otherwise, load the existing dictionary.
+                        loadBinaryDictionaryLocked();
+                        final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                        if (binaryDictionary != null && !(isValidDictionaryLocked()
+                                // TODO: remove the check below
+                                && matchesExpectedBinaryDictFormatVersionForThisType(
+                                        binaryDictionary.getFormatVersion()))) {
+                            // Binary dictionary or its format version is not valid. Regenerate
+                            // the dictionary file. createNewDictionaryLocked will remove the
+                            // existing files if appropriate.
+                            createNewDictionaryLocked();
+                        }
+                    }
+                    clearNeedsToRecreate();
+                } finally {
+                    isReloading.set(false);
+                }
+            }
+        });
     }
 
     /**
@@ -632,22 +633,37 @@
         asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
-                if (mBinaryDictionary == null) {
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
                     return;
                 }
-                if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
-                    mBinaryDictionary.flushWithGC();
+                if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
+                    binaryDictionary.flushWithGC();
                 } else {
-                    mBinaryDictionary.flush();
+                    binaryDictionary.flush();
                 }
             }
         });
     }
 
+    public DictionaryStats getDictionaryStats() {
+        reloadDictionaryIfRequired();
+        final String dictName = mDictName;
+        final File dictFile = mDictFile;
+        final AsyncResultHolder<DictionaryStats> result = new AsyncResultHolder<>();
+        asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
+            @Override
+            public void run() {
+                result.set(new DictionaryStats(mLocale, dictName, dictFile, 0));
+            }
+        });
+        return result.get(null /* defaultValue */, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS);
+    }
+
     @UsedForTesting
     public void waitAllTasksForTests() {
         final CountDownLatch countDownLatch = new CountDownLatch(1);
-        ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
+        asyncExecuteTaskWithWriteLock(new Runnable() {
             @Override
             public void run() {
                 countDownLatch.countDown();
@@ -669,31 +685,71 @@
 
     public void dumpAllWordsForDebug() {
         reloadDictionaryIfRequired();
+        final String tag = TAG;
+        final String dictName = mDictName;
         asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
             @Override
             public void run() {
-                Log.d(TAG, "Dump dictionary: " + mDictName);
+                Log.d(tag, "Dump dictionary: " + dictName + " for " + mLocale);
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
+                    return;
+                }
                 try {
-                    final DictionaryHeader header = mBinaryDictionary.getHeader();
-                    Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
-                    Log.d(TAG, CombinedFormatUtils.formatAttributeMap(
+                    final DictionaryHeader header = binaryDictionary.getHeader();
+                    Log.d(tag, "Format version: " + binaryDictionary.getFormatVersion());
+                    Log.d(tag, CombinedFormatUtils.formatAttributeMap(
                             header.mDictionaryOptions.mAttributes));
                 } catch (final UnsupportedFormatException e) {
-                    Log.d(TAG, "Cannot fetch header information.", e);
+                    Log.d(tag, "Cannot fetch header information.", e);
                 }
                 int token = 0;
                 do {
                     final BinaryDictionary.GetNextWordPropertyResult result =
-                            mBinaryDictionary.getNextWordProperty(token);
+                            binaryDictionary.getNextWordProperty(token);
                     final WordProperty wordProperty = result.mWordProperty;
                     if (wordProperty == null) {
-                        Log.d(TAG, " dictionary is empty.");
+                        Log.d(tag, " dictionary is empty.");
                         break;
                     }
-                    Log.d(TAG, wordProperty.toString());
+                    Log.d(tag, wordProperty.toString());
                     token = result.mNextToken;
                 } while (token != 0);
             }
         });
     }
+
+    /**
+     * Returns dictionary content required for syncing.
+     */
+    public WordProperty[] getWordPropertiesForSyncing() {
+        reloadDictionaryIfRequired();
+        final AsyncResultHolder<WordProperty[]> result = new AsyncResultHolder<>();
+        asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
+            @Override
+            public void run() {
+                final ArrayList<WordProperty> wordPropertyList = new ArrayList<>();
+                final BinaryDictionary binaryDictionary = getBinaryDictionary();
+                if (binaryDictionary == null) {
+                    return;
+                }
+                int token = 0;
+                do {
+                    // TODO: We need a new API that returns *new* un-synced data.
+                    final BinaryDictionary.GetNextWordPropertyResult nextWordPropertyResult =
+                            binaryDictionary.getNextWordProperty(token);
+                    final WordProperty wordProperty = nextWordPropertyResult.mWordProperty;
+                    if (wordProperty == null) {
+                        break;
+                    }
+                    wordPropertyList.add(wordProperty);
+                    token = nextWordPropertyResult.mNextToken;
+                } while (token != 0);
+                result.set(wordPropertyList.toArray(new WordProperty[wordPropertyList.size()]));
+            }
+        });
+        // TODO: Figure out the best timeout duration for this API.
+        return result.get(DEFAULT_WORD_PROPERTIES_FOR_SYNC,
+                TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index fecb0ef..37effee 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -16,15 +16,16 @@
 
 package com.android.inputmethod.latin;
 
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
 
 import android.text.InputType;
 import android.util.Log;
 import android.view.inputmethod.EditorInfo;
 
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -42,6 +43,12 @@
     final public boolean mApplicationSpecifiedCompletionOn;
     final public boolean mShouldInsertSpacesAutomatically;
     final public boolean mShouldShowVoiceInputKey;
+    /**
+     * Whether the floating gesture preview should be disabled. If true, this should override the
+     * corresponding keyboard settings preference, always suppressing the floating preview text.
+     * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled}
+     */
+    final public boolean mDisableGestureFloatingPreviewText;
     final public boolean mIsGeneralTextInput;
     final private int mInputType;
     final private EditorInfo mEditorInfo;
@@ -77,6 +84,7 @@
             mApplicationSpecifiedCompletionOn = false;
             mShouldInsertSpacesAutomatically = false;
             mShouldShowVoiceInputKey = false;
+            mDisableGestureFloatingPreviewText = false;
             mIsGeneralTextInput = false;
             return;
         }
@@ -109,6 +117,9 @@
                 || hasNoMicrophoneKeyOption();
         mShouldShowVoiceInputKey = !noMicrophone;
 
+        mDisableGestureFloatingPreviewText = InputAttributes.inPrivateImeOptions(
+                mPackageNameForPrivateImeOptions, NO_FLOATING_GESTURE_PREVIEW, editorInfo);
+
         // If it's a browser edit field and auto correct is not ON explicitly, then
         // disable auto correction, but keep suggestions on.
         // If NO_SUGGESTIONS is set, don't do prediction.
diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
deleted file mode 100644
index 790e0d8..0000000
--- a/java/src/com/android/inputmethod/latin/InputPointers.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.util.Log;
-import android.util.SparseIntArray;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.ResizableIntArray;
-
-// TODO: This class is not thread-safe.
-public final class InputPointers {
-    private static final String TAG = InputPointers.class.getSimpleName();
-    private static final boolean DEBUG_TIME = false;
-
-    private final int mDefaultCapacity;
-    private final ResizableIntArray mXCoordinates;
-    private final ResizableIntArray mYCoordinates;
-    private final ResizableIntArray mPointerIds;
-    private final ResizableIntArray mTimes;
-
-    public InputPointers(int defaultCapacity) {
-        mDefaultCapacity = defaultCapacity;
-        mXCoordinates = new ResizableIntArray(defaultCapacity);
-        mYCoordinates = new ResizableIntArray(defaultCapacity);
-        mPointerIds = new ResizableIntArray(defaultCapacity);
-        mTimes = new ResizableIntArray(defaultCapacity);
-    }
-
-    private void fillWithLastTimeUntil(final int index) {
-        final int fromIndex = mTimes.getLength();
-        // Fill the gap with the latest time.
-        // See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
-        if (fromIndex <= 0) {
-            return;
-        }
-        final int fillLength = index - fromIndex + 1;
-        if (fillLength <= 0) {
-            return;
-        }
-        final int lastTime = mTimes.get(fromIndex - 1);
-        mTimes.fill(lastTime, fromIndex, fillLength);
-    }
-
-    public void addPointerAt(int index, int x, int y, int pointerId, int time) {
-        mXCoordinates.addAt(index, x);
-        mYCoordinates.addAt(index, y);
-        mPointerIds.addAt(index, pointerId);
-        if (DebugFlags.DEBUG_ENABLED || DEBUG_TIME) {
-            fillWithLastTimeUntil(index);
-        }
-        mTimes.addAt(index, time);
-    }
-
-    @UsedForTesting
-    void addPointer(int x, int y, int pointerId, int time) {
-        mXCoordinates.add(x);
-        mYCoordinates.add(y);
-        mPointerIds.add(pointerId);
-        mTimes.add(time);
-    }
-
-    public void set(InputPointers ip) {
-        mXCoordinates.set(ip.mXCoordinates);
-        mYCoordinates.set(ip.mYCoordinates);
-        mPointerIds.set(ip.mPointerIds);
-        mTimes.set(ip.mTimes);
-    }
-
-    public void copy(InputPointers ip) {
-        mXCoordinates.copy(ip.mXCoordinates);
-        mYCoordinates.copy(ip.mYCoordinates);
-        mPointerIds.copy(ip.mPointerIds);
-        mTimes.copy(ip.mTimes);
-    }
-
-    /**
-     * Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
-     * to the end of this.
-     * @param pointerId the pointer id of the source.
-     * @param times the source {@link ResizableIntArray} to read the event times from.
-     * @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from.
-     * @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from.
-     * @param startPos the starting index of the data in {@code times} and etc.
-     * @param length the number of data to be appended.
-     */
-    public void append(int pointerId, ResizableIntArray times, ResizableIntArray xCoordinates,
-            ResizableIntArray yCoordinates, int startPos, int length) {
-        if (length == 0) {
-            return;
-        }
-        mXCoordinates.append(xCoordinates, startPos, length);
-        mYCoordinates.append(yCoordinates, startPos, length);
-        mPointerIds.fill(pointerId, mPointerIds.getLength(), length);
-        mTimes.append(times, startPos, length);
-    }
-
-    /**
-     * Shift to the left by elementCount, discarding elementCount pointers at the start.
-     * @param elementCount how many elements to shift.
-     */
-    public void shift(final int elementCount) {
-        mXCoordinates.shift(elementCount);
-        mYCoordinates.shift(elementCount);
-        mPointerIds.shift(elementCount);
-        mTimes.shift(elementCount);
-    }
-
-    public void reset() {
-        final int defaultCapacity = mDefaultCapacity;
-        mXCoordinates.reset(defaultCapacity);
-        mYCoordinates.reset(defaultCapacity);
-        mPointerIds.reset(defaultCapacity);
-        mTimes.reset(defaultCapacity);
-    }
-
-    public int getPointerSize() {
-        return mXCoordinates.getLength();
-    }
-
-    public int[] getXCoordinates() {
-        return mXCoordinates.getPrimitiveArray();
-    }
-
-    public int[] getYCoordinates() {
-        return mYCoordinates.getPrimitiveArray();
-    }
-
-    public int[] getPointerIds() {
-        return mPointerIds.getPrimitiveArray();
-    }
-
-    public int[] getTimes() {
-        if (DebugFlags.DEBUG_ENABLED || DEBUG_TIME) {
-            if (!isValidTimeStamps()) {
-                throw new RuntimeException("Time stamps are invalid.");
-            }
-        }
-        return mTimes.getPrimitiveArray();
-    }
-
-    @Override
-    public String toString() {
-        return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes
-                + " x=" + mXCoordinates + " y=" + mYCoordinates;
-    }
-
-    private boolean isValidTimeStamps() {
-        final int[] times = mTimes.getPrimitiveArray();
-        final int[] pointerIds = mPointerIds.getPrimitiveArray();
-        final SparseIntArray lastTimeOfPointers = new SparseIntArray();
-        final int size = getPointerSize();
-        for (int i = 0; i < size; ++i) {
-            final int pointerId = pointerIds[i];
-            final int time = times[i];
-            final int lastTime = lastTimeOfPointers.get(pointerId, time);
-            if (time < lastTime) {
-                // dump
-                for (int j = 0; j < size; ++j) {
-                    Log.d(TAG, "--- (" + j + ") " + times[j]);
-                }
-                return false;
-            }
-            lastTimeOfPointers.put(pointerId, time);
-        }
-        return true;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/InputView.java b/java/src/com/android/inputmethod/latin/InputView.java
index 7fa9354..f3a8ca1 100644
--- a/java/src/com/android/inputmethod/latin/InputView.java
+++ b/java/src/com/android/inputmethod/latin/InputView.java
@@ -139,7 +139,10 @@
             return y - mEventReceivingRect.top;
         }
 
-        // Callback when a {@link MotionEvent} is forwarded.
+        /**
+         * Callback when a {@link MotionEvent} is forwarded.
+         * @param me the motion event to be forwarded.
+         */
         protected void onForwardingEvent(final MotionEvent me) {}
 
         // Returns true if a {@link MotionEvent} is needed to be forwarded to
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 8cbf837..426d33e 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -19,6 +19,8 @@
 import android.text.TextUtils;
 
 import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 
 import java.util.ArrayList;
 
@@ -48,10 +50,10 @@
     public final String mTypedWord;
     public final CharSequence mCommittedWord;
     public final String mSeparatorString;
-    public final PrevWordsInfo mPrevWordsInfo;
+    public final NgramContext mNgramContext;
     public final int mCapitalizedMode;
     public final InputPointers mInputPointers =
-            new InputPointers(Constants.DICTIONARY_MAX_WORD_LENGTH);
+            new InputPointers(DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH);
 
     private boolean mActive;
 
@@ -64,7 +66,7 @@
     public LastComposedWord(final ArrayList<Event> events,
             final InputPointers inputPointers, final String typedWord,
             final CharSequence committedWord, final String separatorString,
-            final PrevWordsInfo prevWordsInfo, final int capitalizedMode) {
+            final NgramContext ngramContext, final int capitalizedMode) {
         if (inputPointers != null) {
             mInputPointers.copy(inputPointers);
         }
@@ -73,7 +75,7 @@
         mCommittedWord = committedWord;
         mSeparatorString = separatorString;
         mActive = true;
-        mPrevWordsInfo = prevWordsInfo;
+        mNgramContext = ngramContext;
         mCapitalizedMode = capitalizedMode;
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d57db8e..330be37 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,9 +16,9 @@
 
 package com.android.inputmethod.latin;
 
-import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
 
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
@@ -31,13 +31,11 @@
 import android.content.res.Resources;
 import android.inputmethodservice.InputMethodService;
 import android.media.AudioManager;
-import android.net.ConnectivityManager;
 import android.os.Debug;
 import android.os.IBinder;
 import android.os.Message;
 import android.preference.PreferenceManager;
 import android.text.InputType;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
@@ -46,19 +44,17 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
-import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
-import android.widget.TextView;
 
 import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
 import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
+import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
+import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
 import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.event.HardwareEventDecoder;
@@ -69,32 +65,29 @@
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.keyboard.MainKeyboardView;
-import com.android.inputmethod.keyboard.TextDecoratorUi;
 import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.InputPointers;
 import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.define.ProductionFlags;
 import com.android.inputmethod.latin.inputlogic.InputLogic;
-import com.android.inputmethod.latin.personalization.ContextualDictionaryUpdater;
-import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever;
-import com.android.inputmethod.latin.personalization.PersonalizationDictionaryUpdater;
 import com.android.inputmethod.latin.personalization.PersonalizationHelper;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsActivity;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.suggestions.SuggestionStripView;
 import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
+import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
-import com.android.inputmethod.latin.utils.CapsModeUtils;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.CursorAnchorInfoUtils;
 import com.android.inputmethod.latin.utils.DialogUtils;
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
 import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
 import com.android.inputmethod.latin.utils.IntentUtils;
 import com.android.inputmethod.latin.utils.JniUtils;
 import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
 import com.android.inputmethod.latin.utils.StatsUtils;
+import com.android.inputmethod.latin.utils.StatsUtilsManager;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 
@@ -105,6 +98,8 @@
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+
 /**
  * Input method implementation for Qwerty'ish keyboard.
  */
@@ -112,17 +107,14 @@
         SuggestionStripView.Listener, SuggestionStripViewAccessor,
         DictionaryFacilitator.DictionaryInitializationListener,
         ImportantNoticeDialog.ImportantNoticeDialogListener {
-    private static final String TAG = LatinIME.class.getSimpleName();
+    static final String TAG = LatinIME.class.getSimpleName();
     private static final boolean TRACE = false;
-    private static boolean DEBUG = false;
 
     private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
-
-    private static final int PENDING_IMS_CALLBACK_DURATION = 800;
-
-    private static final int DELAY_WAIT_FOR_DICTIONARY_LOAD = 2000; // 2s
-
     private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
+    private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
+    static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
+    static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
 
     /**
      * The name of the scheme used by the Package Manager to warn of a new package installation,
@@ -130,22 +122,11 @@
      */
     private static final String SCHEME_PACKAGE = "package";
 
-    private final Settings mSettings;
+    final Settings mSettings;
     private final DictionaryFacilitator mDictionaryFacilitator =
-            new DictionaryFacilitator(
-                    new DistracterFilterCheckingExactMatchesAndSuggestions(this /* context */));
-    // TODO: Move from LatinIME.
-    private final PersonalizationDictionaryUpdater mPersonalizationDictionaryUpdater =
-            new PersonalizationDictionaryUpdater(this /* context */, mDictionaryFacilitator);
-    private final ContextualDictionaryUpdater mContextualDictionaryUpdater =
-            new ContextualDictionaryUpdater(this /* context */, mDictionaryFacilitator,
-                    new Runnable() {
-                        @Override
-                        public void run() {
-                            mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
-                        }
-                    });
-    private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
+            DictionaryFacilitatorProvider.getDictionaryFacilitator(
+                    false /* isNeededForSpellChecking */);
+    final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
             this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
     // We expect to have only one decoder in almost all cases, hence the default capacity of 1.
     // If it turns out we need several, it will get grown seamlessly.
@@ -153,14 +134,15 @@
 
     // TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
     private View mInputView;
+    private InsetsUpdater mInsetsUpdater;
     private SuggestionStripView mSuggestionStripView;
-    private TextView mExtractEditText;
 
     private RichInputMethodManager mRichImm;
     @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
-    private final SubtypeSwitcher mSubtypeSwitcher;
     private final SubtypeState mSubtypeState = new SubtypeState();
-    private final SpecialKeyDetector mSpecialKeyDetector;
+    private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector =
+            new EmojiAltPhysicalKeyDetector(mInputLogic.mConnection);
+    private StatsUtilsManager mStatsUtilsManager;
     // Working variable for {@link #startShowingInputView()} and
     // {@link #onEvaluateInputViewShown()}.
     private boolean mIsExecutingStartShowingInputView;
@@ -176,6 +158,8 @@
 
     private final boolean mIsHardwareAcceleratedDrawingEnabled;
 
+    private GestureConsumer mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
+
     public final UIHandler mHandler = new UIHandler(this);
 
     public static final class UIHandler extends LeakGuardHandlerWrapper<LatinIME> {
@@ -188,20 +172,21 @@
         private static final int MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED = 6;
         private static final int MSG_RESET_CACHES = 7;
         private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
+        private static final int MSG_DEALLOCATE_MEMORY = 9;
+        private static final int MSG_RESUME_SUGGESTIONS_FOR_START_INPUT = 10;
         // Update this when adding new messages
-        private static final int MSG_LAST = MSG_WAIT_FOR_DICTIONARY_LOAD;
+        private static final int MSG_LAST = MSG_RESUME_SUGGESTIONS_FOR_START_INPUT;
 
         private static final int ARG1_NOT_GESTURE_INPUT = 0;
         private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
         private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
         private static final int ARG2_UNUSED = 0;
-        private static final int ARG1_FALSE = 0;
         private static final int ARG1_TRUE = 1;
 
         private int mDelayInMillisecondsToUpdateSuggestions;
         private int mDelayInMillisecondsToUpdateShiftState;
 
-        public UIHandler(final LatinIME ownerInstance) {
+        public UIHandler(@Nonnull final LatinIME ownerInstance) {
             super(ownerInstance);
         }
 
@@ -245,20 +230,26 @@
                 break;
             case MSG_RESUME_SUGGESTIONS:
                 latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
-                        latinIme.mSettings.getCurrent(),
-                        msg.arg1 == ARG1_TRUE /* shouldIncludeResumedWordInSuggestions */,
+                        latinIme.mSettings.getCurrent(), false /* forStartInput */,
+                        latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
+                break;
+            case MSG_RESUME_SUGGESTIONS_FOR_START_INPUT:
+                latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
+                        latinIme.mSettings.getCurrent(), true /* forStartInput */,
                         latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
                 break;
             case MSG_REOPEN_DICTIONARIES:
                 // We need to re-evaluate the currently composing word in case the script has
                 // changed.
                 postWaitForDictionaryLoad();
-                latinIme.resetSuggest();
+                latinIme.resetDictionaryFacilitatorIfNecessary();
                 break;
             case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED:
+                final SuggestedWords suggestedWords = (SuggestedWords) msg.obj;
                 latinIme.mInputLogic.onUpdateTailBatchInputCompleted(
                         latinIme.mSettings.getCurrent(),
-                        (SuggestedWords) msg.obj, latinIme.mKeyboardSwitcher);
+                        suggestedWords, latinIme.mKeyboardSwitcher);
+                latinIme.onTailBatchInputResultShown(suggestedWords);
                 break;
             case MSG_RESET_CACHES:
                 final SettingsValues settingsValues = latinIme.mSettings.getCurrent();
@@ -275,6 +266,9 @@
             case MSG_WAIT_FOR_DICTIONARY_LOAD:
                 Log.i(TAG, "Timeout waiting for dictionary load");
                 break;
+            case MSG_DEALLOCATE_MEMORY:
+                latinIme.deallocateMemory();
+                break;
             }
         }
 
@@ -287,8 +281,8 @@
             sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
         }
 
-        public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions,
-                final boolean shouldDelay) {
+        private void postResumeSuggestionsInternal(final boolean shouldDelay,
+                final boolean forStartInput) {
             final LatinIME latinIme = getOwnerInstance();
             if (latinIme == null) {
                 return;
@@ -297,17 +291,25 @@
                 return;
             }
             removeMessages(MSG_RESUME_SUGGESTIONS);
+            removeMessages(MSG_RESUME_SUGGESTIONS_FOR_START_INPUT);
+            final int message = forStartInput ? MSG_RESUME_SUGGESTIONS_FOR_START_INPUT
+                    : MSG_RESUME_SUGGESTIONS;
             if (shouldDelay) {
-                sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
-                        shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
-                        0 /* ignored */), mDelayInMillisecondsToUpdateSuggestions);
+                sendMessageDelayed(obtainMessage(message),
+                        mDelayInMillisecondsToUpdateSuggestions);
             } else {
-                sendMessage(obtainMessage(MSG_RESUME_SUGGESTIONS,
-                        shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
-                        0 /* ignored */));
+                sendMessage(obtainMessage(message));
             }
         }
 
+        public void postResumeSuggestions(final boolean shouldDelay) {
+            postResumeSuggestionsInternal(shouldDelay, false /* forStartInput */);
+        }
+
+        public void postResumeSuggestionsForStartInput(final boolean shouldDelay) {
+            postResumeSuggestionsInternal(shouldDelay, true /* forStartInput */);
+        }
+
         public void postResetCaches(final boolean tryResumeSuggestions, final int remainingTries) {
             removeMessages(MSG_RESET_CACHES);
             sendMessage(obtainMessage(MSG_RESET_CACHES, tryResumeSuggestions ? 1 : 0,
@@ -316,7 +318,7 @@
 
         public void postWaitForDictionaryLoad() {
             sendMessageDelayed(obtainMessage(MSG_WAIT_FOR_DICTIONARY_LOAD),
-                    DELAY_WAIT_FOR_DICTIONARY_LOAD);
+                    DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS);
         }
 
         public void cancelWaitForDictionaryLoad() {
@@ -345,6 +347,19 @@
                     mDelayInMillisecondsToUpdateShiftState);
         }
 
+        public void postDeallocateMemory() {
+            sendMessageDelayed(obtainMessage(MSG_DEALLOCATE_MEMORY),
+                    DELAY_DEALLOCATE_MEMORY_MILLIS);
+        }
+
+        public void cancelDeallocateMemory() {
+            removeMessages(MSG_DEALLOCATE_MEMORY);
+        }
+
+        public boolean hasPendingDeallocateMemory() {
+            return hasMessages(MSG_DEALLOCATE_MEMORY);
+        }
+
         @UsedForTesting
         public void removeAllMessages() {
             for (int i = 0; i <= MSG_LAST; ++i) {
@@ -442,7 +457,7 @@
                     mPendingSuccessiveImsCallback = false;
                     resetPendingImsCallback();
                     sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
-                            PENDING_IMS_CALLBACK_DURATION);
+                            PENDING_IMS_CALLBACK_DURATION_MILLIS);
                 }
                 final LatinIME latinIme = getOwnerInstance();
                 if (latinIme != null) {
@@ -450,6 +465,7 @@
                     latinIme.onStartInputViewInternal(editorInfo, restarting);
                     mAppliedEditorInfo = editorInfo;
                 }
+                cancelDeallocateMemory();
             }
         }
 
@@ -463,6 +479,9 @@
                     latinIme.onFinishInputViewInternal(finishingInput);
                     mAppliedEditorInfo = null;
                 }
+                if (!hasPendingDeallocateMemory()) {
+                    postDeallocateMemory();
+                }
             }
         }
 
@@ -516,9 +535,8 @@
     public LatinIME() {
         super();
         mSettings = Settings.getInstance();
-        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mKeyboardSwitcher = KeyboardSwitcher.getInstance();
-        mSpecialKeyDetector = new SpecialKeyDetector(this);
+        mStatsUtilsManager = StatsUtilsManager.getInstance();
         mIsHardwareAcceleratedDrawingEnabled =
                 InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
         Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
@@ -530,28 +548,25 @@
         DebugFlags.init(PreferenceManager.getDefaultSharedPreferences(this));
         RichInputMethodManager.init(this);
         mRichImm = RichInputMethodManager.getInstance();
-        SubtypeSwitcher.init(this);
         KeyboardSwitcher.init(this);
         AudioAndHapticFeedbackManager.init(this);
         AccessibilityUtils.init(this);
-        StatsUtils.init(this);
-
+        mStatsUtilsManager.onCreate(this /* context */, mDictionaryFacilitator);
         super.onCreate();
 
         mHandler.onCreate();
-        DEBUG = DebugFlags.DEBUG_ENABLED;
 
-        // TODO: Resolve mutual dependencies of {@link #loadSettings()} and {@link #initSuggest()}.
+        // TODO: Resolve mutual dependencies of {@link #loadSettings()} and
+        // {@link #resetDictionaryFacilitatorIfNecessary()}.
         loadSettings();
-        resetSuggest();
+        resetDictionaryFacilitatorIfNecessary();
 
-        // Register to receive ringer mode change and network state change.
-        // Also receive installation and removal of a dictionary pack.
+        // Register to receive ringer mode change.
         final IntentFilter filter = new IntentFilter();
-        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
-        registerReceiver(mConnectivityAndRingerModeChangeReceiver, filter);
+        registerReceiver(mRingerModeChangeReceiver, filter);
 
+        // Register to receive installation and removal of a dictionary pack.
         final IntentFilter packageFilter = new IntentFilter();
         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -566,15 +581,13 @@
         dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
         registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter);
 
-        DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this);
-
-        StatsUtils.onCreate(mSettings.getCurrent());
+        StatsUtils.onCreate(mSettings.getCurrent(), mRichImm);
     }
 
     // Has to be package-visible for unit tests
     @UsedForTesting
     void loadSettings() {
-        final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+        final Locale locale = mRichImm.getCurrentSubtypeLocale();
         final EditorInfo editorInfo = getCurrentInputEditorInfo();
         final InputAttributes inputAttributes = new InputAttributes(
                 editorInfo, isFullscreenMode(), getPackageName());
@@ -585,30 +598,19 @@
         // been displayed. Opening dictionaries never affects responsivity as dictionaries are
         // asynchronously loaded.
         if (!mHandler.hasPendingReopenDictionaries()) {
-            resetSuggestForLocale(locale);
+            resetDictionaryFacilitator(locale);
         }
-        mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList(
-                true /* allowsImplicitlySelectedSubtypes */));
         refreshPersonalizationDictionarySession(currentSettingsValues);
-        StatsUtils.onLoadSettings(currentSettingsValues);
+        resetDictionaryFacilitatorIfNecessary();
+        mStatsUtilsManager.onLoadSettings(this /* context */, currentSettingsValues);
     }
 
     private void refreshPersonalizationDictionarySession(
             final SettingsValues currentSettingsValues) {
-        mPersonalizationDictionaryUpdater.onLoadSettings(
-                currentSettingsValues.mUsePersonalizedDicts,
-                mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
-        mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
-        final boolean shouldKeepUserHistoryDictionaries;
-        if (currentSettingsValues.mUsePersonalizedDicts) {
-            shouldKeepUserHistoryDictionaries = true;
-        } else {
-            shouldKeepUserHistoryDictionaries = false;
-        }
-        if (!shouldKeepUserHistoryDictionaries) {
+        if (!currentSettingsValues.mUsePersonalizedDicts) {
             // Remove user history dictionaries.
             PersonalizationHelper.removeAllUserHistoryDictionaries(this);
-            mDictionaryFacilitator.clearUserHistoryDictionary();
+            mDictionaryFacilitator.clearUserHistoryDictionary(this);
         }
     }
 
@@ -621,44 +623,49 @@
         }
         if (mHandler.hasPendingWaitForDictionaryLoad()) {
             mHandler.cancelWaitForDictionaryLoad();
-            mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                    false /* shouldDelay */);
+            mHandler.postResumeSuggestions(false /* shouldDelay */);
         }
     }
 
-    private void resetSuggest() {
-        final Locale switcherSubtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
-        final String switcherLocaleStr = switcherSubtypeLocale.toString();
+    void resetDictionaryFacilitatorIfNecessary() {
+        final Locale subtypeSwitcherLocale = mRichImm.getCurrentSubtypeLocale();
         final Locale subtypeLocale;
-        if (TextUtils.isEmpty(switcherLocaleStr)) {
+        if (subtypeSwitcherLocale == null) {
             // This happens in very rare corner cases - for example, immediately after a switch
             // to LatinIME has been requested, about a frame later another switch happens. In this
             // case, we are about to go down but we still don't know it, however the system tells
-            // us there is no current subtype so the locale is the empty string. Take the best
-            // possible guess instead -- it's bound to have no consequences, and we have no way
-            // of knowing anyway.
+            // us there is no current subtype.
             Log.e(TAG, "System is reporting no current subtype.");
             subtypeLocale = getResources().getConfiguration().locale;
         } else {
-            subtypeLocale = switcherSubtypeLocale;
+            subtypeLocale = subtypeSwitcherLocale;
         }
-        resetSuggestForLocale(subtypeLocale);
+        if (mDictionaryFacilitator.isForLocale(subtypeLocale)
+                && mDictionaryFacilitator.isForAccount(mSettings.getCurrent().mAccount)) {
+            return;
+        }
+        resetDictionaryFacilitator(subtypeLocale);
     }
 
     /**
-     * Reset suggest by loading dictionaries for the locale and the current settings values.
+     * Reset the facilitator by loading dictionaries for the given locale and
+     * the current settings values.
      *
      * @param locale the locale
      */
-    private void resetSuggestForLocale(final Locale locale) {
+    // TODO: make sure the current settings always have the right locales, and read from them.
+    private void resetDictionaryFacilitator(final Locale locale) {
         final SettingsValues settingsValues = mSettings.getCurrent();
         mDictionaryFacilitator.resetDictionaries(this /* context */, locale,
                 settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
-                false /* forceReloadMainDictionary */, this);
+                false /* forceReloadMainDictionary */,
+                settingsValues.mAccount, "" /* dictNamePrefix */,
+                this /* DictionaryInitializationListener */);
         if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
             mInputLogic.mSuggest.setAutoCorrectionThreshold(
                     settingsValues.mAutoCorrectionThreshold);
         }
+        mInputLogic.mSuggest.setPlausibilityThreshold(settingsValues.mPlausibilityThreshold);
     }
 
     /**
@@ -668,19 +675,20 @@
         final SettingsValues settingsValues = mSettings.getCurrent();
         mDictionaryFacilitator.resetDictionaries(this /* context */,
                 mDictionaryFacilitator.getLocale(), settingsValues.mUseContactsDict,
-                settingsValues.mUsePersonalizedDicts, true /* forceReloadMainDictionary */, this);
+                settingsValues.mUsePersonalizedDicts,
+                true /* forceReloadMainDictionary */,
+                settingsValues.mAccount, "" /* dictNamePrefix */,
+                this /* DictionaryInitializationListener */);
     }
 
     @Override
     public void onDestroy() {
         mDictionaryFacilitator.closeDictionaries();
-        mPersonalizationDictionaryUpdater.onDestroy();
-        mContextualDictionaryUpdater.onDestroy();
         mSettings.onDestroy();
-        unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
+        unregisterReceiver(mRingerModeChangeReceiver);
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
-        StatsUtils.onDestroy();
+        mStatsUtilsManager.onDestroy(this /* context */);
         super.onDestroy();
     }
 
@@ -688,7 +696,7 @@
     public void recycle() {
         unregisterReceiver(mDictionaryPackInstallReceiver);
         unregisterReceiver(mDictionaryDumpBroadcastReceiver);
-        unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
+        unregisterReceiver(mRingerModeChangeReceiver);
         mInputLogic.recycle();
     }
 
@@ -715,15 +723,12 @@
                 cleanupInternalStateForFinishInput();
             }
         }
-        // TODO: Remove this test.
-        if (!conf.locale.equals(mPersonalizationDictionaryUpdater.getLocale())) {
-            refreshPersonalizationDictionarySession(settingsValues);
-        }
         super.onConfigurationChanged(conf);
     }
 
     @Override
     public View onCreateInputView() {
+        StatsUtils.onCreateInputView();
         return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled);
     }
 
@@ -731,60 +736,17 @@
     public void setInputView(final View view) {
         super.setInputView(view);
         mInputView = view;
+        mInsetsUpdater = ViewOutlineProviderCompatUtils.setInsetsOutlineProvider(view);
+        updateSoftInputWindowLayoutParameters();
         mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
         if (hasSuggestionStripView()) {
             mSuggestionStripView.setListener(this, view);
         }
-        mInputLogic.setTextDecoratorUi(new TextDecoratorUi(this, view));
-    }
-
-    @Override
-    public void setExtractView(final View view) {
-        final TextView prevExtractEditText = mExtractEditText;
-        super.setExtractView(view);
-        TextView nextExtractEditText = null;
-        if (view != null) {
-            final View extractEditText = view.findViewById(android.R.id.inputExtractEditText);
-            if (extractEditText instanceof TextView) {
-                nextExtractEditText = (TextView)extractEditText;
-            }
-        }
-        if (prevExtractEditText == nextExtractEditText) {
-            return;
-        }
-        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && prevExtractEditText != null) {
-            prevExtractEditText.getViewTreeObserver().removeOnPreDrawListener(
-                    mExtractTextViewPreDrawListener);
-        }
-        mExtractEditText = nextExtractEditText;
-        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && mExtractEditText != null) {
-            mExtractEditText.getViewTreeObserver().addOnPreDrawListener(
-                    mExtractTextViewPreDrawListener);
-        }
-    }
-
-    private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
-            new ViewTreeObserver.OnPreDrawListener() {
-                @Override
-                public boolean onPreDraw() {
-                    onExtractTextViewPreDraw();
-                    return true;
-                }
-            };
-
-    private void onExtractTextViewPreDraw() {
-        if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || !isFullscreenMode()
-                || mExtractEditText == null) {
-            return;
-        }
-        final CursorAnchorInfo info = CursorAnchorInfoUtils.getCursorAnchorInfo(mExtractEditText);
-        mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
     }
 
     @Override
     public void setCandidatesView(final View view) {
         // To ensure that CandidatesView will never be set.
-        return;
     }
 
     @Override
@@ -795,11 +757,15 @@
     @Override
     public void onStartInputView(final EditorInfo editorInfo, final boolean restarting) {
         mHandler.onStartInputView(editorInfo, restarting);
+        mStatsUtilsManager.onStartInputView();
     }
 
     @Override
     public void onFinishInputView(final boolean finishingInput) {
+        StatsUtils.onFinishInputView();
         mHandler.onFinishInputView(finishingInput);
+        mStatsUtilsManager.onFinishInputView();
+        mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
     }
 
     @Override
@@ -811,20 +777,27 @@
     public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype) {
         // Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
         // is not guaranteed. It may even be called at the same time on a different thread.
-        mSubtypeSwitcher.onSubtypeChanged(subtype);
+        InputMethodSubtype oldSubtype = mRichImm.getCurrentSubtype().getRawSubtype();
+        StatsUtils.onSubtypeChanged(oldSubtype, subtype);
+        mRichImm.onSubtypeChanged(subtype);
         mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype),
                 mSettings.getCurrent());
         loadKeyboard();
     }
 
-    private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
+    void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
         super.onStartInput(editorInfo, restarting);
     }
 
     @SuppressWarnings("deprecation")
-    private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
+    void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
         super.onStartInputView(editorInfo, restarting);
-        mRichImm.clearSubtypeCaches();
+
+        mDictionaryFacilitator.onStartInput();
+        // Switch to the null consumer to handle cases leading to early exit below, for which we
+        // also wouldn't be consuming gesture data.
+        mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
+        mRichImm.refreshSubtypeCaches();
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
         switcher.updateKeyboardTheme();
         final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
@@ -839,7 +812,7 @@
             }
             return;
         }
-        if (DEBUG) {
+        if (DebugFlags.DEBUG_ENABLED) {
             Log.d(TAG, "onStartInputView: editorInfo:"
                     + String.format("inputType=0x%08x imeOptions=0x%08x",
                             editorInfo.inputType, editorInfo.imeOptions));
@@ -867,6 +840,12 @@
             return;
         }
 
+        // Update to a gesture consumer with the current editor and IME state.
+        mGestureConsumer = GestureConsumer.newInstance(editorInfo,
+                mInputLogic.getPrivateCommandPerformer(),
+                mRichImm.getCurrentSubtypeLocale(),
+                switcher.getKeyboard());
+
         // Forward this event to the accessibility utilities, if enabled.
         final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
         if (accessUtils.isTouchExplorationEnabled()) {
@@ -875,9 +854,10 @@
 
         final boolean inputTypeChanged = !currentSettingsValues.isSameInputType(editorInfo);
         final boolean isDifferentTextField = !restarting || inputTypeChanged;
-        if (isDifferentTextField) {
-            mSubtypeSwitcher.updateParametersOnStartInputView();
-        }
+
+        StatsUtils.onStartInputView(editorInfo.inputType,
+                Settings.getInstance().getCurrent().mDisplayOrientation,
+                !isDifferentTextField);
 
         // The EditorInfo might have a flag that affects fullscreen mode.
         // Note: This call should be done by InputMethodService?
@@ -897,15 +877,10 @@
             // span, so we should reset our state unconditionally, even if restarting is true.
             // We also tell the input logic about the combining rules for the current subtype, so
             // it can adjust its combiners if needed.
-            mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+            mInputLogic.startInput(mRichImm.getCombiningRulesExtraValueOfCurrentSubtype(),
                     currentSettingsValues);
 
-            // Note: the following does a round-trip IPC on the main thread: be careful
-            final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
-            if (null != currentLocale && !currentLocale.equals(suggest.getLocale())) {
-                // TODO: Do this automatically.
-                resetSuggest();
-            }
+            resetDictionaryFacilitatorIfNecessary();
 
             // TODO[IL]: Can the following be moved to InputLogic#startInput?
             if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
@@ -919,11 +894,12 @@
                 // mLastSelection{Start,End} are reset later in this method, no need to do it here
                 needToCallLoadKeyboardLater = true;
             } else {
-                // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
-                // effort to work around this bug.
+                // When rotating, and when input is starting again in a field from where the focus
+                // didn't move (the keyboard having been closed with the back key),
+                // initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
+                // work around this bug.
                 mInputLogic.mConnection.tryFixLyingCursorPosition();
-                mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                        true /* shouldDelay */);
+                mHandler.postResumeSuggestionsForStartInput(true /* shouldDelay */);
                 needToCallLoadKeyboardLater = false;
             }
         } else {
@@ -943,6 +919,7 @@
                 suggest.setAutoCorrectionThreshold(
                         currentSettingsValues.mAutoCorrectionThreshold);
             }
+            suggest.setPlausibilityThreshold(currentSettingsValues.mPlausibilityThreshold);
 
             switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(),
                     getCurrentRecapitalizeState());
@@ -970,7 +947,7 @@
         mHandler.cancelUpdateSuggestionStrip();
 
         mainKeyboardView.setMainDictionaryAvailability(
-                mDictionaryFacilitator.hasInitializedMainDictionary());
+                mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary());
         mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn,
                 currentSettingsValues.mKeyPreviewPopupDismissDelay);
         mainKeyboardView.setSlidingKeyInputPreviewEnabled(
@@ -980,8 +957,6 @@
                 currentSettingsValues.mGestureTrailEnabled,
                 currentSettingsValues.mGestureFloatingPreviewTextEnabled);
 
-        // Contextual dictionary should be updated for the current application.
-        mContextualDictionaryUpdater.onStartInputView(editorInfo.packageName);
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
 
@@ -994,45 +969,50 @@
         }
     }
 
-    private void onFinishInputInternal() {
+    void onFinishInputInternal() {
         super.onFinishInput();
 
+        mDictionaryFacilitator.onFinishInput();
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
         if (mainKeyboardView != null) {
             mainKeyboardView.closing();
         }
     }
 
-    private void onFinishInputViewInternal(final boolean finishingInput) {
+    void onFinishInputViewInternal(final boolean finishingInput) {
         super.onFinishInputView(finishingInput);
         cleanupInternalStateForFinishInput();
     }
 
     private void cleanupInternalStateForFinishInput() {
-        mKeyboardSwitcher.deallocateMemory();
         // Remove pending messages related to update suggestions
         mHandler.cancelUpdateSuggestionStrip();
         // Should do the following in onFinishInputInternal but until JB MR2 it's not called :(
         mInputLogic.finishInput();
     }
 
+    protected void deallocateMemory() {
+        mKeyboardSwitcher.deallocateMemory();
+    }
+
     @Override
     public void onUpdateSelection(final int oldSelStart, final int oldSelEnd,
             final int newSelStart, final int newSelEnd,
             final int composingSpanStart, final int composingSpanEnd) {
         super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                 composingSpanStart, composingSpanEnd);
-        if (DEBUG) {
+        if (DebugFlags.DEBUG_ENABLED) {
             Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd
                     + ", nss=" + newSelStart + ", nse=" + newSelEnd
                     + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
         }
 
-        // This call happens when we have a hardware keyboard as well as when we don't. While we
-        // don't support hardware keyboards yet we should avoid doing the processing associated
-        // with cursor movement when we have a hardware keyboard since we are not in charge.
+        // This call happens whether our view is displayed or not, but if it's not then we should
+        // not attempt recorrection. This is true even with a hardware keyboard connected: if the
+        // view is not displayed we have no means of showing suggestions anyway, and if it is then
+        // we want to show suggestions anyway.
         final SettingsValues settingsValues = mSettings.getCurrent();
-        if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED)
+        if (isInputViewShown()
                 && mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                         settingsValues)) {
             mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
@@ -1040,15 +1020,6 @@
         }
     }
 
-    // We cannot mark this method as @Override until new SDK becomes publicly available.
-    // @Override
-    public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
-        if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || isFullscreenMode()) {
-            return;
-        }
-        mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
-    }
-
     /**
      * This is called when the user has clicked on the extracted text view,
      * when running in fullscreen mode.  The default implementation hides
@@ -1098,7 +1069,7 @@
 
     @Override
     public void onDisplayCompletions(final CompletionInfo[] applicationSpecifiedCompletions) {
-        if (DEBUG) {
+        if (DebugFlags.DEBUG_ENABLED) {
             Log.i(TAG, "Received completions:");
             if (applicationSpecifiedCompletions != null) {
                 for (int i = 0; i < applicationSpecifiedCompletions.length; i++) {
@@ -1121,9 +1092,13 @@
                 SuggestedWords.getFromApplicationSpecifiedCompletions(
                         applicationSpecifiedCompletions);
         final SuggestedWords suggestedWords = new SuggestedWords(applicationSuggestedWords,
-                null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
+                null /* rawSuggestions */,
+                null /* typedWord */,
+                false /* typedWordValid */,
+                false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
-                SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */);
+                SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
         // When in fullscreen mode, show completions generated by the application forcibly
         setSuggestedWords(suggestedWords);
     }
@@ -1131,6 +1106,10 @@
     @Override
     public void onComputeInsets(final InputMethodService.Insets outInsets) {
         super.onComputeInsets(outInsets);
+        // This method may be called before {@link #setInputView(View)}.
+        if (mInputView == null) {
+            return;
+        }
         final SettingsValues settingsValues = mSettings.getCurrent();
         final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
         if (visibleKeyboardView == null || !hasSuggestionStripView()) {
@@ -1141,8 +1120,9 @@
         if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
             // If there is a hardware keyboard and a visible software keyboard view has been hidden,
             // no visual element will be shown on the screen.
-            outInsets.touchableInsets = inputHeight;
+            outInsets.contentTopInsets = inputHeight;
             outInsets.visibleTopInsets = inputHeight;
+            mInsetsUpdater.setInsets(outInsets);
             return;
         }
         final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes()
@@ -1150,7 +1130,7 @@
                 ? mSuggestionStripView.getHeight() : 0;
         final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
         mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
-        // Need to set touchable region only if a keyboard view is being shown.
+        // Need to set expanded touchable region only if a keyboard view is being shown.
         if (visibleKeyboardView.isShown()) {
             final int touchLeft = 0;
             final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY;
@@ -1163,14 +1143,18 @@
         }
         outInsets.contentTopInsets = visibleTopY;
         outInsets.visibleTopInsets = visibleTopY;
+        mInsetsUpdater.setInsets(outInsets);
     }
 
-    public void startShowingInputView() {
+    public void startShowingInputView(final boolean needsToLoadKeyboard) {
         mIsExecutingStartShowingInputView = true;
         // This {@link #showWindow(boolean)} will eventually call back
         // {@link #onEvaluateInputViewShown()}.
         showWindow(true /* showInput */);
         mIsExecutingStartShowingInputView = false;
+        if (needsToLoadKeyboard) {
+            loadKeyboard();
+        }
     }
 
     public void stopShowingInputView() {
@@ -1178,6 +1162,14 @@
     }
 
     @Override
+    public boolean onShowInputRequested(final int flags, final boolean configChange) {
+        if (Settings.getInstance().getCurrent().mHasHardwareKeyboard) {
+            return true;
+        }
+        return super.onShowInputRequested(flags, configChange);
+    }
+
+    @Override
     public boolean onEvaluateInputViewShown() {
         if (mIsExecutingStartShowingInputView) {
             return true;
@@ -1207,8 +1199,13 @@
 
     @Override
     public void updateFullscreenMode() {
+        super.updateFullscreenMode();
+        updateSoftInputWindowLayoutParameters();
+    }
+
+    private void updateSoftInputWindowLayoutParameters() {
         // Override layout parameters to expand {@link SoftInputWindow} to the entire screen.
-        // See {@link InputMethodService#setinputView(View) and
+        // See {@link InputMethodService#setinputView(View)} and
         // {@link SoftInputWindow#updateWidthHeight(WindowManager.LayoutParams)}.
         final Window window = getWindow().getWindow();
         ViewLayoutUtils.updateLayoutHeightOf(window, LayoutParams.MATCH_PARENT);
@@ -1227,22 +1224,16 @@
             ViewLayoutUtils.updateLayoutGravityOf(inputArea, Gravity.BOTTOM);
             ViewLayoutUtils.updateLayoutHeightOf(mInputView, layoutHeight);
         }
-        super.updateFullscreenMode();
-        mInputLogic.onUpdateFullscreenMode(isFullscreenMode());
     }
 
-    private int getCurrentAutoCapsState() {
+    int getCurrentAutoCapsState() {
         return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
     }
 
-    private int getCurrentRecapitalizeState() {
+    int getCurrentRecapitalizeState() {
         return mInputLogic.getCurrentRecapitalizeState();
     }
 
-    public Locale getCurrentSubtypeLocale() {
-        return mSubtypeSwitcher.getCurrentSubtypeLocale();
-    }
-
     /**
      * @param codePoints code points to get coordinates for.
      * @return x,y coordinates for this keyboard, as a flattened array.
@@ -1256,24 +1247,6 @@
         return keyboard.getCoordinates(codePoints);
     }
 
-    // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
-    // pressed.
-    @Override
-    public void addWordToUserDictionary(final String word) {
-        if (TextUtils.isEmpty(word)) {
-            // Probably never supposed to happen, but just in case.
-            return;
-        }
-        final String wordToEdit;
-        if (CapsModeUtils.isAutoCapsMode(mInputLogic.mLastComposedWord.mCapitalizedMode)) {
-            wordToEdit = word.toLowerCase(getCurrentSubtypeLocale());
-        } else {
-            wordToEdit = word;
-        }
-        mDictionaryFacilitator.addWordToUserDictionary(this /* context */, wordToEdit);
-        mInputLogic.onAddWordToUserDictionary();
-    }
-
     // Callback for the {@link SuggestionStripView}, to call when the important notice strip is
     // pressed.
     @Override
@@ -1284,7 +1257,7 @@
     // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
     @Override
     public void onClickSettingsOfImportantNoticeDialog(final int nextVersion) {
-        launchSettings();
+        launchSettings(SettingsActivity.EXTRA_ENTRY_VALUE_NOTICE_DIALOG);
     }
 
     // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
@@ -1328,48 +1301,56 @@
         mSubtypeState.switchSubtype(token, mRichImm);
     }
 
+    // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
+    // alphabetic shift and shift while in symbol layout and get rid of this method.
+    private int getCodePointForKeyboard(final int codePoint) {
+        if (Constants.CODE_SHIFT == codePoint) {
+            final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
+            if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
+                return codePoint;
+            }
+            return Constants.CODE_SYMBOL_SHIFT;
+        }
+        return codePoint;
+    }
+
     // Implementation of {@link KeyboardActionListener}.
     @Override
     public void onCodeInput(final int codePoint, final int x, final int y,
             final boolean isKeyRepeat) {
+        // TODO: this processing does not belong inside LatinIME, the caller should be doing this.
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
         // x and y include some padding, but everything down the line (especially native
         // code) needs the coordinates in the keyboard frame.
         // TODO: We should reconsider which coordinate system should be used to represent
         // keyboard event. Also we should pull this up -- LatinIME has no business doing
-        // this transformation, it should be done already before calling onCodeInput.
+        // this transformation, it should be done already before calling onEvent.
         final int keyX = mainKeyboardView.getKeyX(x);
         final int keyY = mainKeyboardView.getKeyY(y);
-        final int codeToSend;
-        if (Constants.CODE_SHIFT == codePoint) {
-            // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
-            // alphabetic shift and shift while in symbol layout.
-            final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
-            if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
-                codeToSend = codePoint;
-            } else {
-                codeToSend = Constants.CODE_SYMBOL_SHIFT;
-            }
-        } else {
-            codeToSend = codePoint;
+        final Event event = createSoftwareKeypressEvent(getCodePointForKeyboard(codePoint),
+                keyX, keyY, isKeyRepeat);
+        onEvent(event);
+    }
+
+    // This method is public for testability of LatinIME, but also in the future it should
+    // completely replace #onCodeInput.
+    public void onEvent(@Nonnull final Event event) {
+        if (Constants.CODE_SHORTCUT == event.mKeyCode) {
+            mRichImm.switchToShortcutIme(this);
         }
-        if (Constants.CODE_SHORTCUT == codePoint) {
-            mSubtypeSwitcher.switchToShortcutIME(this);
-            // Still call the *#onCodeInput methods for readability.
-        }
-        final Event event = createSoftwareKeypressEvent(codeToSend, keyX, keyY, isKeyRepeat);
         final InputTransaction completeInputTransaction =
                 mInputLogic.onCodeInput(mSettings.getCurrent(), event,
                         mKeyboardSwitcher.getKeyboardShiftMode(),
                         mKeyboardSwitcher.getCurrentKeyboardScriptId(), mHandler);
         updateStateAfterInputTransaction(completeInputTransaction);
-        mKeyboardSwitcher.onCodeInput(codePoint, getCurrentAutoCapsState(),
-                getCurrentRecapitalizeState());
+        mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
     }
 
     // A helper method to split the code point and the key code. Ultimately, they should not be
     // squashed into the same variable, and this method should be removed.
-    private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
+    // public for testing, as we don't want to copy the same logic into test code
+    @Nonnull
+    public static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
              final int keyY, final boolean isKeyRepeat) {
         final int keyCode;
         final int codePoint;
@@ -1387,44 +1368,59 @@
     @Override
     public void onTextInput(final String rawText) {
         // TODO: have the keyboard pass the correct key code when we need it.
-        final Event event = Event.createSoftwareTextEvent(rawText, Event.NOT_A_KEY_CODE);
+        final Event event = Event.createSoftwareTextEvent(rawText, Constants.CODE_OUTPUT_TEXT);
         final InputTransaction completeInputTransaction =
                 mInputLogic.onTextInput(mSettings.getCurrent(), event,
                         mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
         updateStateAfterInputTransaction(completeInputTransaction);
-        mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState(),
-                getCurrentRecapitalizeState());
+        mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
     }
 
     @Override
     public void onStartBatchInput() {
         mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
+        mGestureConsumer.onGestureStarted(
+                mRichImm.getCurrentSubtypeLocale(),
+                mKeyboardSwitcher.getKeyboard());
     }
 
     @Override
     public void onUpdateBatchInput(final InputPointers batchPointers) {
-        mInputLogic.onUpdateBatchInput(mSettings.getCurrent(), batchPointers, mKeyboardSwitcher);
+        mInputLogic.onUpdateBatchInput(batchPointers);
     }
 
     @Override
     public void onEndBatchInput(final InputPointers batchPointers) {
         mInputLogic.onEndBatchInput(batchPointers);
+        mGestureConsumer.onGestureCompleted(batchPointers);
     }
 
     @Override
     public void onCancelBatchInput() {
         mInputLogic.onCancelBatchInput(mHandler);
+        mGestureConsumer.onGestureCanceled();
+    }
+
+    /**
+     * To be called after the InputLogic has gotten a chance to act on the suggested words by the
+     * IME for the full gesture, possibly updating the TextView to reflect the first suggestion.
+     * <p>
+     * This method must be run on the UI Thread.
+     * @param suggestedWords suggested words by the IME for the full gesture.
+     */
+    public void onTailBatchInputResultShown(final SuggestedWords suggestedWords) {
+        mGestureConsumer.onImeSuggestionsProcessed(suggestedWords,
+                mInputLogic.getComposingStart(), mInputLogic.getComposingLength(),
+                mDictionaryFacilitator);
     }
 
     // This method must run on the UI Thread.
-    private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
+    void showGesturePreviewAndSuggestionStrip(@Nonnull final SuggestedWords suggestedWords,
             final boolean dismissGestureFloatingPreviewText) {
         showSuggestionStrip(suggestedWords);
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
-        mainKeyboardView.showGestureFloatingPreviewText(suggestedWords);
-        if (dismissGestureFloatingPreviewText) {
-            mainKeyboardView.dismissGestureFloatingPreviewText();
-        }
+        mainKeyboardView.showGestureFloatingPreviewText(suggestedWords,
+                dismissGestureFloatingPreviewText /* dismissDelayed */);
     }
 
     // Called from PointerTracker through the KeyboardActionListener interface
@@ -1446,22 +1442,9 @@
         return null != mSuggestionStripView;
     }
 
-    @Override
-    public boolean isShowingAddToDictionaryHint() {
-        return hasSuggestionStripView() && mSuggestionStripView.isShowingAddToDictionaryHint();
-    }
-
-    @Override
-    public void dismissAddToDictionaryHint() {
-        if (!hasSuggestionStripView()) {
-            return;
-        }
-        mSuggestionStripView.dismissAddToDictionaryHint();
-    }
-
     private void setSuggestedWords(final SuggestedWords suggestedWords) {
         final SettingsValues currentSettingsValues = mSettings.getCurrent();
-        mInputLogic.setSuggestedWords(suggestedWords, currentSettingsValues, mHandler);
+        mInputLogic.setSuggestedWords(suggestedWords);
         // TODO: Modify this when we support suggestions with hard keyboard
         if (!hasSuggestionStripView()) {
             return;
@@ -1471,7 +1454,7 @@
         }
 
         final boolean shouldShowImportantNotice =
-                ImportantNoticeUtils.shouldShowImportantNotice(this);
+                ImportantNoticeUtils.shouldShowImportantNotice(this, currentSettingsValues);
         final boolean shouldShowSuggestionCandidates =
                 currentSettingsValues.mInputAttributes.mShouldShowSuggestions
                 && currentSettingsValues.isSuggestionsEnabledPerUserSettings();
@@ -1489,7 +1472,7 @@
         final boolean isEmptyApplicationSpecifiedCompletions =
                 currentSettingsValues.isApplicationSpecifiedCompletionsOn()
                 && suggestedWords.isEmpty();
-        final boolean noSuggestionsFromDictionaries = (SuggestedWords.EMPTY == suggestedWords)
+        final boolean noSuggestionsFromDictionaries = suggestedWords.isEmpty()
                 || suggestedWords.isPunctuationSuggestions()
                 || isEmptyApplicationSpecifiedCompletions;
         final boolean isBeginningOfSentencePrediction = (suggestedWords.mInputStyle
@@ -1507,7 +1490,7 @@
                 // We should clear the contextual strip if there is no suggestion from dictionaries.
                 || noSuggestionsFromDictionaries) {
             mSuggestionStripView.setSuggestions(suggestedWords,
-                    SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
+                    mRichImm.getCurrentSubtype().isRtlSubtype());
         }
     }
 
@@ -1516,26 +1499,23 @@
             final OnGetSuggestedWordsCallback callback) {
         final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
         if (keyboard == null) {
-            callback.onGetSuggestedWords(SuggestedWords.EMPTY);
+            callback.onGetSuggestedWords(SuggestedWords.getEmptyInstance());
             return;
         }
-        mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(),
+        mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard,
                 mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback);
     }
 
     @Override
-    public void showSuggestionStrip(final SuggestedWords sourceSuggestedWords) {
-        final SuggestedWords suggestedWords =
-                sourceSuggestedWords.isEmpty() ? SuggestedWords.EMPTY : sourceSuggestedWords;
-        if (SuggestedWords.EMPTY == suggestedWords) {
+    public void showSuggestionStrip(final SuggestedWords suggestedWords) {
+        if (suggestedWords.isEmpty()) {
             setNeutralSuggestionStrip();
         } else {
             setSuggestedWords(suggestedWords);
         }
         // Cache the auto-correction in accessibility code so we can speak it if the user
         // touches a key that will insert it.
-        AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords,
-                sourceSuggestedWords.mTypedWord);
+        AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords);
     }
 
     // Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
@@ -1550,25 +1530,17 @@
         updateStateAfterInputTransaction(completeInputTransaction);
     }
 
-    @Override
-    public void showAddToDictionaryHint(final String word) {
-        if (!hasSuggestionStripView()) {
-            return;
-        }
-        mSuggestionStripView.showAddToDictionaryHint(word);
-    }
-
     // This will show either an empty suggestion strip (if prediction is enabled) or
     // punctuation suggestions (if it's disabled).
     @Override
     public void setNeutralSuggestionStrip() {
         final SettingsValues currentSettings = mSettings.getCurrent();
         final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled
-                ? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
+                ? SuggestedWords.getEmptyInstance()
+                : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
         setSuggestedWords(neutralSuggestions);
     }
 
-    // TODO: Make this private
     // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
     @UsedForTesting
     void loadKeyboard() {
@@ -1676,7 +1648,8 @@
     // Hooks for hardware keyboard
     @Override
     public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
-        mSpecialKeyDetector.onKeyDown(keyEvent);
+        // TODO: This should be processed in {@link InputLogic}.
+        mEmojiAltPhysicalKeyDetector.onKeyDown(keyEvent);
         if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
             return super.onKeyDown(keyCode, keyEvent);
         }
@@ -1697,7 +1670,8 @@
 
     @Override
     public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) {
-        mSpecialKeyDetector.onKeyUp(keyEvent);
+        // TODO: This should be processed in {@link InputLogic}.
+        mEmojiAltPhysicalKeyDetector.onKeyUp(keyEvent);
         if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
             return super.onKeyUp(keyCode, keyEvent);
         }
@@ -1713,21 +1687,18 @@
     // boolean onKeyLongPress(final int keyCode, final KeyEvent event);
     // boolean onKeyMultiple(final int keyCode, final int count, final KeyEvent event);
 
-    // receive ringer mode change and network state change.
-    private final BroadcastReceiver mConnectivityAndRingerModeChangeReceiver =
-            new BroadcastReceiver() {
+    // receive ringer mode change.
+    private final BroadcastReceiver mRingerModeChangeReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(final Context context, final Intent intent) {
             final String action = intent.getAction();
-            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                mSubtypeSwitcher.onNetworkStateChanged(intent);
-            } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+            if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
                 AudioAndHapticFeedbackManager.getInstance().onRingerModeChanged();
             }
         }
     };
 
-    private void launchSettings() {
+    void launchSettings(final String extraEntryValue) {
         mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
         requestHideSelf(0);
         final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1740,6 +1711,7 @@
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
         intent.putExtra(SettingsActivity.EXTRA_SHOW_HOME_AS_UP, false);
+        intent.putExtra(SettingsActivity.EXTRA_ENTRY_KEY, extraEntryValue);
         startActivity(intent);
     }
 
@@ -1751,6 +1723,7 @@
                 languageSelectionTitle,
                 getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
         };
+        final String imeId = mRichImm.getInputMethodIdOfThisIme();
         final OnClickListener listener = new OnClickListener() {
             @Override
             public void onClick(DialogInterface di, int position) {
@@ -1758,7 +1731,7 @@
                 switch (position) {
                 case 0:
                     final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
-                            mRichImm.getInputMethodIdOfThisIme(),
+                            imeId,
                             Intent.FLAG_ACTIVITY_NEW_TASK
                                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -1766,7 +1739,7 @@
                     startActivity(intent);
                     break;
                 case 1:
-                    launchSettings();
+                    launchSettings(SettingsActivity.EXTRA_ENTRY_VALUE_LONG_PRESS_COMMA);
                     break;
                 }
             }
@@ -1798,45 +1771,45 @@
         dialog.show();
     }
 
-    // TODO: can this be removed somehow without breaking the tests?
     @UsedForTesting
-    /* package for test */ SuggestedWords getSuggestedWordsForTest() {
+    SuggestedWords getSuggestedWordsForTest() {
         // You may not use this method for anything else than debug
-        return DEBUG ? mInputLogic.mSuggestedWords : null;
+        return DebugFlags.DEBUG_ENABLED ? mInputLogic.mSuggestedWords : null;
     }
 
     // DO NOT USE THIS for any other purpose than testing. This is information private to LatinIME.
     @UsedForTesting
-    /* package for test */ void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
+    void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
             throws InterruptedException {
         mDictionaryFacilitator.waitForLoadingDictionariesForTesting(timeout, unit);
     }
 
     // DO NOT USE THIS for any other purpose than testing. This can break the keyboard badly.
     @UsedForTesting
-    /* package for test */ void replaceDictionariesForTest(final Locale locale) {
+    void replaceDictionariesForTest(final Locale locale) {
         final SettingsValues settingsValues = mSettings.getCurrent();
         mDictionaryFacilitator.resetDictionaries(this, locale,
             settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
-            false /* forceReloadMainDictionary */, this /* listener */);
+            false /* forceReloadMainDictionary */,
+            settingsValues.mAccount, "", /* dictionaryNamePrefix */
+            this /* DictionaryInitializationListener */);
     }
 
     // DO NOT USE THIS for any other purpose than testing.
     @UsedForTesting
-    /* package for test */ void clearPersonalizedDictionariesForTest() {
-        mDictionaryFacilitator.clearUserHistoryDictionary();
-        mDictionaryFacilitator.clearPersonalizationDictionary();
+    void clearPersonalizedDictionariesForTest() {
+        mDictionaryFacilitator.clearUserHistoryDictionary(this);
     }
 
     @UsedForTesting
-    /* package for test */ List<InputMethodSubtype> getEnabledSubtypesForTest() {
+    List<InputMethodSubtype> getEnabledSubtypesForTest() {
         return (mRichImm != null) ? mRichImm.getMyEnabledInputMethodSubtypeList(
                 true /* allowsImplicitlySelectedSubtypes */) : new ArrayList<InputMethodSubtype>();
     }
 
     public void dumpDictionaryForDebug(final String dictName) {
-        if (mDictionaryFacilitator.getLocale() == null) {
-            resetSuggest();
+        if (!mDictionaryFacilitator.isActive()) {
+            resetDictionaryFacilitatorIfNecessary();
         }
         mDictionaryFacilitator.dumpDictionaryForDebug(dictName);
     }
@@ -1862,6 +1835,7 @@
         p.println("  Keyboard mode = " + keyboardMode);
         final SettingsValues settingsValues = mSettings.getCurrent();
         p.println(settingsValues.dump());
+        p.println(mDictionaryFacilitator.dump(this /* context */));
         // TODO: Dump all settings values
     }
 
diff --git a/java/src/com/android/inputmethod/latin/NgramContext.java b/java/src/com/android/inputmethod/latin/NgramContext.java
new file mode 100644
index 0000000..9682fb8
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/NgramContext.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.text.TextUtils;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Class to represent information of previous words. This class is used to add n-gram entries
+ * into binary dictionaries, to get predictions, and to get suggestions.
+ */
+public class NgramContext {
+    @Nonnull
+    public static final NgramContext EMPTY_PREV_WORDS_INFO =
+            new NgramContext(WordInfo.EMPTY_WORD_INFO);
+    @Nonnull
+    public static final NgramContext BEGINNING_OF_SENTENCE =
+            new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+
+    public static final String BEGINNING_OF_SENTENCE_TAG = "<S>";
+
+    public static final String CONTEXT_SEPARATOR = " ";
+
+    public static NgramContext getEmptyPrevWordsContext(int maxPrevWordCount) {
+        return new NgramContext(maxPrevWordCount, WordInfo.EMPTY_WORD_INFO);
+    }
+
+    /**
+     * Word information used to represent previous words information.
+     */
+    public static class WordInfo {
+        @Nonnull
+        public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
+        @Nonnull
+        public static final WordInfo BEGINNING_OF_SENTENCE_WORD_INFO = new WordInfo();
+
+        // This is an empty char sequence when mIsBeginningOfSentence is true.
+        public final CharSequence mWord;
+        // TODO: Have sentence separator.
+        // Whether the current context is beginning of sentence or not. This is true when composing
+        // at the beginning of an input field or composing a word after a sentence separator.
+        public final boolean mIsBeginningOfSentence;
+
+        // Beginning of sentence.
+        private WordInfo() {
+            mWord = "";
+            mIsBeginningOfSentence = true;
+        }
+
+        public WordInfo(final CharSequence word) {
+            mWord = word;
+            mIsBeginningOfSentence = false;
+        }
+
+        public boolean isValid() {
+            return mWord != null;
+        }
+
+        @Override
+        public int hashCode() {
+            return Arrays.hashCode(new Object[] { mWord, mIsBeginningOfSentence } );
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof WordInfo)) return false;
+            final WordInfo wordInfo = (WordInfo)o;
+            if (mWord == null || wordInfo.mWord == null) {
+                return mWord == wordInfo.mWord
+                        && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
+            }
+            return TextUtils.equals(mWord, wordInfo.mWord)
+                    && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
+        }
+    }
+
+    // The words immediately before the considered word. EMPTY_WORD_INFO element means we don't
+    // have any context for that previous word including the "beginning of sentence context" - we
+    // just don't know what to predict using the information. An example of that is after a comma.
+    // For simplicity of implementation, elements may also be EMPTY_WORD_INFO transiently after the
+    // WordComposer was reset and before starting a new composing word, but we should never be
+    // calling getSuggetions* in this situation.
+    private final WordInfo[] mPrevWordsInfo;
+    private final int mPrevWordsCount;
+
+    private final int mMaxPrevWordCount;
+
+    // Construct from the previous word information.
+    public NgramContext(final WordInfo... prevWordsInfo) {
+        this(DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM, prevWordsInfo);
+    }
+
+    public NgramContext(final int maxPrevWordCount, final WordInfo... prevWordsInfo) {
+        mPrevWordsInfo = prevWordsInfo;
+        mPrevWordsCount = prevWordsInfo.length;
+        mMaxPrevWordCount = maxPrevWordCount;
+    }
+
+    /**
+     * Create next prevWordsInfo using current prevWordsInfo.
+     */
+    @Nonnull
+    public NgramContext getNextNgramContext(final WordInfo wordInfo) {
+        final int nextPrevWordCount = Math.min(mMaxPrevWordCount, mPrevWordsCount + 1);
+        final WordInfo[] prevWordsInfo = new WordInfo[nextPrevWordCount];
+        prevWordsInfo[0] = wordInfo;
+        System.arraycopy(mPrevWordsInfo, 0, prevWordsInfo, 1, nextPrevWordCount - 1);
+        return new NgramContext(mMaxPrevWordCount, prevWordsInfo);
+    }
+
+
+    /**
+     * Extracts the previous words context.
+     *
+     * @return a String with the previous words separated by white space.
+     */
+    public String extractPrevWordsContext() {
+        final ArrayList<String> terms = new ArrayList<>();
+        for (int i = mPrevWordsInfo.length - 1; i >= 0; --i) {
+            if (mPrevWordsInfo[i] != null && mPrevWordsInfo[i].isValid()) {
+                final NgramContext.WordInfo wordInfo = mPrevWordsInfo[i];
+                if (wordInfo.mIsBeginningOfSentence) {
+                    terms.add(BEGINNING_OF_SENTENCE_TAG);
+                } else {
+                    final String term = wordInfo.mWord.toString();
+                    if (!term.isEmpty()) {
+                        terms.add(term);
+                    }
+                }
+            }
+        }
+        return TextUtils.join(CONTEXT_SEPARATOR, terms);
+    }
+
+    /**
+     * Extracts the previous words context.
+     *
+     * @return a String array with the previous words.
+     */
+    public String[] extractPrevWordsContextArray() {
+        final ArrayList<String> prevTermList = new ArrayList<>();
+        for (int i = mPrevWordsInfo.length - 1; i >= 0; --i) {
+            if (mPrevWordsInfo[i] != null && mPrevWordsInfo[i].isValid()) {
+                final NgramContext.WordInfo wordInfo = mPrevWordsInfo[i];
+                if (wordInfo.mIsBeginningOfSentence) {
+                    prevTermList.add(BEGINNING_OF_SENTENCE_TAG);
+                } else {
+                    final String term = wordInfo.mWord.toString();
+                    if (!term.isEmpty()) {
+                        prevTermList.add(term);
+                    }
+                }
+            }
+        }
+        final String[] contextStringArray = prevTermList.toArray(new String[prevTermList.size()]);
+        return contextStringArray;
+    }
+
+    public boolean isValid() {
+        return mPrevWordsCount > 0 && mPrevWordsInfo[0].isValid();
+    }
+
+    public boolean isBeginningOfSentenceContext() {
+        return mPrevWordsCount > 0 && mPrevWordsInfo[0].mIsBeginningOfSentence;
+    }
+
+    // n is 1-indexed.
+    // TODO: Remove
+    public CharSequence getNthPrevWord(final int n) {
+        if (n <= 0 || n > mPrevWordsCount) {
+            return null;
+        }
+        return mPrevWordsInfo[n - 1].mWord;
+    }
+
+    // n is 1-indexed.
+    @UsedForTesting
+    public boolean isNthPrevWordBeginningOfSentence(final int n) {
+        if (n <= 0 || n > mPrevWordsCount) {
+            return false;
+        }
+        return mPrevWordsInfo[n - 1].mIsBeginningOfSentence;
+    }
+
+    public void outputToArray(final int[][] codePointArrays,
+            final boolean[] isBeginningOfSentenceArray) {
+        for (int i = 0; i < mPrevWordsCount; i++) {
+            final WordInfo wordInfo = mPrevWordsInfo[i];
+            if (wordInfo == null || !wordInfo.isValid()) {
+                codePointArrays[i] = new int[0];
+                isBeginningOfSentenceArray[i] = false;
+                continue;
+            }
+            codePointArrays[i] = StringUtils.toCodePointArray(wordInfo.mWord);
+            isBeginningOfSentenceArray[i] = wordInfo.mIsBeginningOfSentence;
+        }
+    }
+
+    public int getPrevWordCount() {
+        return mPrevWordsCount;
+    }
+
+    @Override
+    public int hashCode() {
+        int hashValue = 0;
+        for (final WordInfo wordInfo : mPrevWordsInfo) {
+            if (wordInfo == null || !WordInfo.EMPTY_WORD_INFO.equals(wordInfo)) {
+                break;
+            }
+            hashValue ^= wordInfo.hashCode();
+        }
+        return hashValue;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof NgramContext)) return false;
+        final NgramContext prevWordsInfo = (NgramContext)o;
+
+        final int minLength = Math.min(mPrevWordsCount, prevWordsInfo.mPrevWordsCount);
+        for (int i = 0; i < minLength; i++) {
+            if (!mPrevWordsInfo[i].equals(prevWordsInfo.mPrevWordsInfo[i])) {
+                return false;
+            }
+        }
+        final WordInfo[] longerWordsInfo;
+        final int longerWordsInfoCount;
+        if (mPrevWordsCount > prevWordsInfo.mPrevWordsCount) {
+            longerWordsInfo = mPrevWordsInfo;
+            longerWordsInfoCount = mPrevWordsCount;
+        } else {
+            longerWordsInfo = prevWordsInfo.mPrevWordsInfo;
+            longerWordsInfoCount = prevWordsInfo.mPrevWordsCount;
+        }
+        for (int i = minLength; i < longerWordsInfoCount; i++) {
+            if (longerWordsInfo[i] != null
+                    && !WordInfo.EMPTY_WORD_INFO.equals(longerWordsInfo[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer builder = new StringBuffer();
+        for (int i = 0; i < mPrevWordsCount; i++) {
+            final WordInfo wordInfo = mPrevWordsInfo[i];
+            builder.append("PrevWord[");
+            builder.append(i);
+            builder.append("]: ");
+            if (wordInfo == null) {
+                builder.append("null. ");
+                continue;
+            }
+            if (!wordInfo.isValid()) {
+                builder.append("Empty. ");
+                continue;
+            }
+            builder.append(wordInfo.mWord);
+            builder.append(", isBeginningOfSentence: ");
+            builder.append(wordInfo.mIsBeginningOfSentence);
+            builder.append(". ");
+        }
+        return builder.toString();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java
deleted file mode 100644
index db877ab..0000000
--- a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.text.TextUtils;
-
-import com.android.inputmethod.latin.utils.StringUtils;
-
-import java.util.Arrays;
-
-/**
- * Class to represent information of previous words. This class is used to add n-gram entries
- * into binary dictionaries, to get predictions, and to get suggestions.
- */
-public class PrevWordsInfo {
-    public static final PrevWordsInfo EMPTY_PREV_WORDS_INFO =
-            new PrevWordsInfo(WordInfo.EMPTY_WORD_INFO);
-    public static final PrevWordsInfo BEGINNING_OF_SENTENCE =
-            new PrevWordsInfo(WordInfo.BEGINNING_OF_SENTENCE);
-
-    /**
-     * Word information used to represent previous words information.
-     */
-    public static class WordInfo {
-        public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
-        public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo();
-
-        // This is an empty char sequence when mIsBeginningOfSentence is true.
-        public final CharSequence mWord;
-        // TODO: Have sentence separator.
-        // Whether the current context is beginning of sentence or not. This is true when composing
-        // at the beginning of an input field or composing a word after a sentence separator.
-        public final boolean mIsBeginningOfSentence;
-
-        // Beginning of sentence.
-        public WordInfo() {
-            mWord = "";
-            mIsBeginningOfSentence = true;
-        }
-
-        public WordInfo(final CharSequence word) {
-            mWord = word;
-            mIsBeginningOfSentence = false;
-        }
-
-        public boolean isValid() {
-            return mWord != null;
-        }
-
-        @Override
-        public int hashCode() {
-            return Arrays.hashCode(new Object[] { mWord, mIsBeginningOfSentence } );
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof WordInfo)) return false;
-            final WordInfo wordInfo = (WordInfo)o;
-            if (mWord == null || wordInfo.mWord == null) {
-                return mWord == wordInfo.mWord
-                        && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
-            }
-            return TextUtils.equals(mWord, wordInfo.mWord)
-                    && mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
-        }
-    }
-
-    // The words immediately before the considered word. EMPTY_WORD_INFO element means we don't
-    // have any context for that previous word including the "beginning of sentence context" - we
-    // just don't know what to predict using the information. An example of that is after a comma.
-    // For simplicity of implementation, elements may also be EMPTY_WORD_INFO transiently after the
-    // WordComposer was reset and before starting a new composing word, but we should never be
-    // calling getSuggetions* in this situation.
-    public WordInfo[] mPrevWordsInfo = new WordInfo[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-
-    // Construct from the previous word information.
-    public PrevWordsInfo(final WordInfo prevWordInfo) {
-        mPrevWordsInfo[0] = prevWordInfo;
-    }
-
-    // Construct from WordInfo array. n-th element represents (n+1)-th previous word's information.
-    public PrevWordsInfo(final WordInfo[] prevWordsInfo) {
-        for (int i = 0; i < Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM; i++) {
-            mPrevWordsInfo[i] =
-                    (prevWordsInfo.length > i) ? prevWordsInfo[i] : WordInfo.EMPTY_WORD_INFO;
-        }
-    }
-
-    // Create next prevWordsInfo using current prevWordsInfo.
-    public PrevWordsInfo getNextPrevWordsInfo(final WordInfo wordInfo) {
-        final WordInfo[] prevWordsInfo = new WordInfo[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        prevWordsInfo[0] = wordInfo;
-        for (int i = 1; i < prevWordsInfo.length; i++) {
-            prevWordsInfo[i] = mPrevWordsInfo[i - 1];
-        }
-        return new PrevWordsInfo(prevWordsInfo);
-    }
-
-    public boolean isValid() {
-        return mPrevWordsInfo[0].isValid();
-    }
-
-    public void outputToArray(final int[][] codePointArrays,
-            final boolean[] isBeginningOfSentenceArray) {
-        for (int i = 0; i < mPrevWordsInfo.length; i++) {
-            final WordInfo wordInfo = mPrevWordsInfo[i];
-            if (wordInfo == null || !wordInfo.isValid()) {
-                codePointArrays[i] = new int[0];
-                isBeginningOfSentenceArray[i] = false;
-                continue;
-            }
-            codePointArrays[i] = StringUtils.toCodePointArray(wordInfo.mWord);
-            isBeginningOfSentenceArray[i] = wordInfo.mIsBeginningOfSentence;
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        return Arrays.hashCode(mPrevWordsInfo);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof PrevWordsInfo)) return false;
-        final PrevWordsInfo prevWordsInfo = (PrevWordsInfo)o;
-        return Arrays.equals(mPrevWordsInfo, prevWordsInfo.mPrevWordsInfo);
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer builder = new StringBuffer();
-        for (int i = 0; i < mPrevWordsInfo.length; i++) {
-            final WordInfo wordInfo = mPrevWordsInfo[i];
-            builder.append("PrevWord[");
-            builder.append(i);
-            builder.append("]: ");
-            if (wordInfo == null || !wordInfo.isValid()) {
-                builder.append("Empty. ");
-                continue;
-            }
-            builder.append(wordInfo.mWord);
-            builder.append(", isBeginningOfSentence: ");
-            builder.append(wordInfo.mIsBeginningOfSentence);
-            builder.append(". ");
-        }
-        return builder.toString();
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
index 56014cb..e2c5621 100644
--- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
@@ -17,11 +17,14 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.internal.KeySpecParser;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 
+import javax.annotation.Nullable;
+
 /**
  * The extended {@link SuggestedWords} class to represent punctuation suggestions.
  *
@@ -32,10 +35,12 @@
     private PunctuationSuggestions(final ArrayList<SuggestedWordInfo> punctuationsList) {
         super(punctuationsList,
                 null /* rawSuggestions */,
+                null /* typedWord */,
                 false /* typedWordValid */,
                 false /* hasAutoCorrectionCandidate */,
                 false /* isObsoleteSuggestions */,
-                INPUT_STYLE_NONE /* inputStyle */);
+                INPUT_STYLE_NONE /* inputStyle */,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
     }
 
     /**
@@ -46,17 +51,21 @@
      * @return The {@link PunctuationSuggestions} object.
      */
     public static PunctuationSuggestions newPunctuationSuggestions(
-            final String[] punctuationSpecs) {
-        final ArrayList<SuggestedWordInfo> puncuationsList = new ArrayList<>();
-        for (final String puncSpec : punctuationSpecs) {
-            puncuationsList.add(newHardCodedWordInfo(puncSpec));
+            @Nullable final String[] punctuationSpecs) {
+        if (punctuationSpecs == null || punctuationSpecs.length == 0) {
+            return new PunctuationSuggestions(new ArrayList<SuggestedWordInfo>(0));
         }
-        return new PunctuationSuggestions(puncuationsList);
+        final ArrayList<SuggestedWordInfo> punctuationList =
+                new ArrayList<>(punctuationSpecs.length);
+        for (String spec : punctuationSpecs) {
+            punctuationList.add(newHardCodedWordInfo(spec));
+        }
+        return new PunctuationSuggestions(punctuationList);
     }
 
     /**
      * {@inheritDoc}
-     * Note that {@link super#getWord(int)} returns a punctuation key specification text.
+     * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text.
      * The suggested punctuation should be gotten by parsing the key specification.
      */
     @Override
@@ -70,7 +79,7 @@
 
     /**
      * {@inheritDoc}
-     * Note that {@link super#getWord(int)} returns a punctuation key specification text.
+     * Note that {@link SuggestedWords#getWord(int)} returns a punctuation key specification text.
      * The displayed text should be gotten by parsing the key specification.
      */
     @Override
@@ -82,7 +91,7 @@
     /**
      * {@inheritDoc}
      * Note that {@link #getWord(int)} returns a suggested punctuation. We should create a
-     * {@link SuggestedWordInfo} object that represents a hard coded word.
+     * {@link SuggestedWords.SuggestedWordInfo} object that represents a hard coded word.
      */
     @Override
     public SuggestedWordInfo getInfo(final int index) {
@@ -105,7 +114,8 @@
     }
 
     private static SuggestedWordInfo newHardCodedWordInfo(final String keySpec) {
-        return new SuggestedWordInfo(keySpec, SuggestedWordInfo.MAX_SCORE,
+        return new SuggestedWordInfo(keySpec, "" /* prevWordsContext */,
+                SuggestedWordInfo.MAX_SCORE,
                 SuggestedWordInfo.KIND_HARDCODED,
                 Dictionary.DICTIONARY_HARDCODED,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
index 5d4fc58..7b1a53a 100644
--- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
@@ -16,8 +16,8 @@
 
 package com.android.inputmethod.latin;
 
-import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 
 import java.util.ArrayList;
@@ -40,7 +40,7 @@
 
     public ReadOnlyBinaryDictionary(final String filename, final long offset, final long length,
             final boolean useFullEditDistance, final Locale locale, final String dictType) {
-        super(dictType);
+        super(dictType, locale);
         mBinaryDictionary = new BinaryDictionary(filename, offset, length, useFullEditDistance,
                 locale, dictType, false /* isUpdatable */);
     }
@@ -50,14 +50,16 @@
     }
 
     @Override
-    public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+    public ArrayList<SuggestedWordInfo> getSuggestions(final ComposedData composedData,
+            final NgramContext ngramContext, final long proximityInfoHandle,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
-            final int sessionId, final float[] inOutLanguageWeight) {
+            final int sessionId, final float weightForLocale,
+            final float[] inOutWeightOfLangModelVsSpatialModel) {
         if (mLock.readLock().tryLock()) {
             try {
-                return mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
-                        settingsValuesForSuggestion, sessionId, inOutLanguageWeight);
+                return mBinaryDictionary.getSuggestions(composedData, ngramContext,
+                        proximityInfoHandle, settingsValuesForSuggestion, sessionId,
+                        weightForLocale, inOutWeightOfLangModelVsSpatialModel);
             } finally {
                 mLock.readLock().unlock();
             }
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 744b032..08e8fe3 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -16,13 +16,14 @@
 
 package com.android.inputmethod.latin;
 
-import android.graphics.Color;
+import static com.android.inputmethod.latin.define.DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH;
+
 import android.inputmethodservice.InputMethodService;
 import android.os.Build;
+import android.os.Bundle;
 import android.text.SpannableStringBuilder;
-import android.text.Spanned;
 import android.text.TextUtils;
-import android.text.style.BackgroundColorSpan;
+import android.text.style.CharacterStyle;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.inputmethod.CompletionInfo;
@@ -33,16 +34,20 @@
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.inputmethod.compat.InputConnectionCompatUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.UnicodeSurrogate;
+import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
+import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.CapsModeUtils;
 import com.android.inputmethod.latin.utils.DebugLogUtils;
-import com.android.inputmethod.latin.utils.PrevWordsInfoUtils;
+import com.android.inputmethod.latin.utils.NgramContextUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
 import com.android.inputmethod.latin.utils.SpannableStringUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
-import java.util.Arrays;
+import javax.annotation.Nonnull;
 
 /**
  * Enrichment class for InputConnection to simplify interaction and add functionality.
@@ -52,15 +57,15 @@
  * all the time to find out what text is in the buffer, when we need it to determine caps mode
  * for example.
  */
-public final class RichInputConnection {
+public final class RichInputConnection implements PrivateCommandPerformer {
     private static final String TAG = RichInputConnection.class.getSimpleName();
     private static final boolean DBG = false;
     private static final boolean DEBUG_PREVIOUS_TEXT = false;
     private static final boolean DEBUG_BATCH_NESTING = false;
     // Provision for long words and separators between the words.
-    private static final int LOOKBACK_CHARACTER_NUM = Constants.DICTIONARY_MAX_WORD_LENGTH
-            * (Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1) /* words */
-            + Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM /* separators */;
+    private static final int LOOKBACK_CHARACTER_NUM = DICTIONARY_MAX_WORD_LENGTH
+            * (DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1) /* words */
+            + DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM /* separators */;
     private static final int INVALID_CURSOR_POSITION = -1;
 
     /**
@@ -88,26 +93,25 @@
     private final StringBuilder mComposingText = new StringBuilder();
 
     /**
-     * This variable is a temporary object used in
-     * {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation.
+     * This variable is a temporary object used in {@link #commitText(CharSequence,int)}
+     * to avoid object creation.
      */
     private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
-    /**
-     * This variable is used to track whether the last committed text had the background color or
-     * not.
-     * TODO: Omit this flag if possible.
-     */
-    private boolean mLastCommittedTextHasBackgroundColor = false;
 
     private final InputMethodService mParent;
     InputConnection mIC;
     int mNestLevel;
+
     public RichInputConnection(final InputMethodService parent) {
         mParent = parent;
         mIC = null;
         mNestLevel = 0;
     }
 
+    public boolean isConnected() {
+        return mIC != null;
+    }
+
     private void checkConsistencyForDebug() {
         final ExtractedTextRequest r = new ExtractedTextRequest();
         r.hintMaxChars = 0;
@@ -143,15 +147,14 @@
     public void beginBatchEdit() {
         if (++mNestLevel == 1) {
             mIC = mParent.getCurrentInputConnection();
-            if (null != mIC) {
+            if (isConnected()) {
                 mIC.beginBatchEdit();
             }
         } else {
             if (DBG) {
                 throw new RuntimeException("Nest level too deep");
-            } else {
-                Log.e(TAG, "Nest level too deep : " + mNestLevel);
             }
+            Log.e(TAG, "Nest level too deep : " + mNestLevel);
         }
         if (DEBUG_BATCH_NESTING) checkBatchEdit();
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -159,7 +162,7 @@
 
     public void endBatchEdit() {
         if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
-        if (--mNestLevel == 0 && null != mIC) {
+        if (--mNestLevel == 0 && isConnected()) {
             mIC.endBatchEdit();
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -191,7 +194,7 @@
             Log.d(TAG, "Will try to retrieve text later.");
             return false;
         }
-        if (null != mIC && shouldFinishComposition) {
+        if (isConnected() && shouldFinishComposition) {
             mIC.finishComposingText();
         }
         return true;
@@ -207,8 +210,9 @@
         mIC = mParent.getCurrentInputConnection();
         // Call upon the inputconnection directly since our own method is using the cache, and
         // we want to refresh it.
-        final CharSequence textBeforeCursor = null == mIC ? null :
-                mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
+        final CharSequence textBeforeCursor = isConnected()
+                ? mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0)
+                : null;
         if (null == textBeforeCursor) {
             // For some reason the app thinks we are not connected to it. This looks like a
             // framework bug... Fall back to ground state and return false.
@@ -237,39 +241,18 @@
         // it works, but it's wrong and should be fixed.
         mCommittedTextBeforeComposingText.append(mComposingText);
         mComposingText.setLength(0);
-        // TODO: Clear this flag in setComposingRegion() and setComposingText() as well if needed.
-        mLastCommittedTextHasBackgroundColor = false;
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.finishComposingText();
         }
     }
 
     /**
-     * Synonym of {@code commitTextWithBackgroundColor(text, newCursorPosition, Color.TRANSPARENT}.
+     * Calls {@link InputConnection#commitText(CharSequence, int)}.
+     *
      * @param text The text to commit. This may include styles.
-     * See {@link InputConnection#commitText(CharSequence, int)}.
      * @param newCursorPosition The new cursor position around the text.
-     * See {@link InputConnection#commitText(CharSequence, int)}.
      */
     public void commitText(final CharSequence text, final int newCursorPosition) {
-        commitTextWithBackgroundColor(text, newCursorPosition, Color.TRANSPARENT, text.length());
-    }
-
-    /**
-     * Calls {@link InputConnection#commitText(CharSequence, int)} with the given background color.
-     * @param text The text to commit. This may include styles.
-     * See {@link InputConnection#commitText(CharSequence, int)}.
-     * @param newCursorPosition The new cursor position around the text.
-     * See {@link InputConnection#commitText(CharSequence, int)}.
-     * @param color The background color to be attached. Set {@link Color#TRANSPARENT} to disable
-     * the background color. Note that this method specifies {@link BackgroundColorSpan} with
-     * {@link Spanned#SPAN_COMPOSING} flag, meaning that the background color persists until
-     * {@link #finishComposingText()} is called.
-     * @param coloredTextLength the length of text, in Java chars, which should be rendered with
-     * the given background color.
-     */
-    public void commitTextWithBackgroundColor(final CharSequence text, final int newCursorPosition,
-            final int color, final int coloredTextLength) {
         if (DEBUG_BATCH_NESTING) checkBatchEdit();
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
         mCommittedTextBeforeComposingText.append(text);
@@ -279,46 +262,34 @@
         mExpectedSelStart += text.length() - mComposingText.length();
         mExpectedSelEnd = mExpectedSelStart;
         mComposingText.setLength(0);
-        mLastCommittedTextHasBackgroundColor = false;
-        if (null != mIC) {
-            if (color == Color.TRANSPARENT) {
-                mIC.commitText(text, newCursorPosition);
-            } else {
-                mTempObjectForCommitText.clear();
-                mTempObjectForCommitText.append(text);
-                final BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(color);
-                final int spanLength = Math.min(coloredTextLength, text.length());
-                mTempObjectForCommitText.setSpan(backgroundColorSpan, 0, spanLength,
-                        Spanned.SPAN_COMPOSING | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-                mIC.commitText(mTempObjectForCommitText, newCursorPosition);
-                mLastCommittedTextHasBackgroundColor = true;
+        if (isConnected()) {
+            mTempObjectForCommitText.clear();
+            mTempObjectForCommitText.append(text);
+            final CharacterStyle[] spans = mTempObjectForCommitText.getSpans(
+                    0, text.length(), CharacterStyle.class);
+            for (final CharacterStyle span : spans) {
+                final int spanStart = mTempObjectForCommitText.getSpanStart(span);
+                final int spanEnd = mTempObjectForCommitText.getSpanEnd(span);
+                final int spanFlags = mTempObjectForCommitText.getSpanFlags(span);
+                // We have to adjust the end of the span to include an additional character.
+                // This is to avoid splitting a unicode surrogate pair.
+                // See com.android.inputmethod.latin.common.Constants.UnicodeSurrogate
+                // See https://b.corp.google.com/issues/19255233
+                if (0 < spanEnd && spanEnd < mTempObjectForCommitText.length()) {
+                    final char spanEndChar = mTempObjectForCommitText.charAt(spanEnd - 1);
+                    final char nextChar = mTempObjectForCommitText.charAt(spanEnd);
+                    if (UnicodeSurrogate.isLowSurrogate(spanEndChar)
+                            && UnicodeSurrogate.isHighSurrogate(nextChar)) {
+                        mTempObjectForCommitText.setSpan(span, spanStart, spanEnd + 1, spanFlags);
+                    }
+                }
             }
+            mIC.commitText(mTempObjectForCommitText, newCursorPosition);
         }
     }
 
-    /**
-     * Removes the background color from the highlighted text if necessary. Should be called while
-     * there is no on-going composing text.
-     *
-     * <p>CAVEAT: This method internally calls {@link InputConnection#finishComposingText()}.
-     * Be careful of any unexpected side effects.</p>
-     */
-    public void removeBackgroundColorFromHighlightedTextIfNecessary() {
-        // TODO: We haven't yet full tested if we really need to check this flag or not. Omit this
-        // flag if everything works fine without this condition.
-        if (!mLastCommittedTextHasBackgroundColor) {
-            return;
-        }
-        if (mComposingText.length() > 0) {
-            Log.e(TAG, "clearSpansWithComposingFlags should be called when composing text is " +
-                    "empty. mComposingText=" + mComposingText);
-            return;
-        }
-        finishComposingText();
-    }
-
     public CharSequence getSelectedText(final int flags) {
-        return (null == mIC) ? null : mIC.getSelectedText(flags);
+        return isConnected() ?  mIC.getSelectedText(flags) : null;
     }
 
     public boolean canDeleteCharacters() {
@@ -343,16 +314,17 @@
     public int getCursorCapsMode(final int inputType,
             final SpacingAndPunctuations spacingAndPunctuations, final boolean hasSpaceBefore) {
         mIC = mParent.getCurrentInputConnection();
-        if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
+        if (!isConnected()) {
+            return Constants.TextUtils.CAP_MODE_OFF;
+        }
         if (!TextUtils.isEmpty(mComposingText)) {
             if (hasSpaceBefore) {
                 // If we have some composing text and a space before, then we should have
                 // MODE_CHARACTERS and MODE_WORDS on.
                 return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & inputType;
-            } else {
-                // We have some composing text - we should be in MODE_CHARACTERS only.
-                return TextUtils.CAP_MODE_CHARACTERS & inputType;
             }
+            // We have some composing text - we should be in MODE_CHARACTERS only.
+            return TextUtils.CAP_MODE_CHARACTERS & inputType;
         }
         // TODO: this will generally work, but there may be cases where the buffer contains SOME
         // information but not enough to determine the caps mode accurately. This may happen after
@@ -367,7 +339,9 @@
         }
         // This never calls InputConnection#getCapsMode - in fact, it's a static method that
         // never blocks or initiates IPC.
-        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType,
+        // TODO: don't call #toString() here. Instead, all accesses to
+        // mCommittedTextBeforeComposingText should be done on the main thread.
+        return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText.toString(), inputType,
                 spacingAndPunctuations, hasSpaceBefore);
     }
 
@@ -402,12 +376,12 @@
             return s;
         }
         mIC = mParent.getCurrentInputConnection();
-        return (null == mIC) ? null : mIC.getTextBeforeCursor(n, flags);
+        return isConnected() ? mIC.getTextBeforeCursor(n, flags) : null;
     }
 
     public CharSequence getTextAfterCursor(final int n, final int flags) {
         mIC = mParent.getCurrentInputConnection();
-        return (null == mIC) ? null : mIC.getTextAfterCursor(n, flags);
+        return isConnected() ? mIC.getTextAfterCursor(n, flags) : null;
     }
 
     public void deleteSurroundingText(final int beforeLength, final int afterLength) {
@@ -434,7 +408,7 @@
             mExpectedSelEnd -= mExpectedSelStart;
             mExpectedSelStart = 0;
         }
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.deleteSurroundingText(beforeLength, afterLength);
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -442,7 +416,7 @@
 
     public void performEditorAction(final int actionId) {
         mIC = mParent.getCurrentInputConnection();
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.performEditorAction(actionId);
         }
     }
@@ -494,7 +468,7 @@
                 break;
             }
         }
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.sendKeyEvent(keyEvent);
         }
     }
@@ -517,7 +491,7 @@
             mCommittedTextBeforeComposingText.append(
                     textBeforeCursor.subSequence(0, indexOfStartOfComposingText));
         }
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.setComposingRegion(start, end);
         }
     }
@@ -531,7 +505,7 @@
         mComposingText.append(text);
         // TODO: support values of newCursorPosition != 1. At this time, this is never called with
         // newCursorPosition != 1.
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.setComposingText(text, newCursorPosition);
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -556,7 +530,7 @@
         }
         mExpectedSelStart = start;
         mExpectedSelEnd = end;
-        if (null != mIC) {
+        if (isConnected()) {
             final boolean isIcValid = mIC.setSelection(start, end);
             if (!isIcValid) {
                 return false;
@@ -570,7 +544,7 @@
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
         // This has no effect on the text field and does not change its content. It only makes
         // TextView flash the text for a second based on indices contained in the argument.
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.commitCorrection(correctionInfo);
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
@@ -586,18 +560,19 @@
         mExpectedSelStart += text.length() - mComposingText.length();
         mExpectedSelEnd = mExpectedSelStart;
         mComposingText.setLength(0);
-        if (null != mIC) {
+        if (isConnected()) {
             mIC.commitCompletion(completionInfo);
         }
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
     }
 
     @SuppressWarnings("unused")
-    public PrevWordsInfo getPrevWordsInfoFromNthPreviousWord(
+    @Nonnull
+    public NgramContext getNgramContextFromNthPreviousWord(
             final SpacingAndPunctuations spacingAndPunctuations, final int n) {
         mIC = mParent.getCurrentInputConnection();
-        if (null == mIC) {
-            return PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
+        if (!isConnected()) {
+            return NgramContext.EMPTY_PREV_WORDS_INFO;
         }
         final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
         if (DEBUG_PREVIOUS_TEXT && null != prev) {
@@ -618,14 +593,10 @@
                 }
             }
         }
-        return PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
+        return NgramContextUtils.getNgramContextFromNthPreviousWord(
                 prev, spacingAndPunctuations, n);
     }
 
-    private static boolean isSeparator(final int code, final int[] sortedSeparators) {
-        return Arrays.binarySearch(sortedSeparators, code) >= 0;
-    }
-
     private static boolean isPartOfCompositionForScript(final int codePoint,
             final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) {
         // We always consider word connectors part of compositions.
@@ -645,7 +616,7 @@
     public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations,
             final int scriptId) {
         mIC = mParent.getCurrentInputConnection();
-        if (mIC == null) {
+        if (!isConnected()) {
             return null;
         }
         final CharSequence before = mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
@@ -740,17 +711,19 @@
         return TextUtils.equals(text, beforeText);
     }
 
-    public boolean revertDoubleSpacePeriod() {
+    public boolean revertDoubleSpacePeriod(final SpacingAndPunctuations spacingAndPunctuations) {
         if (DEBUG_BATCH_NESTING) checkBatchEdit();
         // Here we test whether we indeed have a period and a space before us. This should not
         // be needed, but it's there just in case something went wrong.
         final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
-        if (!TextUtils.equals(Constants.STRING_PERIOD_AND_SPACE, textBeforeCursor)) {
+        if (!TextUtils.equals(spacingAndPunctuations.mSentenceSeparatorAndSpace,
+                textBeforeCursor)) {
             // Theoretically we should not be coming here if there isn't ". " before the
             // cursor, but the application may be changing the text while we are typing, so
             // anything goes. We should not crash.
-            Log.d(TAG, "Tried to revert double-space combo but we didn't find "
-                    + "\"" + Constants.STRING_PERIOD_AND_SPACE + "\" just before the cursor.");
+            Log.d(TAG, "Tried to revert double-space combo but we didn't find \""
+                    + spacingAndPunctuations.mSentenceSeparatorAndSpace
+                    + "\" just before the cursor.");
             return false;
         }
         // Double-space results in ". ". A backspace to cancel this should result in a single
@@ -847,17 +820,32 @@
 
     /**
      * Try to get the text from the editor to expose lies the framework may have been
-     * telling us. Concretely, when the device rotates, the frameworks tells us about where the
-     * cursor used to be initially in the editor at the time it first received the focus; this
+     * telling us. Concretely, when the device rotates and when the keyboard reopens in the same
+     * text field after having been closed with the back key, the frameworks tells us about where
+     * the cursor used to be initially in the editor at the time it first received the focus; this
      * may be completely different from the place it is upon rotation. Since we don't have any
      * means to get the real value, try at least to ask the text view for some characters and
      * detect the most damaging cases: when the cursor position is declared to be much smaller
      * than it really is.
      */
     public void tryFixLyingCursorPosition() {
+        mIC = mParent.getCurrentInputConnection();
         final CharSequence textBeforeCursor = getTextBeforeCursor(
                 Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
-        if (null == textBeforeCursor) {
+        final CharSequence selectedText = isConnected() ? mIC.getSelectedText(0 /* flags */) : null;
+        if (null == textBeforeCursor ||
+                (!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) {
+            // If textBeforeCursor is null, we have no idea what kind of text field we have or if
+            // thinking about the "cursor position" actually makes any sense. In this case we
+            // remember a meaningless cursor position. Contrast this with an empty string, which is
+            // valid and should mean the cursor is at the start of the text.
+            // Also, if we expect we don't have a selection but we DO have non-empty selected text,
+            // then the framework lied to us about the cursor position. In this case, we should just
+            // revert to the most basic behavior possible for the next action (backspace in
+            // particular comes to mind), so we remember a meaningless cursor position which should
+            // result in degraded behavior from the next input.
+            // Interestingly, in either case, chances are any action the user takes next will result
+            // in a call to onUpdateSelection, which should set things right.
             mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION;
         } else {
             final int textLength = textBeforeCursor.length();
@@ -880,6 +868,15 @@
         }
     }
 
+    @Override
+    public boolean performPrivateCommand(final String action, final Bundle data) {
+        mIC = mParent.getCurrentInputConnection();
+        if (!isConnected()) {
+            return false;
+        }
+        return mIC.performPrivateCommand(action, data);
+    }
+
     public int getExpectedSelectionStart() {
         return mExpectedSelStart;
     }
@@ -920,8 +917,6 @@
         }
     }
 
-    private boolean mCursorAnchorInfoMonitorEnabled = false;
-
     /**
      * Requests the editor to call back {@link InputMethodManager#updateCursorAnchorInfo}.
      * @param enableMonitor {@code true} to request the editor to call back the method whenever the
@@ -936,22 +931,10 @@
     public boolean requestCursorUpdates(final boolean enableMonitor,
             final boolean requestImmediateCallback) {
         mIC = mParent.getCurrentInputConnection();
-        final boolean scheduled;
-        if (null != mIC) {
-            scheduled = InputConnectionCompatUtils.requestCursorUpdates(mIC, enableMonitor,
-                    requestImmediateCallback);
-        } else {
-            scheduled = false;
+        if (!isConnected()) {
+            return false;
         }
-        mCursorAnchorInfoMonitorEnabled = (scheduled && enableMonitor);
-        return scheduled;
-    }
-
-    /**
-     * @return {@code true} if the application reported that the monitor mode of
-     * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is currently enabled.
-     */
-    public boolean isCursorAnchorInfoMonitorEnabled() {
-        return mCursorAnchorInfoMonitorEnabled;
+        return InputConnectionCompatUtils.requestCursorUpdates(
+                mIC, enableMonitor, requestImmediateCallback);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 7cf4eff..ef946c8 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -16,10 +16,12 @@
 
 package com.android.inputmethod.latin;
 
-import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.inputmethodservice.InputMethodService;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.IBinder;
 import android.preference.PreferenceManager;
@@ -28,20 +30,31 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * Enrichment class for InputMethodManager to simplify interaction and add functionality.
  */
-public final class RichInputMethodManager {
+// non final for easy mocking.
+public class RichInputMethodManager {
     private static final String TAG = RichInputMethodManager.class.getSimpleName();
+    private static final boolean DEBUG = false;
 
     private RichInputMethodManager() {
         // This utility class is not publicly instantiable.
@@ -49,12 +62,12 @@
 
     private static final RichInputMethodManager sInstance = new RichInputMethodManager();
 
+    private Context mContext;
     private InputMethodManagerCompatWrapper mImmWrapper;
     private InputMethodInfoCache mInputMethodInfoCache;
-    final HashMap<InputMethodInfo, List<InputMethodSubtype>>
-            mSubtypeListCacheWithImplicitlySelectedSubtypes = new HashMap<>();
-    final HashMap<InputMethodInfo, List<InputMethodSubtype>>
-            mSubtypeListCacheWithoutImplicitlySelectedSubtypes = new HashMap<>();
+    private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
+    private InputMethodInfo mShortcutInputMethodInfo;
+    private InputMethodSubtype mShortcutSubtype;
 
     private static final int INDEX_NOT_FOUND = -1;
 
@@ -82,20 +95,24 @@
             return;
         }
         mImmWrapper = new InputMethodManagerCompatWrapper(context);
+        mContext = context;
         mInputMethodInfoCache = new InputMethodInfoCache(
                 mImmWrapper.mImm, context.getPackageName());
 
         // Initialize additional subtypes.
         SubtypeLocaleUtils.init(context);
-        final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes(context);
-        setAdditionalInputMethodSubtypes(additionalSubtypes);
+        final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes();
+        mImmWrapper.mImm.setAdditionalInputMethodSubtypes(
+                getInputMethodIdOfThisIme(), additionalSubtypes);
+
+        // Initialize the current input method subtype and the shortcut IME.
+        refreshSubtypeCaches();
     }
 
-    public InputMethodSubtype[] getAdditionalSubtypes(final Context context) {
-        SubtypeLocaleUtils.init(context);
-        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+    public InputMethodSubtype[] getAdditionalSubtypes() {
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
         final String prefAdditionalSubtypes = Settings.readPrefAdditionalSubtypes(
-                prefs, context.getResources());
+                prefs, mContext.getResources());
         return AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefAdditionalSubtypes);
     }
 
@@ -212,33 +229,57 @@
         private final InputMethodManager mImm;
         private final String mImePackageName;
 
-        private InputMethodInfo mCachedValue;
+        private InputMethodInfo mCachedThisImeInfo;
+        private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
+                mCachedSubtypeListWithImplicitlySelected;
+        private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
+                mCachedSubtypeListOnlyExplicitlySelected;
 
         public InputMethodInfoCache(final InputMethodManager imm, final String imePackageName) {
             mImm = imm;
             mImePackageName = imePackageName;
+            mCachedSubtypeListWithImplicitlySelected = new HashMap<>();
+            mCachedSubtypeListOnlyExplicitlySelected = new HashMap<>();
         }
 
-        public synchronized InputMethodInfo get() {
-            if (mCachedValue != null) {
-                return mCachedValue;
+        public synchronized InputMethodInfo getInputMethodOfThisIme() {
+            if (mCachedThisImeInfo != null) {
+                return mCachedThisImeInfo;
             }
             for (final InputMethodInfo imi : mImm.getInputMethodList()) {
                 if (imi.getPackageName().equals(mImePackageName)) {
-                    mCachedValue = imi;
+                    mCachedThisImeInfo = imi;
                     return imi;
                 }
             }
             throw new RuntimeException("Input method id for " + mImePackageName + " not found.");
         }
 
+        public synchronized List<InputMethodSubtype> getEnabledInputMethodSubtypeList(
+                final InputMethodInfo imi, final boolean allowsImplicitlySelectedSubtypes) {
+            final HashMap<InputMethodInfo, List<InputMethodSubtype>> cache =
+                    allowsImplicitlySelectedSubtypes
+                    ? mCachedSubtypeListWithImplicitlySelected
+                    : mCachedSubtypeListOnlyExplicitlySelected;
+            final List<InputMethodSubtype> cachedList = cache.get(imi);
+            if (cachedList != null) {
+                return cachedList;
+            }
+            final List<InputMethodSubtype> result = mImm.getEnabledInputMethodSubtypeList(
+                    imi, allowsImplicitlySelectedSubtypes);
+            cache.put(imi, result);
+            return result;
+        }
+
         public synchronized void clear() {
-            mCachedValue = null;
+            mCachedThisImeInfo = null;
+            mCachedSubtypeListWithImplicitlySelected.clear();
+            mCachedSubtypeListOnlyExplicitlySelected.clear();
         }
     }
 
     public InputMethodInfo getInputMethodInfoOfThisIme() {
-        return mInputMethodInfoCache.get();
+        return mInputMethodInfoCache.getInputMethodOfThisIme();
     }
 
     public String getInputMethodIdOfThisIme() {
@@ -246,24 +287,20 @@
     }
 
     public boolean checkIfSubtypeBelongsToThisImeAndEnabled(final InputMethodSubtype subtype) {
-        return checkIfSubtypeBelongsToImeAndEnabled(getInputMethodInfoOfThisIme(), subtype);
+        return checkIfSubtypeBelongsToList(subtype,
+                getEnabledInputMethodSubtypeList(
+                        getInputMethodInfoOfThisIme(),
+                        true /* allowsImplicitlySelectedSubtypes */));
     }
 
     public boolean checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(
             final InputMethodSubtype subtype) {
         final boolean subtypeEnabled = checkIfSubtypeBelongsToThisImeAndEnabled(subtype);
-        final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList(
-                subtype, getMyEnabledInputMethodSubtypeList(
-                        false /* allowsImplicitlySelectedSubtypes */));
+        final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList(subtype,
+                getMyEnabledInputMethodSubtypeList(false /* allowsImplicitlySelectedSubtypes */));
         return subtypeEnabled && !subtypeExplicitlyEnabled;
     }
 
-    public boolean checkIfSubtypeBelongsToImeAndEnabled(final InputMethodInfo imi,
-            final InputMethodSubtype subtype) {
-        return checkIfSubtypeBelongsToList(subtype, getEnabledInputMethodSubtypeList(imi,
-                true /* allowsImplicitlySelectedSubtypes */));
-    }
-
     private static boolean checkIfSubtypeBelongsToList(final InputMethodSubtype subtype,
             final List<InputMethodSubtype> subtypes) {
         return getSubtypeIndexInList(subtype, subtypes) != INDEX_NOT_FOUND;
@@ -281,26 +318,40 @@
         return INDEX_NOT_FOUND;
     }
 
-    public boolean checkIfSubtypeBelongsToThisIme(final InputMethodSubtype subtype) {
-        return getSubtypeIndexInIme(subtype, getInputMethodInfoOfThisIme()) != INDEX_NOT_FOUND;
-    }
-
-    private static int getSubtypeIndexInIme(final InputMethodSubtype subtype,
-            final InputMethodInfo imi) {
-        final int count = imi.getSubtypeCount();
-        for (int index = 0; index < count; index++) {
-            final InputMethodSubtype ims = imi.getSubtypeAt(index);
-            if (ims.equals(subtype)) {
-                return index;
-            }
+    public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
+        updateCurrentSubtype(newSubtype);
+        updateShortcutIme();
+        if (DEBUG) {
+            Log.w(TAG, "onSubtypeChanged: " + mCurrentRichInputMethodSubtype.getNameForLogging());
         }
-        return INDEX_NOT_FOUND;
     }
 
-    public InputMethodSubtype getCurrentInputMethodSubtype(
-            final InputMethodSubtype defaultSubtype) {
-        final InputMethodSubtype currentSubtype = mImmWrapper.mImm.getCurrentInputMethodSubtype();
-        return (currentSubtype != null) ? currentSubtype : defaultSubtype;
+    private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
+
+    @UsedForTesting
+    static void forceSubtype(@Nonnull final InputMethodSubtype subtype) {
+        sForcedSubtypeForTesting = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
+    }
+
+    @Nonnull
+    public Locale getCurrentSubtypeLocale() {
+        if (null != sForcedSubtypeForTesting) {
+            return sForcedSubtypeForTesting.getLocale();
+        }
+        return getCurrentSubtype().getLocale();
+    }
+
+    @Nonnull
+    public RichInputMethodSubtype getCurrentSubtype() {
+        if (null != sForcedSubtypeForTesting) {
+            return sForcedSubtypeForTesting;
+        }
+        return mCurrentRichInputMethodSubtype;
+    }
+
+
+    public String getCombiningRulesExtraValueOfCurrentSubtype() {
+        return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
     }
 
     public boolean hasMultipleEnabledIMEsOrSubtypes(final boolean shouldIncludeAuxiliarySubtypes) {
@@ -343,7 +394,6 @@
             // subtypes should be counted as well.
             if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
                 ++filteredImisCount;
-                continue;
             }
         }
 
@@ -388,27 +438,19 @@
                 getInputMethodIdOfThisIme(), subtypes);
         // Clear the cache so that we go read the {@link InputMethodInfo} of this IME and list of
         // subtypes again next time.
-        clearSubtypeCaches();
+        refreshSubtypeCaches();
     }
 
     private List<InputMethodSubtype> getEnabledInputMethodSubtypeList(final InputMethodInfo imi,
             final boolean allowsImplicitlySelectedSubtypes) {
-        final HashMap<InputMethodInfo, List<InputMethodSubtype>> cache =
-                allowsImplicitlySelectedSubtypes
-                ? mSubtypeListCacheWithImplicitlySelectedSubtypes
-                : mSubtypeListCacheWithoutImplicitlySelectedSubtypes;
-        final List<InputMethodSubtype> cachedList = cache.get(imi);
-        if (null != cachedList) return cachedList;
-        final List<InputMethodSubtype> result = mImmWrapper.mImm.getEnabledInputMethodSubtypeList(
+        return mInputMethodInfoCache.getEnabledInputMethodSubtypeList(
                 imi, allowsImplicitlySelectedSubtypes);
-        cache.put(imi, result);
-        return result;
     }
 
-    public void clearSubtypeCaches() {
-        mSubtypeListCacheWithImplicitlySelectedSubtypes.clear();
-        mSubtypeListCacheWithoutImplicitlySelectedSubtypes.clear();
+    public void refreshSubtypeCaches() {
         mInputMethodInfoCache.clear();
+        updateCurrentSubtype(mImmWrapper.mImm.getCurrentInputMethodSubtype());
+        updateShortcutIme();
     }
 
     public boolean shouldOfferSwitchingToNextInputMethod(final IBinder binder,
@@ -421,4 +463,109 @@
         }
         return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
     }
+
+    public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
+        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
+        final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
+        final InputMethodManager inputMethodManager = getInputMethodManager();
+        final List<InputMethodInfo> enabledInputMethodInfoList =
+                inputMethodManager.getEnabledInputMethodList();
+        for (final InputMethodInfo info : enabledInputMethodInfoList) {
+            final List<InputMethodSubtype> enabledSubtypes =
+                    inputMethodManager.getEnabledInputMethodSubtypeList(
+                            info, true /* allowsImplicitlySelectedSubtypes */);
+            if (enabledSubtypes.isEmpty()) {
+                // An IME with no subtypes is found.
+                return false;
+            }
+            enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
+        }
+        for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
+            if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
+                    && !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void updateCurrentSubtype(@Nullable final InputMethodSubtype subtype) {
+        mCurrentRichInputMethodSubtype = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
+    }
+
+    private void updateShortcutIme() {
+        if (DEBUG) {
+            Log.d(TAG, "Update shortcut IME from : "
+                    + (mShortcutInputMethodInfo == null
+                            ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
+                    + (mShortcutSubtype == null ? "<null>" : (
+                            mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
+        }
+        final RichInputMethodSubtype richSubtype = mCurrentRichInputMethodSubtype;
+        final boolean implicitlyEnabledSubtype = checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(
+                richSubtype.getRawSubtype());
+        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
+        LanguageOnSpacebarUtils.onSubtypeChanged(
+                richSubtype, implicitlyEnabledSubtype, systemLocale);
+        LanguageOnSpacebarUtils.setEnabledSubtypes(getMyEnabledInputMethodSubtypeList(
+                true /* allowsImplicitlySelectedSubtypes */));
+
+        // TODO: Update an icon for shortcut IME
+        final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
+                getInputMethodManager().getShortcutInputMethodsAndSubtypes();
+        mShortcutInputMethodInfo = null;
+        mShortcutSubtype = null;
+        for (final InputMethodInfo imi : shortcuts.keySet()) {
+            final List<InputMethodSubtype> subtypes = shortcuts.get(imi);
+            // TODO: Returns the first found IMI for now. Should handle all shortcuts as
+            // appropriate.
+            mShortcutInputMethodInfo = imi;
+            // TODO: Pick up the first found subtype for now. Should handle all subtypes
+            // as appropriate.
+            mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null;
+            break;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "Update shortcut IME to : "
+                    + (mShortcutInputMethodInfo == null
+                            ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
+                    + (mShortcutSubtype == null ? "<null>" : (
+                            mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
+        }
+    }
+
+    public void switchToShortcutIme(final InputMethodService context) {
+        if (mShortcutInputMethodInfo == null) {
+            return;
+        }
+
+        final String imiId = mShortcutInputMethodInfo.getId();
+        switchToTargetIME(imiId, mShortcutSubtype, context);
+    }
+
+    private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype,
+            final InputMethodService context) {
+        final IBinder token = context.getWindow().getWindow().getAttributes().token;
+        if (token == null) {
+            return;
+        }
+        final InputMethodManager imm = getInputMethodManager();
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                imm.setInputMethodAndSubtype(token, imiId, subtype);
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    public boolean isShortcutImeReady() {
+        if (mShortcutInputMethodInfo == null) {
+            return false;
+        }
+        if (mShortcutSubtype == null) {
+            return true;
+        }
+        return true;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java b/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java
new file mode 100644
index 0000000..9d7849f
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodSubtype.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 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;
+
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+
+import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Enrichment class for InputMethodSubtype to enable concurrent multi-lingual input.
+ *
+ * Right now, this returns the extra value of its primary subtype.
+ */
+// non final for easy mocking.
+public class RichInputMethodSubtype {
+    private static final String TAG = RichInputMethodSubtype.class.getSimpleName();
+
+    @Nonnull
+    private final InputMethodSubtype mSubtype;
+    @Nonnull
+    private final Locale mLocale;
+
+    public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype) {
+        mSubtype = subtype;
+        mLocale = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
+    }
+
+    // Extra values are determined by the primary subtype. This is probably right, but
+    // we may have to revisit this later.
+    public String getExtraValueOf(@Nonnull final String key) {
+        return mSubtype.getExtraValueOf(key);
+    }
+
+    // The mode is also determined by the primary subtype.
+    public String getMode() {
+        return mSubtype.getMode();
+    }
+
+    public boolean isNoLanguage() {
+        return SubtypeLocaleUtils.NO_LANGUAGE.equals(mSubtype.getLocale());
+    }
+
+    public String getNameForLogging() {
+        return toString();
+    }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout  |  Middle      Full
+    // ------ ------- - --------- ----------------------
+    //  en_US qwerty  F  English   English (US)           exception
+    //  en_GB qwerty  F  English   English (UK)           exception
+    //  es_US spanish F  Español   Español (EE.UU.)       exception
+    //  fr    azerty  F  Français  Français
+    //  fr_CA qwerty  F  Français  Français (Canada)
+    //  fr_CH swiss   F  Français  Français (Suisse)
+    //  de    qwertz  F  Deutsch   Deutsch
+    //  de_CH swiss   T  Deutsch   Deutsch (Schweiz)
+    //  zz    qwerty  F  QWERTY    QWERTY
+    //  fr    qwertz  T  Français  Français
+    //  de    qwerty  T  Deutsch   Deutsch
+    //  en_US azerty  T  English   English (US)
+    //  zz    azerty  T  AZERTY    AZERTY
+    // Get the RichInputMethodSubtype's full display name in its locale.
+    @Nonnull
+    public String getFullDisplayName() {
+        if (isNoLanguage()) {
+            return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
+        }
+        return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(mSubtype.getLocale());
+    }
+
+    // Get the RichInputMethodSubtype's middle display name in its locale.
+    @Nonnull
+    public String getMiddleDisplayName() {
+        if (isNoLanguage()) {
+            return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(mSubtype);
+        }
+        return SubtypeLocaleUtils.getSubtypeLanguageDisplayName(mSubtype.getLocale());
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (!(o instanceof RichInputMethodSubtype)) {
+            return false;
+        }
+        final RichInputMethodSubtype other = (RichInputMethodSubtype)o;
+        return mSubtype.equals(other.mSubtype) && mLocale.equals(other.mLocale);
+    }
+
+    @Override
+    public int hashCode() {
+        return mSubtype.hashCode() + mLocale.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "Multi-lingual subtype: " + mSubtype + ", " + mLocale;
+    }
+
+    @Nonnull
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    public boolean isRtlSubtype() {
+        // The subtype is considered RTL if the language of the main subtype is RTL.
+        return LocaleUtils.isRtlLanguage(mLocale);
+    }
+
+    // TODO: remove this method
+    @Nonnull
+    public InputMethodSubtype getRawSubtype() { return mSubtype; }
+
+    @Nonnull
+    public String getKeyboardLayoutSetName() {
+        return SubtypeLocaleUtils.getKeyboardLayoutSetName(mSubtype);
+    }
+
+    public static RichInputMethodSubtype getRichInputMethodSubtype(
+            @Nullable final InputMethodSubtype subtype) {
+        if (subtype == null) {
+            return getNoLanguageSubtype();
+        } else {
+            return new RichInputMethodSubtype(subtype);
+        }
+    }
+
+    // Dummy no language QWERTY subtype. See {@link R.xml.method}.
+    private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
+    private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
+            "KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
+            + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
+            + "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
+            + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+    @Nonnull
+    private static final RichInputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
+            new RichInputMethodSubtype(InputMethodSubtypeCompatUtils.newInputMethodSubtype(
+                    R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
+                    SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
+                    EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
+                    false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
+                    SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE));
+    // Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
+    // Dummy Emoji subtype. See {@link R.xml.method}.
+    private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
+    private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
+            "KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
+            + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+    @Nonnull
+    private static final RichInputMethodSubtype DUMMY_EMOJI_SUBTYPE = new RichInputMethodSubtype(
+            InputMethodSubtypeCompatUtils.newInputMethodSubtype(
+                    R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
+                    SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
+                    EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
+                    false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
+                    SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE));
+    private static RichInputMethodSubtype sNoLanguageSubtype;
+    private static RichInputMethodSubtype sEmojiSubtype;
+
+    @Nonnull
+    public static RichInputMethodSubtype getNoLanguageSubtype() {
+        RichInputMethodSubtype noLanguageSubtype = sNoLanguageSubtype;
+        if (noLanguageSubtype == null) {
+            final InputMethodSubtype rawNoLanguageSubtype = RichInputMethodManager.getInstance()
+                    .findSubtypeByLocaleAndKeyboardLayoutSet(
+                            SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
+            if (rawNoLanguageSubtype != null) {
+                noLanguageSubtype = new RichInputMethodSubtype(rawNoLanguageSubtype);
+            }
+        }
+        if (noLanguageSubtype != null) {
+            sNoLanguageSubtype = noLanguageSubtype;
+            return noLanguageSubtype;
+        }
+        Log.w(TAG, "Can't find any language with QWERTY subtype");
+        Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+                + DUMMY_NO_LANGUAGE_SUBTYPE);
+        return DUMMY_NO_LANGUAGE_SUBTYPE;
+    }
+
+    @Nonnull
+    public static RichInputMethodSubtype getEmojiSubtype() {
+        RichInputMethodSubtype emojiSubtype = sEmojiSubtype;
+        if (emojiSubtype == null) {
+            final InputMethodSubtype rawEmojiSubtype = RichInputMethodManager.getInstance()
+                    .findSubtypeByLocaleAndKeyboardLayoutSet(
+                            SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
+            if (rawEmojiSubtype != null) {
+                emojiSubtype = new RichInputMethodSubtype(rawEmojiSubtype);
+            }
+        }
+        if (emojiSubtype != null) {
+            sEmojiSubtype = emojiSubtype;
+            return emojiSubtype;
+        }
+        Log.w(TAG, "Can't find emoji subtype");
+        Log.w(TAG, "No input method subtype found; returning dummy subtype: "
+                + DUMMY_EMOJI_SUBTYPE);
+        return DUMMY_EMOJI_SUBTYPE;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
deleted file mode 100644
index a725e16..0000000
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2010 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;
-
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.REQ_NETWORK_CONNECTIVITY;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.inputmethodservice.InputMethodService;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.AsyncTask;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
-import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
-import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-public final class SubtypeSwitcher {
-    private static boolean DBG = DebugFlags.DEBUG_ENABLED;
-    private static final String TAG = SubtypeSwitcher.class.getSimpleName();
-
-    private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
-
-    private /* final */ RichInputMethodManager mRichImm;
-    private /* final */ Resources mResources;
-
-    private final LanguageOnSpacebarHelper mLanguageOnSpacebarHelper =
-            new LanguageOnSpacebarHelper();
-    private InputMethodInfo mShortcutInputMethodInfo;
-    private InputMethodSubtype mShortcutSubtype;
-    private InputMethodSubtype mNoLanguageSubtype;
-    private InputMethodSubtype mEmojiSubtype;
-    private boolean mIsNetworkConnected;
-
-    private static final String KEYBOARD_MODE = "keyboard";
-    // Dummy no language QWERTY subtype. See {@link R.xml.method}.
-    private static final int SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE = 0xdde0bfd3;
-    private static final String EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE =
-            "KeyboardLayoutSet=" + SubtypeLocaleUtils.QWERTY
-            + "," + Constants.Subtype.ExtraValue.ASCII_CAPABLE
-            + "," + Constants.Subtype.ExtraValue.ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE
-            + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
-    private static final InputMethodSubtype DUMMY_NO_LANGUAGE_SUBTYPE =
-            InputMethodSubtypeCompatUtils.newInputMethodSubtype(
-                    R.string.subtype_no_language_qwerty, R.drawable.ic_ime_switcher_dark,
-                    SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
-                    EXTRA_VALUE_OF_DUMMY_NO_LANGUAGE_SUBTYPE,
-                    false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
-                    SUBTYPE_ID_OF_DUMMY_NO_LANGUAGE_SUBTYPE);
-    // Caveat: We probably should remove this when we add an Emoji subtype in {@link R.xml.method}.
-    // Dummy Emoji subtype. See {@link R.xml.method}.
-    private static final int SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE = 0xd78b2ed0;
-    private static final String EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE =
-            "KeyboardLayoutSet=" + SubtypeLocaleUtils.EMOJI
-            + "," + Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
-    private static final InputMethodSubtype DUMMY_EMOJI_SUBTYPE =
-            InputMethodSubtypeCompatUtils.newInputMethodSubtype(
-                    R.string.subtype_emoji, R.drawable.ic_ime_switcher_dark,
-                    SubtypeLocaleUtils.NO_LANGUAGE, KEYBOARD_MODE,
-                    EXTRA_VALUE_OF_DUMMY_EMOJI_SUBTYPE,
-                    false /* isAuxiliary */, false /* overridesImplicitlyEnabledSubtype */,
-                    SUBTYPE_ID_OF_DUMMY_EMOJI_SUBTYPE);
-
-    public static SubtypeSwitcher getInstance() {
-        return sInstance;
-    }
-
-    public static void init(final Context context) {
-        SubtypeLocaleUtils.init(context);
-        RichInputMethodManager.init(context);
-        sInstance.initialize(context);
-    }
-
-    private SubtypeSwitcher() {
-        // Intentional empty constructor for singleton.
-    }
-
-    private void initialize(final Context context) {
-        if (mResources != null) {
-            return;
-        }
-        mResources = context.getResources();
-        mRichImm = RichInputMethodManager.getInstance();
-        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(
-                Context.CONNECTIVITY_SERVICE);
-
-        final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
-        mIsNetworkConnected = (info != null && info.isConnected());
-
-        onSubtypeChanged(getCurrentSubtype());
-        updateParametersOnStartInputView();
-    }
-
-    /**
-     * Update parameters which are changed outside LatinIME. This parameters affect UI so that they
-     * should be updated every time onStartInputView is called.
-     */
-    public void updateParametersOnStartInputView() {
-        final List<InputMethodSubtype> enabledSubtypesOfThisIme =
-                mRichImm.getMyEnabledInputMethodSubtypeList(true);
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(enabledSubtypesOfThisIme);
-        updateShortcutIME();
-    }
-
-    private void updateShortcutIME() {
-        if (DBG) {
-            Log.d(TAG, "Update shortcut IME from : "
-                    + (mShortcutInputMethodInfo == null
-                            ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
-                    + (mShortcutSubtype == null ? "<null>" : (
-                            mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
-        }
-        // TODO: Update an icon for shortcut IME
-        final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
-                mRichImm.getInputMethodManager().getShortcutInputMethodsAndSubtypes();
-        mShortcutInputMethodInfo = null;
-        mShortcutSubtype = null;
-        for (final InputMethodInfo imi : shortcuts.keySet()) {
-            final List<InputMethodSubtype> subtypes = shortcuts.get(imi);
-            // TODO: Returns the first found IMI for now. Should handle all shortcuts as
-            // appropriate.
-            mShortcutInputMethodInfo = imi;
-            // TODO: Pick up the first found subtype for now. Should handle all subtypes
-            // as appropriate.
-            mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null;
-            break;
-        }
-        if (DBG) {
-            Log.d(TAG, "Update shortcut IME to : "
-                    + (mShortcutInputMethodInfo == null
-                            ? "<null>" : mShortcutInputMethodInfo.getId()) + ", "
-                    + (mShortcutSubtype == null ? "<null>" : (
-                            mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode())));
-        }
-    }
-
-    // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
-    public void onSubtypeChanged(final InputMethodSubtype newSubtype) {
-        if (DBG) {
-            Log.w(TAG, "onSubtypeChanged: "
-                    + SubtypeLocaleUtils.getSubtypeNameForLogging(newSubtype));
-        }
-
-        final Locale newLocale = SubtypeLocaleUtils.getSubtypeLocale(newSubtype);
-        final Locale systemLocale = mResources.getConfiguration().locale;
-        final boolean sameLocale = systemLocale.equals(newLocale);
-        final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage());
-        final boolean implicitlyEnabled =
-                mRichImm.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype);
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(
-                sameLocale || (sameLanguage && implicitlyEnabled));
-
-        updateShortcutIME();
-    }
-
-    ////////////////////////////
-    // Shortcut IME functions //
-    ////////////////////////////
-
-    public void switchToShortcutIME(final InputMethodService context) {
-        if (mShortcutInputMethodInfo == null) {
-            return;
-        }
-
-        final String imiId = mShortcutInputMethodInfo.getId();
-        switchToTargetIME(imiId, mShortcutSubtype, context);
-    }
-
-    private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype,
-            final InputMethodService context) {
-        final IBinder token = context.getWindow().getWindow().getAttributes().token;
-        if (token == null) {
-            return;
-        }
-        final InputMethodManager imm = mRichImm.getInputMethodManager();
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                imm.setInputMethodAndSubtype(token, imiId, subtype);
-                return null;
-            }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-    }
-
-    public boolean isShortcutImeEnabled() {
-        updateShortcutIME();
-        if (mShortcutInputMethodInfo == null) {
-            return false;
-        }
-        if (mShortcutSubtype == null) {
-            return true;
-        }
-        return mRichImm.checkIfSubtypeBelongsToImeAndEnabled(
-                mShortcutInputMethodInfo, mShortcutSubtype);
-    }
-
-    public boolean isShortcutImeReady() {
-        updateShortcutIME();
-        if (mShortcutInputMethodInfo == null) {
-            return false;
-        }
-        if (mShortcutSubtype == null) {
-            return true;
-        }
-        if (mShortcutSubtype.containsExtraValueKey(REQ_NETWORK_CONNECTIVITY)) {
-            return mIsNetworkConnected;
-        }
-        return true;
-    }
-
-    public void onNetworkStateChanged(final Intent intent) {
-        final boolean noConnection = intent.getBooleanExtra(
-                ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-        mIsNetworkConnected = !noConnection;
-
-        KeyboardSwitcher.getInstance().onNetworkStateChanged();
-    }
-
-    //////////////////////////////////
-    // Subtype Switching functions //
-    //////////////////////////////////
-
-    public int getLanguageOnSpacebarFormatType(final InputMethodSubtype subtype) {
-        return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
-    }
-
-    public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
-        final Locale systemLocale = mResources.getConfiguration().locale;
-        final Set<InputMethodSubtype> enabledSubtypesOfEnabledImes = new HashSet<>();
-        final InputMethodManager inputMethodManager = mRichImm.getInputMethodManager();
-        final List<InputMethodInfo> enabledInputMethodInfoList =
-                inputMethodManager.getEnabledInputMethodList();
-        for (final InputMethodInfo info : enabledInputMethodInfoList) {
-            final List<InputMethodSubtype> enabledSubtypes =
-                    inputMethodManager.getEnabledInputMethodSubtypeList(
-                            info, true /* allowsImplicitlySelectedSubtypes */);
-            if (enabledSubtypes.isEmpty()) {
-                // An IME with no subtypes is found.
-                return false;
-            }
-            enabledSubtypesOfEnabledImes.addAll(enabledSubtypes);
-        }
-        for (final InputMethodSubtype subtype : enabledSubtypesOfEnabledImes) {
-            if (!subtype.isAuxiliary() && !subtype.getLocale().isEmpty()
-                    && !systemLocale.equals(SubtypeLocaleUtils.getSubtypeLocale(subtype))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static InputMethodSubtype sForcedSubtypeForTesting = null;
-    @UsedForTesting
-    void forceSubtype(final InputMethodSubtype subtype) {
-        sForcedSubtypeForTesting = subtype;
-    }
-
-    public Locale getCurrentSubtypeLocale() {
-        if (null != sForcedSubtypeForTesting) {
-            return LocaleUtils.constructLocaleFromString(sForcedSubtypeForTesting.getLocale());
-        }
-        return SubtypeLocaleUtils.getSubtypeLocale(getCurrentSubtype());
-    }
-
-    public InputMethodSubtype getCurrentSubtype() {
-        if (null != sForcedSubtypeForTesting) {
-            return sForcedSubtypeForTesting;
-        }
-        return mRichImm.getCurrentInputMethodSubtype(getNoLanguageSubtype());
-    }
-
-    public InputMethodSubtype getNoLanguageSubtype() {
-        if (mNoLanguageSubtype == null) {
-            mNoLanguageSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                    SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
-        }
-        if (mNoLanguageSubtype != null) {
-            return mNoLanguageSubtype;
-        }
-        Log.w(TAG, "Can't find any language with QWERTY subtype");
-        Log.w(TAG, "No input method subtype found; returning dummy subtype: "
-                + DUMMY_NO_LANGUAGE_SUBTYPE);
-        return DUMMY_NO_LANGUAGE_SUBTYPE;
-    }
-
-    public InputMethodSubtype getEmojiSubtype() {
-        if (mEmojiSubtype == null) {
-            mEmojiSubtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                    SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.EMOJI);
-        }
-        if (mEmojiSubtype != null) {
-            return mEmojiSubtype;
-        }
-        Log.w(TAG, "Can't find emoji subtype");
-        Log.w(TAG, "No input method subtype found; returning dummy subtype: "
-                + DUMMY_EMOJI_SUBTYPE);
-        return DUMMY_EMOJI_SUBTYPE;
-    }
-
-    public String getCombiningRulesExtraValueOfCurrentSubtype() {
-        return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype());
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index b03818c..7ccefd2 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -18,18 +18,25 @@
 
 import android.text.TextUtils;
 
-import com.android.inputmethod.keyboard.ProximityInfo;
+import static com.android.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION;
+import static com.android.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION;
+
+import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.SuggestionResults;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+
 /**
  * This class loads a dictionary and provides a list of suggestions for a given sequence of
  * characters. This includes corrections and completions.
@@ -49,34 +56,55 @@
     private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
     private final DictionaryFacilitator mDictionaryFacilitator;
 
+    private static final int MAXIMUM_AUTO_CORRECT_LENGTH_FOR_GERMAN = 12;
+    private static final HashMap<String, Integer> sLanguageToMaximumAutoCorrectionWithSpaceLength =
+            new HashMap<>();
+    static {
+        // TODO: should we add Finnish here?
+        // TODO: This should not be hardcoded here but be written in the dictionary header
+        sLanguageToMaximumAutoCorrectionWithSpaceLength.put(Locale.GERMAN.getLanguage(),
+                MAXIMUM_AUTO_CORRECT_LENGTH_FOR_GERMAN);
+    }
+
     private float mAutoCorrectionThreshold;
+    private float mPlausibilityThreshold;
 
     public Suggest(final DictionaryFacilitator dictionaryFacilitator) {
         mDictionaryFacilitator = dictionaryFacilitator;
     }
 
-    public Locale getLocale() {
-        return mDictionaryFacilitator.getLocale();
-    }
-
+    /**
+     * Set the normalized-score threshold for a suggestion to be considered strong enough that we
+     * will auto-correct to this.
+     * @param threshold the threshold
+     */
     public void setAutoCorrectionThreshold(final float threshold) {
         mAutoCorrectionThreshold = threshold;
     }
 
+    /**
+     * Set the normalized-score threshold for what we consider a "plausible" suggestion, in
+     * the same dimension as the auto-correction threshold.
+     * @param threshold the threshold
+     */
+    public void setPlausibilityThreshold(final float threshold) {
+        mPlausibilityThreshold = threshold;
+    }
+
     public interface OnGetSuggestedWordsCallback {
         public void onGetSuggestedWords(final SuggestedWords suggestedWords);
     }
 
     public void getSuggestedWords(final WordComposer wordComposer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+            final NgramContext ngramContext, final Keyboard keyboard,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         if (wordComposer.isBatchMode()) {
-            getSuggestedWordsForBatchInput(wordComposer, prevWordsInfo, proximityInfo,
+            getSuggestedWordsForBatchInput(wordComposer, ngramContext, keyboard,
                     settingsValuesForSuggestion, inputStyle, sequenceNumber, callback);
         } else {
-            getSuggestedWordsForNonBatchInput(wordComposer, prevWordsInfo, proximityInfo,
+            getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, keyboard,
                     settingsValuesForSuggestion, inputStyle, isCorrectionEnabled,
                     sequenceNumber, callback);
         }
@@ -84,7 +112,7 @@
 
     private static ArrayList<SuggestedWordInfo> getTransformedSuggestedWordInfoList(
             final WordComposer wordComposer, final SuggestionResults results,
-            final int trailingSingleQuotesCount) {
+            final int trailingSingleQuotesCount, final Locale defaultLocale) {
         final boolean shouldMakeSuggestionsAllUpperCase = wordComposer.isAllUpperCase()
                 && !wordComposer.isResumed();
         final boolean isOnlyFirstCharCapitalized =
@@ -96,16 +124,19 @@
                 || 0 != trailingSingleQuotesCount) {
             for (int i = 0; i < suggestionsCount; ++i) {
                 final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+                final Locale wordLocale = wordInfo.mSourceDict.mLocale;
                 final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
-                        wordInfo, results.mLocale, shouldMakeSuggestionsAllUpperCase,
-                        isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+                        wordInfo, null == wordLocale ? defaultLocale : wordLocale,
+                        shouldMakeSuggestionsAllUpperCase, isOnlyFirstCharCapitalized,
+                        trailingSingleQuotesCount);
                 suggestionsContainer.set(i, transformedWordInfo);
             }
         }
         return suggestionsContainer;
     }
 
-    private static String getWhitelistedWordOrNull(final ArrayList<SuggestedWordInfo> suggestions) {
+    private static SuggestedWordInfo getWhitelistedWordInfoOrNull(
+            @Nonnull final ArrayList<SuggestedWordInfo> suggestions) {
         if (suggestions.isEmpty()) {
             return null;
         }
@@ -113,75 +144,124 @@
         if (!firstSuggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
             return null;
         }
-        return firstSuggestedWordInfo.mWord;
+        return firstSuggestedWordInfo;
     }
 
     // Retrieves suggestions for non-batch input (typing, recorrection, predictions...)
     // and calls the callback function with the suggestions.
     private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+            final NgramContext ngramContext, final Keyboard keyboard,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final int inputStyleIfNotPrediction, final boolean isCorrectionEnabled,
             final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
-        final String typedWord = wordComposer.getTypedWord();
-        final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWord);
+        final String typedWordString = wordComposer.getTypedWord();
+        final int trailingSingleQuotesCount =
+                StringUtils.getTrailingSingleQuotesCount(typedWordString);
         final String consideredWord = trailingSingleQuotesCount > 0
-                ? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
-                : typedWord;
+                ? typedWordString.substring(0, typedWordString.length() - trailingSingleQuotesCount)
+                : typedWordString;
 
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
-                wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
-                SESSION_ID_TYPING);
+                wordComposer.getComposedDataSnapshot(), ngramContext, keyboard,
+                settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction);
+        final Locale locale = mDictionaryFacilitator.getLocale();
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
                 getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
-                        trailingSingleQuotesCount);
-        final boolean didRemoveTypedWord =
-                SuggestedWordInfo.removeDups(wordComposer.getTypedWord(), suggestionsContainer);
+                        trailingSingleQuotesCount, locale);
 
-        final String whitelistedWord = getWhitelistedWordOrNull(suggestionsContainer);
-        final boolean resultsArePredictions = !wordComposer.isComposingWord();
-
-        // We allow auto-correction if we have a whitelisted word, or if the word had more than
-        // one char and was not suggested.
-        final boolean allowsToBeAutoCorrected = (null != whitelistedWord)
-                || (consideredWord.length() > 1 && !didRemoveTypedWord);
-
-        final boolean hasAutoCorrection;
-        // TODO: using isCorrectionEnabled here is not very good. It's probably useless, because
-        // any attempt to do auto-correction is already shielded with a test for this flag; at the
-        // same time, it feels wrong that the SuggestedWord object includes information about
-        // the current settings. It may also be useful to know, when the setting is off, whether
-        // the word *would* have been auto-corrected.
-        if (!isCorrectionEnabled || !allowsToBeAutoCorrected || resultsArePredictions
-                || suggestionResults.isEmpty() || wordComposer.hasDigits()
-                || wordComposer.isMostlyCaps() || wordComposer.isResumed()
-                || !mDictionaryFacilitator.hasInitializedMainDictionary()
-                || suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
-            // If we don't have a main dictionary, we never want to auto-correct. The reason for
-            // this is, the user may have a contact whose name happens to match a valid word in
-            // their language, and it will unexpectedly auto-correct. For example, if the user
-            // types in English with no dictionary and has a "Will" in their contact list, "will"
-            // would always auto-correct to "Will" which is unwanted. Hence, no main dict => no
-            // auto-correct.
-            // Also, shortcuts should never auto-correct unless they are whitelist entries.
-            // TODO: we may want to have shortcut-only entries auto-correct in the future.
-            hasAutoCorrection = false;
-        } else {
-            hasAutoCorrection = AutoCorrectionUtils.suggestionExceedsAutoCorrectionThreshold(
-                    suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
+        boolean foundInDictionary = false;
+        Dictionary sourceDictionaryOfRemovedWord = null;
+        for (final SuggestedWordInfo info : suggestionsContainer) {
+            // Search for the best dictionary, defined as the first one with the highest match
+            // quality we can find.
+            if (!foundInDictionary && typedWordString.equals(info.mWord)) {
+                // Use this source if the old match had lower quality than this match
+                sourceDictionaryOfRemovedWord = info.mSourceDict;
+                foundInDictionary = true;
+                break;
+            }
         }
 
-        if (!TextUtils.isEmpty(typedWord)) {
-            suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
-                    SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
-                    Dictionary.DICTIONARY_USER_TYPED,
-                    SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
-                    SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
+        final int firstOcurrenceOfTypedWordInSuggestions =
+                SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer);
+
+        final SuggestedWordInfo whitelistedWordInfo =
+                getWhitelistedWordInfoOrNull(suggestionsContainer);
+        final String whitelistedWord = whitelistedWordInfo == null
+                ? null : whitelistedWordInfo.mWord;
+        final boolean resultsArePredictions = !wordComposer.isComposingWord();
+
+        // We allow auto-correction if whitelisting is not required or the word is whitelisted,
+        // or if the word had more than one char and was not suggested.
+        final boolean allowsToBeAutoCorrected =
+                (SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION || whitelistedWord != null)
+                || (consideredWord.length() > 1 && (sourceDictionaryOfRemovedWord == null));
+
+        final boolean hasAutoCorrection;
+        // If correction is not enabled, we never auto-correct. This is for example for when
+        // the setting "Auto-correction" is "off": we still suggest, but we don't auto-correct.
+        if (!isCorrectionEnabled
+                // If the word does not allow to be auto-corrected, then we don't auto-correct.
+                || !allowsToBeAutoCorrected
+                // If we are doing prediction, then we never auto-correct of course
+                || resultsArePredictions
+                // If we don't have suggestion results, we can't evaluate the first suggestion
+                // for auto-correction
+                || suggestionResults.isEmpty()
+                // If the word has digits, we never auto-correct because it's likely the word
+                // was type with a lot of care
+                || wordComposer.hasDigits()
+                // If the word is mostly caps, we never auto-correct because this is almost
+                // certainly intentional (and careful input)
+                || wordComposer.isMostlyCaps()
+                // We never auto-correct when suggestions are resumed because it would be unexpected
+                || wordComposer.isResumed()
+                // If we don't have a main dictionary, we never want to auto-correct. The reason
+                // for this is, the user may have a contact whose name happens to match a valid
+                // word in their language, and it will unexpectedly auto-correct. For example, if
+                // the user types in English with no dictionary and has a "Will" in their contact
+                // list, "will" would always auto-correct to "Will" which is unwanted. Hence, no
+                // main dict => no auto-correct. Also, it would probably get obnoxious quickly.
+                // TODO: now that we have personalization, we may want to re-evaluate this decision
+                || !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary()
+                // If the first suggestion is a shortcut we never auto-correct to it, regardless
+                // of how strong it is (whitelist entries are not KIND_SHORTCUT but KIND_WHITELIST).
+                // TODO: we may want to have shortcut-only entries auto-correct in the future.
+                || suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
+            hasAutoCorrection = false;
+        } else {
+            final SuggestedWordInfo firstSuggestion = suggestionResults.first();
+            if (suggestionResults.mFirstSuggestionExceedsConfidenceThreshold
+                    && firstOcurrenceOfTypedWordInSuggestions != 0) {
+                hasAutoCorrection = true;
+            } else if (!AutoCorrectionUtils.suggestionExceedsThreshold(
+                    firstSuggestion, consideredWord, mAutoCorrectionThreshold)) {
+                // Score is too low for autocorrect
+                hasAutoCorrection = false;
+            } else {
+                // We have a high score, so we need to check if this suggestion is in the correct
+                // form to allow auto-correcting to it in this language. For details of how this
+                // is determined, see #isAllowedByAutoCorrectionWithSpaceFilter.
+                // TODO: this should not have its own logic here but be handled by the dictionary.
+                hasAutoCorrection = isAllowedByAutoCorrectionWithSpaceFilter(firstSuggestion);
+            }
+        }
+
+        final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString,
+                "" /* prevWordsContext */, SuggestedWordInfo.MAX_SCORE,
+                SuggestedWordInfo.KIND_TYPED,
+                null == sourceDictionaryOfRemovedWord ? Dictionary.DICTIONARY_USER_TYPED
+                        : sourceDictionaryOfRemovedWord,
+                SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+                SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
+        if (!TextUtils.isEmpty(typedWordString)) {
+            suggestionsContainer.add(0, typedWordInfo);
         }
 
         final ArrayList<SuggestedWordInfo> suggestionsList;
         if (DBG && !suggestionsContainer.isEmpty()) {
-            suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWord, suggestionsContainer);
+            suggestionsList = getSuggestionsInfoListWithDebugInfo(typedWordString,
+                    suggestionsContainer);
         } else {
             suggestionsList = suggestionsContainer;
         }
@@ -194,12 +274,12 @@
         } else {
             inputStyle = inputStyleIfNotPrediction;
         }
+
+        final boolean isTypedWordValid = firstOcurrenceOfTypedWordInSuggestions > -1
+                || (!resultsArePredictions && !allowsToBeAutoCorrected);
         callback.onGetSuggestedWords(new SuggestedWords(suggestionsList,
-                suggestionResults.mRawSuggestions,
-                // TODO: this first argument is lying. If this is a whitelisted word which is an
-                // actual word, it says typedWordValid = false, which looks wrong. We should either
-                // rename the attribute or change the value.
-                !resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */,
+                suggestionResults.mRawSuggestions, typedWordInfo,
+                isTypedWordValid,
                 hasAutoCorrection /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */, inputStyle, sequenceNumber));
     }
@@ -207,13 +287,15 @@
     // Retrieves suggestions for the batch input
     // and calls the callback function with the suggestions.
     private void getSuggestedWordsForBatchInput(final WordComposer wordComposer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
+            final NgramContext ngramContext, final Keyboard keyboard,
             final SettingsValuesForSuggestion settingsValuesForSuggestion,
             final int inputStyle, final int sequenceNumber,
             final OnGetSuggestedWordsCallback callback) {
         final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
-                wordComposer, prevWordsInfo, proximityInfo, settingsValuesForSuggestion,
-                SESSION_ID_GESTURE);
+                wordComposer.getComposedDataSnapshot(), ngramContext, keyboard,
+                settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle);
+        // For transforming words that don't come from a dictionary, because it's our best bet
+        final Locale locale = mDictionaryFacilitator.getLocale();
         final ArrayList<SuggestedWordInfo> suggestionsContainer =
                 new ArrayList<>(suggestionResults);
         final int suggestionsCount = suggestionsContainer.size();
@@ -222,22 +304,25 @@
         if (isFirstCharCapitalized || isAllUpperCase) {
             for (int i = 0; i < suggestionsCount; ++i) {
                 final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+                final Locale wordlocale = wordInfo.mSourceDict.mLocale;
                 final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
-                        wordInfo, suggestionResults.mLocale, isAllUpperCase, isFirstCharCapitalized,
-                        0 /* trailingSingleQuotesCount */);
+                        wordInfo, null == wordlocale ? locale : wordlocale, isAllUpperCase,
+                        isFirstCharCapitalized, 0 /* trailingSingleQuotesCount */);
                 suggestionsContainer.set(i, transformedWordInfo);
             }
         }
 
-        if (suggestionsContainer.size() > 1 && TextUtils.equals(suggestionsContainer.get(0).mWord,
-                wordComposer.getRejectedBatchModeSuggestion())) {
+        if (SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION
+                && suggestionsContainer.size() > 1
+                && TextUtils.equals(suggestionsContainer.get(0).mWord,
+                   wordComposer.getRejectedBatchModeSuggestion())) {
             final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
             suggestionsContainer.add(1, rejected);
         }
         SuggestedWordInfo.removeDups(null /* typedWord */, suggestionsContainer);
 
         // For some reason some suggestions with MIN_VALUE are making their way here.
-        // TODO: Find a more robust way to detect distractors.
+        // TODO: Find a more robust way to detect distracters.
         for (int i = suggestionsContainer.size() - 1; i >= 0; --i) {
             if (suggestionsContainer.get(i).mScore < SUPPRESS_SUGGEST_THRESHOLD) {
                 suggestionsContainer.remove(i);
@@ -248,8 +333,12 @@
         // (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false).
         // Note that because this method is never used to get predictions, there is no need to
         // modify inputType such in getSuggestedWordsForNonBatchInput.
+        final SuggestedWordInfo pseudoTypedWordInfo = suggestionsContainer.isEmpty() ? null
+                : suggestionsContainer.get(0);
+
         callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer,
                 suggestionResults.mRawSuggestions,
+                pseudoTypedWordInfo,
                 true /* typedWordValid */,
                 false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
@@ -283,6 +372,41 @@
         return suggestionsList;
     }
 
+    /**
+     * Computes whether this suggestion should be blocked or not in this language
+     *
+     * This function implements a filter that avoids auto-correcting to suggestions that contain
+     * spaces that are above a certain language-dependent character limit. In languages like German
+     * where it's possible to concatenate many words, it often happens our dictionary does not
+     * have the longer words. In this case, we offer a lot of unhelpful suggestions that contain
+     * one or several spaces. Ideally we should understand what the user wants and display useful
+     * suggestions by improving the dictionary and possibly having some specific logic. Until
+     * that's possible we should avoid displaying unhelpful suggestions. But it's hard to tell
+     * whether a suggestion is useful or not. So at least for the time being we block
+     * auto-correction when the suggestion is long and contains a space, which should avoid the
+     * worst damage.
+     * This function is implementing that filter. If the language enforces no such limit, then it
+     * always returns true. If the suggestion contains no space, it also returns true. Otherwise,
+     * it checks the length against the language-specific limit.
+     *
+     * @param info the suggestion info
+     * @return whether it's fine to auto-correct to this.
+     */
+    private static boolean isAllowedByAutoCorrectionWithSpaceFilter(final SuggestedWordInfo info) {
+        final Locale locale = info.mSourceDict.mLocale;
+        if (null == locale) {
+            return true;
+        }
+        final Integer maximumLengthForThisLanguage =
+                sLanguageToMaximumAutoCorrectionWithSpaceLength.get(locale.getLanguage());
+        if (null == maximumLengthForThisLanguage) {
+            // This language does not enforce a maximum length to auto-correction
+            return true;
+        }
+        return info.mWord.length() <= maximumLengthForThisLanguage
+                || -1 == info.mWord.indexOf(Constants.CODE_SPACE);
+    }
+
     /* package for test */ static SuggestedWordInfo getTransformedSuggestedWordInfo(
             final SuggestedWordInfo wordInfo, final Locale locale, final boolean isAllUpperCase,
             final boolean isOnlyFirstCharCapitalized, final int trailingSingleQuotesCount) {
@@ -302,7 +426,8 @@
         for (int i = quotesToAppend - 1; i >= 0; --i) {
             sb.appendCodePoint(Constants.CODE_SINGLE_QUOTE);
         }
-        return new SuggestedWordInfo(sb.toString(), wordInfo.mScore, wordInfo.mKindAndFlags,
+        return new SuggestedWordInfo(sb.toString(), wordInfo.mPrevWordsContext,
+                wordInfo.mScore, wordInfo.mKindAndFlags,
                 wordInfo.mSourceDict, wordInfo.mIndexOfTouchPointOfSecondWord,
                 wordInfo.mAutoCommitFirstWordConfidence);
     }
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 1d221b7..bcd4d5f 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -20,13 +20,16 @@
 import android.view.inputmethod.CompletionInfo;
 
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public class SuggestedWords {
     public static final int INDEX_OF_TYPED_WORD = 0;
     public static final int INDEX_OF_AUTO_CORRECTION = 1;
@@ -45,11 +48,14 @@
     public static final int MAX_SUGGESTIONS = 18;
 
     private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = new ArrayList<>(0);
-    public static final SuggestedWords EMPTY = new SuggestedWords(
-            EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false /* typedWordValid */,
-            false /* willAutoCorrect */, false /* isObsoleteSuggestions */, INPUT_STYLE_NONE);
+    @Nonnull
+    private static final SuggestedWords EMPTY = new SuggestedWords(
+            EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, null /* typedWord */,
+            false /* typedWordValid */, false /* willAutoCorrect */,
+            false /* isObsoleteSuggestions */, INPUT_STYLE_NONE, NOT_A_SEQUENCE_NUMBER);
 
-    public final String mTypedWord;
+    @Nullable
+    public final SuggestedWordInfo mTypedWordInfo;
     public final boolean mTypedWordValid;
     // Note: this INCLUDES cases where the word will auto-correct to itself. A good definition
     // of what this flag means would be "the top suggestion is strong enough to auto-correct",
@@ -60,35 +66,14 @@
     // INPUT_STYLE_* constants above.
     public final int mInputStyle;
     public final int mSequenceNumber; // Sequence number for auto-commit.
+    @Nonnull
     protected final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList;
+    @Nullable
     public final ArrayList<SuggestedWordInfo> mRawSuggestions;
 
-    public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
-            final ArrayList<SuggestedWordInfo> rawSuggestions,
-            final boolean typedWordValid,
-            final boolean willAutoCorrect,
-            final boolean isObsoleteSuggestions,
-            final int inputStyle) {
-        this(suggestedWordInfoList, rawSuggestions, typedWordValid, willAutoCorrect,
-                isObsoleteSuggestions, inputStyle, NOT_A_SEQUENCE_NUMBER);
-    }
-
-    public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
-            final ArrayList<SuggestedWordInfo> rawSuggestions,
-            final boolean typedWordValid,
-            final boolean willAutoCorrect,
-            final boolean isObsoleteSuggestions,
-            final int inputStyle,
-            final int sequenceNumber) {
-        this(suggestedWordInfoList, rawSuggestions,
-                (suggestedWordInfoList.isEmpty() || isPrediction(inputStyle)) ? null
-                        : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord,
-                typedWordValid, willAutoCorrect, isObsoleteSuggestions, inputStyle, sequenceNumber);
-    }
-
-    public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
-            final ArrayList<SuggestedWordInfo> rawSuggestions,
-            final String typedWord,
+    public SuggestedWords(@Nonnull final ArrayList<SuggestedWordInfo> suggestedWordInfoList,
+            @Nullable final ArrayList<SuggestedWordInfo> rawSuggestions,
+            @Nullable final SuggestedWordInfo typedWordInfo,
             final boolean typedWordValid,
             final boolean willAutoCorrect,
             final boolean isObsoleteSuggestions,
@@ -101,7 +86,7 @@
         mIsObsoleteSuggestions = isObsoleteSuggestions;
         mInputStyle = inputStyle;
         mSequenceNumber = sequenceNumber;
-        mTypedWord = typedWord;
+        mTypedWordInfo = typedWordInfo;
     }
 
     public boolean isEmpty() {
@@ -113,6 +98,27 @@
     }
 
     /**
+     * Get suggested word to show as suggestions to UI.
+     *
+     * @param shouldShowLxxSuggestionUi true if showing suggestion UI introduced in LXX and later.
+     * @return the count of suggested word to show as suggestions to UI.
+     */
+    public int getWordCountToShow(final boolean shouldShowLxxSuggestionUi) {
+        if (isPrediction() || !shouldShowLxxSuggestionUi) {
+            return size();
+        }
+        return size() - /* typed word */ 1;
+    }
+
+    /**
+     * Get {@link SuggestedWordInfo} object for the typed word.
+     * @return The {@link SuggestedWordInfo} object for the typed word.
+     */
+    public SuggestedWordInfo getTypedWordInfo() {
+        return mTypedWordInfo;
+    }
+
+    /**
      * Get suggested word at <code>index</code>.
      * @param index The index of the suggested word.
      * @return The suggested word.
@@ -142,6 +148,15 @@
         return mSuggestedWordInfoList.get(index);
     }
 
+    /**
+     * Gets the suggestion index from the suggestions list.
+     * @param suggestedWordInfo The {@link SuggestedWordInfo} to find the index.
+     * @return The position of the suggestion in the suggestion list.
+     */
+    public int indexOf(SuggestedWordInfo suggestedWordInfo) {
+        return mSuggestedWordInfoList.indexOf(suggestedWordInfo);
+    }
+
     public String getDebugString(final int pos) {
         if (!DebugFlags.DEBUG_ENABLED) {
             return null;
@@ -187,17 +202,20 @@
         return result;
     }
 
+    @Nonnull
+    public static final SuggestedWords getEmptyInstance() {
+        return SuggestedWords.EMPTY;
+    }
+
     // Should get rid of the first one (what the user typed previously) from suggestions
     // and replace it with what the user currently typed.
     public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions(
-            final String typedWord, final SuggestedWords previousSuggestions) {
+            @Nonnull final SuggestedWordInfo typedWordInfo,
+            @Nonnull final SuggestedWords previousSuggestions) {
         final ArrayList<SuggestedWordInfo> suggestionsList = new ArrayList<>();
         final HashSet<String> alreadySeen = new HashSet<>();
-        suggestionsList.add(new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE,
-                SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
-                SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
-                SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
-        alreadySeen.add(typedWord.toString());
+        suggestionsList.add(typedWordInfo);
+        alreadySeen.add(typedWordInfo.mWord);
         final int previousSize = previousSuggestions.size();
         for (int index = 1; index < previousSize; index++) {
             final SuggestedWordInfo prevWordInfo = previousSuggestions.getInfo(index);
@@ -217,7 +235,8 @@
         return candidate.isEligibleForAutoCommit() ? candidate : null;
     }
 
-    public static final class SuggestedWordInfo {
+    // non-final for testability.
+    public static class SuggestedWordInfo {
         public static final int NOT_AN_INDEX = -1;
         public static final int NOT_A_CONFIDENCE = -1;
         public static final int MAX_SCORE = Integer.MAX_VALUE;
@@ -240,14 +259,17 @@
         public static final int KIND_FLAG_POSSIBLY_OFFENSIVE = 0x80000000;
         public static final int KIND_FLAG_EXACT_MATCH = 0x40000000;
         public static final int KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION = 0x20000000;
+        public static final int KIND_FLAG_APPROPRIATE_FOR_AUTO_CORRECTION = 0x10000000;
 
         public final String mWord;
+        public final String mPrevWordsContext;
         // The completion info from the application. Null for suggestions that don't come from
         // the application (including keyboard-computed ones, so this is almost always null)
         public final CompletionInfo mApplicationSpecifiedCompletionInfo;
         public final int mScore;
         public final int mKindAndFlags;
         public final int mCodePointCount;
+        @Deprecated
         public final Dictionary mSourceDict;
         // For auto-commit. This keeps track of the index inside the touch coordinates array
         // passed to native code to get suggestions for a gesture that corresponds to the first
@@ -261,6 +283,7 @@
         /**
          * Create a new suggested word info.
          * @param word The string to suggest.
+         * @param prevWordsContext previous words context.
          * @param score A measure of how likely this suggestion is.
          * @param kindAndFlags The kind of suggestion, as one of the above KIND_* constants with
          * flags.
@@ -268,10 +291,12 @@
          * @param indexOfTouchPointOfSecondWord See mIndexOfTouchPointOfSecondWord.
          * @param autoCommitFirstWordConfidence See mAutoCommitFirstWordConfidence.
          */
-        public SuggestedWordInfo(final String word, final int score, final int kindAndFlags,
+        public SuggestedWordInfo(final String word, final String prevWordsContext,
+                final int score, final int kindAndFlags,
                 final Dictionary sourceDict, final int indexOfTouchPointOfSecondWord,
                 final int autoCommitFirstWordConfidence) {
             mWord = word;
+            mPrevWordsContext = prevWordsContext;
             mApplicationSpecifiedCompletionInfo = null;
             mScore = score;
             mKindAndFlags = kindAndFlags;
@@ -288,6 +313,7 @@
          */
         public SuggestedWordInfo(final CompletionInfo applicationSpecifiedCompletion) {
             mWord = applicationSpecifiedCompletion.getText().toString();
+            mPrevWordsContext = "";
             mApplicationSpecifiedCompletionInfo = applicationSpecifiedCompletion;
             mScore = SuggestedWordInfo.MAX_SCORE;
             mKindAndFlags = SuggestedWordInfo.KIND_APP_DEFINED;
@@ -321,6 +347,10 @@
             return (mKindAndFlags & KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION) != 0;
         }
 
+        public boolean isAprapreateForAutoCorrection() {
+            return (mKindAndFlags & KIND_FLAG_APPROPRIATE_FOR_AUTO_CORRECTION) != 0;
+        }
+
         public void setDebugString(final String str) {
             if (null == str) throw new NullPointerException("Debug info is null");
             mDebugString = str;
@@ -330,6 +360,15 @@
             return mDebugString;
         }
 
+        public String getWord() {
+            return mWord;
+        }
+
+        @Deprecated
+        public Dictionary getSourceDictionary() {
+            return mSourceDict;
+        }
+
         public int codePointAt(int i) {
             return mWord.codePointAt(i);
         }
@@ -338,43 +377,49 @@
         public String toString() {
             if (TextUtils.isEmpty(mDebugString)) {
                 return mWord;
-            } else {
-                return mWord + " (" + mDebugString + ")";
             }
+            return mWord + " (" + mDebugString + ")";
         }
 
-        // This will always remove the higher index if a duplicate is found.
-        public static boolean removeDups(final String typedWord,
-                ArrayList<SuggestedWordInfo> candidates) {
+        /**
+         * This will always remove the higher index if a duplicate is found.
+         *
+         * @return position of typed word in the candidate list
+         */
+        public static int removeDups(
+                @Nullable final String typedWord,
+                @Nonnull final ArrayList<SuggestedWordInfo> candidates) {
             if (candidates.isEmpty()) {
-                return false;
+                return -1;
             }
-            final boolean didRemoveTypedWord;
+            int firstOccurrenceOfWord = -1;
             if (!TextUtils.isEmpty(typedWord)) {
-                didRemoveTypedWord = removeSuggestedWordInfoFrom(typedWord, candidates,
-                        -1 /* startIndexExclusive */);
-            } else {
-                didRemoveTypedWord = false;
+                firstOccurrenceOfWord = removeSuggestedWordInfoFromList(
+                        typedWord, candidates, -1 /* startIndexExclusive */);
             }
             for (int i = 0; i < candidates.size(); ++i) {
-                removeSuggestedWordInfoFrom(candidates.get(i).mWord, candidates,
-                        i /* startIndexExclusive */);
+                removeSuggestedWordInfoFromList(
+                        candidates.get(i).mWord, candidates, i /* startIndexExclusive */);
             }
-            return didRemoveTypedWord;
+            return firstOccurrenceOfWord;
         }
 
-        private static boolean removeSuggestedWordInfoFrom(final String word,
-                final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) {
-            boolean didRemove = false;
+        private static int removeSuggestedWordInfoFromList(
+                @Nonnull final String word,
+                @Nonnull final ArrayList<SuggestedWordInfo> candidates,
+                final int startIndexExclusive) {
+            int firstOccurrenceOfWord = -1;
             for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) {
                 final SuggestedWordInfo previous = candidates.get(i);
                 if (word.equals(previous.mWord)) {
-                    didRemove = true;
+                    if (firstOccurrenceOfWord == -1) {
+                        firstOccurrenceOfWord = i;
+                    }
                     candidates.remove(i);
                     --i;
                 }
             }
-            return didRemove;
+            return firstOccurrenceOfWord;
         }
     }
 
@@ -387,47 +432,6 @@
         return isPrediction(mInputStyle);
     }
 
-    // SuggestedWords is an immutable object, as much as possible. We must not just remove
-    // words from the member ArrayList as some other parties may expect the object to never change.
-    // This is only ever called by recorrection at the moment, hence the ForRecorrection moniker.
-    public SuggestedWords getSuggestedWordsExcludingTypedWordForRecorrection() {
-        final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
-        String typedWord = null;
-        for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
-            final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
-            if (!info.isKindOf(SuggestedWordInfo.KIND_TYPED)) {
-                newSuggestions.add(info);
-            } else {
-                assert(null == typedWord);
-                typedWord = info.mWord;
-            }
-        }
-        // We should never autocorrect, so we say the typed word is valid. Also, in this case,
-        // no auto-correction should take place hence willAutoCorrect = false.
-        return new SuggestedWords(newSuggestions, null /* rawSuggestions */, typedWord,
-                true /* typedWordValid */, false /* willAutoCorrect */, mIsObsoleteSuggestions,
-                SuggestedWords.INPUT_STYLE_RECORRECTION, NOT_A_SEQUENCE_NUMBER);
-    }
-
-    // Creates a new SuggestedWordInfo from the currently suggested words that removes all but the
-    // last word of all suggestions, separated by a space. This is necessary because when we commit
-    // a multiple-word suggestion, the IME only retains the last word as the composing word, and
-    // we should only suggest replacements for this last word.
-    // TODO: make this work with languages without spaces.
-    public SuggestedWords getSuggestedWordsForLastWordOfPhraseGesture() {
-        final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
-        for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
-            final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
-            final int indexOfLastSpace = info.mWord.lastIndexOf(Constants.CODE_SPACE) + 1;
-            final String lastWord = info.mWord.substring(indexOfLastSpace);
-            newSuggestions.add(new SuggestedWordInfo(lastWord, info.mScore, info.mKindAndFlags,
-                    info.mSourceDict, SuggestedWordInfo.NOT_AN_INDEX,
-                    SuggestedWordInfo.NOT_A_CONFIDENCE));
-        }
-        return new SuggestedWords(newSuggestions, null /* rawSuggestions */, mTypedWordValid,
-                mWillAutoCorrect, mIsObsoleteSuggestions, INPUT_STYLE_TAIL_BATCH);
-    }
-
     /**
      * @return the {@link SuggestedWordInfo} which corresponds to the word that is originally
      * typed by the user. Otherwise returns {@code null}. Note that gesture input is not
diff --git a/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java b/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java
deleted file mode 100644
index 08785f3..0000000
--- a/java/src/com/android/inputmethod/latin/SuggestionSpanPickedNotificationReceiver.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.text.style.SuggestionSpan;
-import android.util.Log;
-
-import com.android.inputmethod.latin.define.DebugFlags;
-
-public final class SuggestionSpanPickedNotificationReceiver extends BroadcastReceiver {
-    private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
-    private static final String TAG =
-            SuggestionSpanPickedNotificationReceiver.class.getSimpleName();
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(intent.getAction())) {
-            if (DBG) {
-                final String before = intent.getStringExtra(
-                        SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE);
-                final String after = intent.getStringExtra(
-                        SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER);
-                Log.d(TAG, "Received notification picked: " + before + "," + after);
-            }
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
index 123ab20..2a69d36 100644
--- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java
@@ -17,16 +17,20 @@
 package com.android.inputmethod.latin;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.os.Process;
 import android.util.Log;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.compat.IntentCompatUtils;
+import com.android.inputmethod.dictionarypack.CommonPreferences;
+import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
-import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
+import com.android.inputmethod.latin.setup.SetupActivity;
 import com.android.inputmethod.latin.utils.UncachedInputMethodManagerUtils;
 
 /**
@@ -50,10 +54,6 @@
  * receiver and it checks whether the setup wizard's icon should be appeared or not on the launcher
  * depending on which partition this IME is installed.
  *
- * When a multiuser account has been created, {@link Intent#ACTION_USER_INITIALIZE} is received
- * by this receiver and it checks the whether the setup wizard's icon should be appeared or not on
- * the launcher depending on which partition this IME is installed.
- *
  * When the system locale has been changed, {@link Intent#ACTION_LOCALE_CHANGED} is received by
  * this receiver and the {@link KeyboardLayoutSet}'s cache is cleared.
  */
@@ -69,26 +69,25 @@
             // subtypes when the package is replaced.
             RichInputMethodManager.init(context);
             final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
-            final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(context);
+            final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes();
             richImm.setAdditionalInputMethodSubtypes(additionalSubtypes);
-            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
+            toggleAppIcon(context);
+            downloadLatestDictionaries(context);
         } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) {
             Log.i(TAG, "Boot has been completed");
-            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
-        } else if (IntentCompatUtils.is_ACTION_USER_INITIALIZE(intentAction)) {
-            Log.i(TAG, "User initialize");
-            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(context);
+            toggleAppIcon(context);
         } else if (Intent.ACTION_LOCALE_CHANGED.equals(intentAction)) {
             Log.i(TAG, "System locale changed");
             KeyboardLayoutSet.onSystemLocaleChanged();
         }
 
         // The process that hosts this broadcast receiver is invoked and remains alive even after
-        // 1) the package has been re-installed, 2) the device has just booted,
+        // 1) the package has been re-installed,
+        // 2) the device has just booted,
         // 3) a new user has been created.
         // There is no good reason to keep the process alive if this IME isn't a current IME.
-        final InputMethodManager imm =
-                (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        final InputMethodManager imm = (InputMethodManager)
+                context.getSystemService(Context.INPUT_METHOD_SERVICE);
         // Called to check whether this IME has been triggered by the current user or not
         final boolean isInputMethodManagerValidForUserOfThisProcess =
                 !imm.getInputMethodList().isEmpty();
@@ -100,4 +99,24 @@
             Process.killProcess(myPid);
         }
     }
+
+    private void downloadLatestDictionaries(Context context) {
+        final Intent updateIntent = new Intent(
+                DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION);
+        context.sendBroadcast(updateIntent);
+    }
+
+    private static void toggleAppIcon(final Context context) {
+        final int appInfoFlags = context.getApplicationInfo().flags;
+        final boolean isSystemApp = (appInfoFlags & ApplicationInfo.FLAG_SYSTEM) > 0;
+        if (Log.isLoggable(TAG, Log.INFO)) {
+            Log.i(TAG, "toggleAppIcon() : FLAG_SYSTEM = " + isSystemApp);
+        }
+        context.getPackageManager().setComponentEnabledSetting(
+                new ComponentName(context, SetupActivity.class),
+                isSystemApp
+                        ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                PackageManager.DONT_KILL_APP);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 21014b3..fe24ccf 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -16,26 +16,25 @@
 
 package com.android.inputmethod.latin;
 
-import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
-import android.os.Build;
 import android.provider.UserDictionary.Words;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.UserDictionaryCompatUtils;
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.io.File;
 import java.util.Arrays;
 import java.util.Locale;
 
+import javax.annotation.Nullable;
+
 /**
  * An expandable dictionary that stores the words in the user dictionary provider into a binary
  * dictionary file to use it from native code.
@@ -47,36 +46,26 @@
     private static final String USER_DICTIONARY_ALL_LANGUAGES = "";
     private static final int HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY = 250;
     private static final int LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY = 160;
-    // Shortcut frequency is 0~15, with 15 = whitelist. We don't want user dictionary entries
-    // to auto-correct, so we set this to the highest frequency that won't, i.e. 14.
-    private static final int USER_DICT_SHORTCUT_FREQUENCY = 14;
 
-    private static final String[] PROJECTION_QUERY_WITH_SHORTCUT = new String[] {
-        Words.WORD,
-        Words.SHORTCUT,
-        Words.FREQUENCY,
-    };
-    private static final String[] PROJECTION_QUERY_WITHOUT_SHORTCUT = new String[] {
-        Words.WORD,
-        Words.FREQUENCY,
-    };
+    private static final String[] PROJECTION_QUERY = new String[] {Words.WORD, Words.FREQUENCY};
 
     private static final String NAME = "userunigram";
 
     private ContentObserver mObserver;
-    final private String mLocale;
+    final private String mLocaleString;
     final private boolean mAlsoUseMoreRestrictiveLocales;
 
     protected UserBinaryDictionary(final Context context, final Locale locale,
-            final boolean alsoUseMoreRestrictiveLocales, final File dictFile, final String name) {
+                                   final boolean alsoUseMoreRestrictiveLocales,
+                                   final File dictFile, final String name) {
         super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_USER, dictFile);
         if (null == locale) throw new NullPointerException(); // Catch the error earlier
         final String localeStr = locale.toString();
         if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) {
             // If we don't have a locale, insert into the "all locales" user dictionary.
-            mLocale = USER_DICTIONARY_ALL_LANGUAGES;
+            mLocaleString = USER_DICTIONARY_ALL_LANGUAGES;
         } else {
-            mLocale = localeStr;
+            mLocaleString = localeStr;
         }
         mAlsoUseMoreRestrictiveLocales = alsoUseMoreRestrictiveLocales;
         ContentResolver cres = context.getContentResolver();
@@ -101,10 +90,13 @@
         reloadDictionaryIfRequired();
     }
 
-    @UsedForTesting
-    public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
-            final File dictFile, final String dictNamePrefix) {
-        return new UserBinaryDictionary(context, locale, false /* alsoUseMoreRestrictiveLocales */,
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @ExternallyReferenced
+    public static UserBinaryDictionary getDictionary(
+            final Context context, final Locale locale, final File dictFile,
+            final String dictNamePrefix, @Nullable final String account) {
+        return new UserBinaryDictionary(
+                context, locale, false /* alsoUseMoreRestrictiveLocales */,
                 dictFile, dictNamePrefix + NAME);
     }
 
@@ -124,7 +116,7 @@
         // This is correct for locale processing.
         // For this example, we'll look at the "en_US_POSIX" case.
         final String[] localeElements =
-                TextUtils.isEmpty(mLocale) ? new String[] {} : mLocale.split("_", 3);
+                TextUtils.isEmpty(mLocaleString) ? new String[] {} : mLocaleString.split("_", 3);
         final int length = localeElements.length;
 
         final StringBuilder request = new StringBuilder("(locale is NULL)");
@@ -167,24 +159,12 @@
             requestArguments = localeElements;
         }
         final String requestString = request.toString();
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-            try {
-                addWordsFromProjectionLocked(PROJECTION_QUERY_WITH_SHORTCUT, requestString,
-                        requestArguments);
-            } catch (IllegalArgumentException e) {
-                // This may happen on some non-compliant devices where the declared API is JB+ but
-                // the SHORTCUT column is not present for some reason.
-                addWordsFromProjectionLocked(PROJECTION_QUERY_WITHOUT_SHORTCUT, requestString,
-                        requestArguments);
-            }
-        } else {
-            addWordsFromProjectionLocked(PROJECTION_QUERY_WITHOUT_SHORTCUT, requestString,
-                    requestArguments);
-        }
+        addWordsFromProjectionLocked(PROJECTION_QUERY, requestString, requestArguments);
     }
 
     private void addWordsFromProjectionLocked(final String[] query, String request,
-            final String[] requestArguments) throws IllegalArgumentException {
+                                              final String[] requestArguments)
+            throws IllegalArgumentException {
         Cursor cursor = null;
         try {
             cursor = mContext.getContentResolver().query(
@@ -201,69 +181,33 @@
         }
     }
 
-    public static boolean isEnabled(final Context context) {
-        final ContentResolver cr = context.getContentResolver();
-        final ContentProviderClient client = cr.acquireContentProviderClient(Words.CONTENT_URI);
-        if (client != null) {
-            client.release();
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Adds a word to the user dictionary and makes it persistent.
-     *
-     * @param context the context
-     * @param locale the locale
-     * @param word the word to add. If the word is capitalized, then the dictionary will
-     * recognize it as a capitalized word when searched.
-     */
-    public static void addWordToUserDictionary(final Context context, final Locale locale,
-            final String word) {
-        // Update the user dictionary provider
-        UserDictionaryCompatUtils.addWord(context, word,
-                HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY, null, locale);
-    }
-
-    private int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
+    private static int scaleFrequencyFromDefaultToLatinIme(final int defaultFrequency) {
         // The default frequency for the user dictionary is 250 for historical reasons.
         // Latin IME considers a good value for the default user dictionary frequency
         // is about 160 considering the scale we use. So we are scaling down the values.
         if (defaultFrequency > Integer.MAX_VALUE / LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY) {
             return (defaultFrequency / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY)
                     * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY;
-        } else {
-            return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
-                    / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
         }
+        return (defaultFrequency * LATINIME_DEFAULT_USER_DICTIONARY_FREQUENCY)
+                / HISTORICAL_DEFAULT_USER_DICTIONARY_FREQUENCY;
     }
 
     private void addWordsLocked(final Cursor cursor) {
-        final boolean hasShortcutColumn = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
         if (cursor == null) return;
         if (cursor.moveToFirst()) {
             final int indexWord = cursor.getColumnIndex(Words.WORD);
-            final int indexShortcut = hasShortcutColumn ? cursor.getColumnIndex(Words.SHORTCUT) : 0;
             final int indexFrequency = cursor.getColumnIndex(Words.FREQUENCY);
             while (!cursor.isAfterLast()) {
                 final String word = cursor.getString(indexWord);
-                final String shortcut = hasShortcutColumn ? cursor.getString(indexShortcut) : null;
                 final int frequency = cursor.getInt(indexFrequency);
                 final int adjustedFrequency = scaleFrequencyFromDefaultToLatinIme(frequency);
                 // Safeguard against adding really long words.
                 if (word.length() <= MAX_WORD_LENGTH) {
                     runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                    addUnigramLocked(word, adjustedFrequency, null /* shortcutTarget */,
-                            0 /* shortcutFreq */, false /* isNotAWord */,
-                            false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    if (null != shortcut && shortcut.length() <= MAX_WORD_LENGTH) {
-                        runGCIfRequiredLocked(true /* mindsBlockByGC */);
-                        addUnigramLocked(shortcut, adjustedFrequency, word,
-                                USER_DICT_SHORTCUT_FREQUENCY, true /* isNotAWord */,
-                                false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                    }
+                    addUnigramLocked(word, adjustedFrequency, false /* isNotAWord */,
+                            false /* isPossiblyOffensive */,
+                            BinaryDictionary.NOT_A_VALID_TIMESTAMP);
                 }
                 cursor.moveToNext();
             }
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 32d1fe3..8803edc 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -16,11 +16,17 @@
 
 package com.android.inputmethod.latin;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.event.CombinerChain;
 import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.ComposedData;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -31,7 +37,7 @@
  * A place to store the currently composing word with information such as adjacent key codes as well
  */
 public final class WordComposer {
-    private static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
+    private static final int MAX_WORD_LENGTH = DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH;
     private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
 
     public static final int CAPS_MODE_OFF = 0;
@@ -48,7 +54,7 @@
     // The list of events that served to compose this string.
     private final ArrayList<Event> mEvents;
     private final InputPointers mInputPointers = new InputPointers(MAX_WORD_LENGTH);
-    private String mAutoCorrection;
+    private SuggestedWordInfo mAutoCorrection;
     private boolean mIsResumed;
     private boolean mIsBatchMode;
     // A memory of the last rejected batch mode suggestion, if any. This goes like this: the user
@@ -87,6 +93,10 @@
         refreshTypedWordCache();
     }
 
+    public ComposedData getComposedDataSnapshot() {
+        return new ComposedData(getInputPointers(), isBatchMode(), mTypedWordCache.toString());
+    }
+
     /**
      * Restart the combiners, possibly with a new spec.
      * @param combiningSpec The spec string for combining. This is found in the extra value.
@@ -95,8 +105,7 @@
         final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec;
         if (!nonNullCombiningSpec.equals(mCombiningSpec)) {
             mCombinerChain = new CombinerChain(
-                    mCombinerChain.getComposingWordWithCombiningFeedback().toString(),
-                    CombinerChain.createCombiners(nonNullCombiningSpec));
+                    mCombinerChain.getComposingWordWithCombiningFeedback().toString());
             mCombiningSpec = nonNullCombiningSpec;
         }
     }
@@ -127,43 +136,10 @@
      * Number of keystrokes in the composing word.
      * @return the number of keystrokes
      */
-    // This may be made public if need be, but right now it's not used anywhere
-    /* package for tests */ int size() {
+    public int size() {
         return mCodePointSize;
     }
 
-    /**
-     * Copy the code points in the typed word to a destination array of ints.
-     *
-     * If the array is too small to hold the code points in the typed word, nothing is copied and
-     * -1 is returned.
-     *
-     * @param destination the array of ints.
-     * @return the number of copied code points.
-     */
-    public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
-            final int[] destination) {
-        // This method can be called on a separate thread and mTypedWordCache can change while we
-        // are executing this method.
-        final String typedWord = mTypedWordCache.toString();
-        // lastIndex is exclusive
-        final int lastIndex = typedWord.length()
-                - StringUtils.getTrailingSingleQuotesCount(typedWord);
-        if (lastIndex <= 0) {
-            // The string is empty or contains only single quotes.
-            return 0;
-        }
-
-        // The following function counts the number of code points in the text range which begins
-        // at index 0 and extends to the character at lastIndex.
-        final int codePointSize = Character.codePointCount(typedWord, 0, lastIndex);
-        if (codePointSize > destination.length) {
-            return -1;
-        }
-        return StringUtils.copyCodePointsAndReturnCodePointCount(destination, typedWord, 0,
-                lastIndex, true /* downCase */);
-    }
-
     public boolean isSingleLetter() {
         return size() == 1;
     }
@@ -182,7 +158,7 @@
      * @return the processed event. Never null, but may be marked as consumed.
      */
     @Nonnull
-    public Event processEvent(final Event event) {
+    public Event processEvent(@Nonnull final Event event) {
         final Event processedEvent = mCombinerChain.processEvent(mEvents, event);
         // The retained state of the combiner chain may have changed while processing the event,
         // so we need to update our cache.
@@ -256,31 +232,33 @@
      * @return true if the cursor is still inside the composing word, false otherwise.
      */
     public boolean moveCursorByAndReturnIfInsideComposingWord(final int expectedMoveAmount) {
-        // TODO: should uncommit the composing feedback
-        mCombinerChain.reset();
-        int actualMoveAmountWithinWord = 0;
+        int actualMoveAmount = 0;
         int cursorPos = mCursorPositionWithinWord;
         // TODO: Don't make that copy. We can do this directly from mTypedWordCache.
         final int[] codePoints = StringUtils.toCodePointArray(mTypedWordCache);
         if (expectedMoveAmount >= 0) {
             // Moving the cursor forward for the expected amount or until the end of the word has
             // been reached, whichever comes first.
-            while (actualMoveAmountWithinWord < expectedMoveAmount && cursorPos < mCodePointSize) {
-                actualMoveAmountWithinWord += Character.charCount(codePoints[cursorPos]);
+            while (actualMoveAmount < expectedMoveAmount && cursorPos < codePoints.length) {
+                actualMoveAmount += Character.charCount(codePoints[cursorPos]);
                 ++cursorPos;
             }
         } else {
             // Moving the cursor backward for the expected amount or until the start of the word
             // has been reached, whichever comes first.
-            while (actualMoveAmountWithinWord > expectedMoveAmount && cursorPos > 0) {
+            while (actualMoveAmount > expectedMoveAmount && cursorPos > 0) {
                 --cursorPos;
-                actualMoveAmountWithinWord -= Character.charCount(codePoints[cursorPos]);
+                actualMoveAmount -= Character.charCount(codePoints[cursorPos]);
             }
         }
         // If the actual and expected amounts differ, we crossed the start or the end of the word
         // so the result would not be inside the composing word.
-        if (actualMoveAmountWithinWord != expectedMoveAmount) return false;
+        if (actualMoveAmount != expectedMoveAmount) {
+            return false;
+        }
         mCursorPositionWithinWord = cursorPos;
+        mCombinerChain.applyProcessedEvent(mCombinerChain.processEvent(
+                mEvents, Event.createCursorMovedEvent(cursorPos)));
         return true;
     }
 
@@ -353,9 +331,8 @@
         if (size() <= 1) {
             return mCapitalizedMode == CAPS_MODE_AUTO_SHIFT_LOCKED
                     || mCapitalizedMode == CAPS_MODE_MANUAL_SHIFT_LOCKED;
-        } else {
-            return mCapsCount == size();
         }
+        return mCapsCount == size();
     }
 
     public boolean wasShiftedNoLock() {
@@ -418,14 +395,14 @@
     /**
      * Sets the auto-correction for this word.
      */
-    public void setAutoCorrection(final String correction) {
-        mAutoCorrection = correction;
+    public void setAutoCorrection(final SuggestedWordInfo autoCorrection) {
+        mAutoCorrection = autoCorrection;
     }
 
     /**
      * @return the auto-correction for this word, or null if none.
      */
-    public String getAutoCorrectionOrNull() {
+    public SuggestedWordInfo getAutoCorrectionOrNull() {
         return mAutoCorrection;
     }
 
@@ -439,13 +416,13 @@
     // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above.
     // committedWord should contain suggestion spans if applicable.
     public LastComposedWord commitWord(final int type, final CharSequence committedWord,
-            final String separatorString, final PrevWordsInfo prevWordsInfo) {
+            final String separatorString, final NgramContext ngramContext) {
         // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
         // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
         // the last composed word to ensure this does not happen.
         final LastComposedWord lastComposedWord = new LastComposedWord(mEvents,
                 mInputPointers, mTypedWordCache.toString(), committedWord, separatorString,
-                prevWordsInfo, mCapitalizedMode);
+                ngramContext, mCapitalizedMode);
         mInputPointers.reset();
         if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
                 && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
@@ -491,4 +468,14 @@
     public String getRejectedBatchModeSuggestion() {
         return mRejectedBatchModeSuggestion;
     }
+
+    @UsedForTesting
+    void addInputPointerForTest(int index, int keyX, int keyY) {
+        mInputPointers.addPointerAt(index, keyX, keyY, 0, 0);
+    }
+
+    @UsedForTesting
+    void setTypedWordCacheForTests(String typedWordCacheForTests) {
+        mTypedWordCache = typedWordCacheForTests;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java b/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java
new file mode 100644
index 0000000..00bcecf
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.accounts.AccountManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.settings.LocalSettingsConstants;
+
+/**
+ * {@link BroadcastReceiver} for {@link AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION}.
+ */
+public class AccountsChangedReceiver extends BroadcastReceiver {
+    static final String TAG = "AccountsChangedReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
+            Log.w(TAG, "Received unknown broadcast: " + intent);
+            return;
+        }
+
+        // Ideally the account preference could live in a different preferences file
+        // that wasn't being backed up and restored, however the preference fragments
+        // currently only deal with the default shared preferences which is why
+        // separating this out into a different file is not trivial currently.
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        final String currentAccount = prefs.getString(
+                LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
+        removeUnknownAccountFromPreference(prefs, getAccountsForLogin(context), currentAccount);
+    }
+
+    /**
+     * Helper method to help test this receiver.
+     */
+    @UsedForTesting
+    protected String[] getAccountsForLogin(Context context) {
+        return LoginAccountUtils.getAccountsForLogin(context);
+    }
+
+    /**
+     * Removes the currentAccount from preferences if it's not found
+     * in the list of current accounts.
+     */
+    private static void removeUnknownAccountFromPreference(final SharedPreferences prefs,
+            final String[] accounts, final String currentAccount) {
+        if (currentAccount == null) {
+            return;
+        }
+        for (final String account : accounts) {
+            if (TextUtils.equals(currentAccount, account)) {
+                return;
+            }
+        }
+        Log.i(TAG, "The current account was removed from the system: " + currentAccount);
+        prefs.edit()
+                .remove(LocalSettingsConstants.PREF_ACCOUNT_NAME)
+                .apply();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/accounts/AuthUtils.java b/java/src/com/android/inputmethod/latin/accounts/AuthUtils.java
new file mode 100644
index 0000000..31aba36
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/accounts/AuthUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+
+import java.io.IOException;
+
+/**
+ * Utility class that handles generation/invalidation of auth tokens in the app.
+ */
+public class AuthUtils {
+    private final AccountManager mAccountManager;
+
+    public AuthUtils(Context context) {
+        mAccountManager = AccountManager.get(context);
+    }
+
+    /**
+     * @see AccountManager#invalidateAuthToken(String, String)
+     */
+    public void invalidateAuthToken(final String accountType, final String authToken) {
+        mAccountManager.invalidateAuthToken(accountType, authToken);
+    }
+
+    /**
+     * @see AccountManager#getAuthToken(
+     *              Account, String, Bundle, boolean, AccountManagerCallback, Handler)
+     */
+    public AccountManagerFuture<Bundle> getAuthToken(final Account account,
+            final String authTokenType, final Bundle options, final boolean notifyAuthFailure,
+            final AccountManagerCallback<Bundle> callback, final Handler handler) {
+        return mAccountManager.getAuthToken(account, authTokenType, options, notifyAuthFailure,
+                callback, handler);
+    }
+
+    /**
+     * @see AccountManager#blockingGetAuthToken(Account, String, boolean)
+     */
+    public String blockingGetAuthToken(final Account account, final String authTokenType,
+            final boolean notifyAuthFailure) throws OperationCanceledException,
+            AuthenticatorException, IOException {
+        return mAccountManager.blockingGetAuthToken(account, authTokenType, notifyAuthFailure);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
deleted file mode 100644
index a87785b..0000000
--- a/java/src/com/android/inputmethod/latin/debug/ExternalDictionaryGetterForDebug.java
+++ /dev/null
@@ -1,189 +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.debug;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnClickListener;
-import android.os.Environment;
-
-import com.android.inputmethod.latin.BinaryDictionaryFileDumper;
-import com.android.inputmethod.latin.BinaryDictionaryGetter;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.utils.DialogUtils;
-import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * A class to read a local file as a dictionary for debugging purposes.
- */
-public class ExternalDictionaryGetterForDebug {
-    private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
-            + "/Download";
-
-    private static String[] findDictionariesInTheDownloadedFolder() {
-        final File[] files = new File(SOURCE_FOLDER).listFiles();
-        final ArrayList<String> eligibleList = new ArrayList<>();
-        for (File f : files) {
-            final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(f);
-            if (null == header) continue;
-            eligibleList.add(f.getName());
-        }
-        return eligibleList.toArray(new String[0]);
-    }
-
-    public static void chooseAndInstallDictionary(final Context context) {
-        final String[] fileNames = findDictionariesInTheDownloadedFolder();
-        if (0 == fileNames.length) {
-            showNoFileDialog(context);
-        } else if (1 == fileNames.length) {
-            askInstallFile(context, SOURCE_FOLDER, fileNames[0], null /* completeRunnable */);
-        } else {
-            showChooseFileDialog(context, fileNames);
-        }
-    }
-
-    private static void showNoFileDialog(final Context context) {
-        new AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(context))
-                .setMessage(R.string.read_external_dictionary_no_files_message)
-                .setPositiveButton(android.R.string.ok, new OnClickListener() {
-                    @Override
-                    public void onClick(final DialogInterface dialog, final int which) {
-                        dialog.dismiss();
-                    }
-                }).create().show();
-    }
-
-    private static void showChooseFileDialog(final Context context, final String[] fileNames) {
-        new AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(context))
-                .setTitle(R.string.read_external_dictionary_multiple_files_title)
-                .setItems(fileNames, new OnClickListener() {
-                    @Override
-                    public void onClick(final DialogInterface dialog, final int which) {
-                        askInstallFile(context, SOURCE_FOLDER, fileNames[which],
-                                null /* completeRunnable */);
-                    }
-                })
-                .create().show();
-    }
-
-    /**
-     * Shows a dialog which offers the user to install the external dictionary.
-     */
-    public static void askInstallFile(final Context context, final String dirPath,
-            final String fileName, final Runnable completeRunnable) {
-        final File file = new File(dirPath, fileName.toString());
-        final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
-        final StringBuilder message = new StringBuilder();
-        final String locale = header.getLocaleString();
-        for (String key : header.mDictionaryOptions.mAttributes.keySet()) {
-            message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key));
-            message.append("\n");
-        }
-        final String languageName = LocaleUtils.constructLocaleFromString(locale)
-                .getDisplayName(Locale.getDefault());
-        final String title = String.format(
-                context.getString(R.string.read_external_dictionary_confirm_install_message),
-                languageName);
-        new AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(context))
-                .setTitle(title)
-                .setMessage(message)
-                .setNegativeButton(android.R.string.cancel, new OnClickListener() {
-                    @Override
-                    public void onClick(final DialogInterface dialog, final int which) {
-                        dialog.dismiss();
-                        if (completeRunnable != null) {
-                            completeRunnable.run();
-                        }
-                    }
-                }).setPositiveButton(android.R.string.ok, new OnClickListener() {
-                    @Override
-                    public void onClick(final DialogInterface dialog, final int which) {
-                        installFile(context, file, header);
-                        dialog.dismiss();
-                        if (completeRunnable != null) {
-                            completeRunnable.run();
-                        }
-                    }
-                }).setOnCancelListener(new OnCancelListener() {
-                    @Override
-                    public void onCancel(DialogInterface dialog) {
-                        // Canceled by the user by hitting the back key
-                        if (completeRunnable != null) {
-                            completeRunnable.run();
-                        }
-                    }
-                }).create().show();
-    }
-
-    private static void installFile(final Context context, final File file,
-            final DictionaryHeader header) {
-        BufferedOutputStream outputStream = null;
-        File tempFile = null;
-        try {
-            final String locale = header.getLocaleString();
-            // Create the id for a main dictionary for this locale
-            final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
-                    + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale;
-            final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
-            final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
-            tempFile = new File(tempFileName);
-            tempFile.delete();
-            outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
-            final BufferedInputStream bufferedStream = new BufferedInputStream(
-                    new FileInputStream(file));
-            BinaryDictionaryFileDumper.checkMagicAndCopyFileTo(bufferedStream, outputStream);
-            outputStream.flush();
-            final File finalFile = new File(finalFileName);
-            finalFile.delete();
-            if (!tempFile.renameTo(finalFile)) {
-                throw new IOException("Can't move the file to its final name");
-            }
-        } catch (IOException e) {
-            // There was an error: show a dialog
-            new AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(context))
-                    .setTitle(R.string.read_external_dictionary_error)
-                    .setMessage(e.toString())
-                    .setPositiveButton(android.R.string.ok, new OnClickListener() {
-                        @Override
-                        public void onClick(final DialogInterface dialog, final int which) {
-                            dialog.dismiss();
-                        }
-                    }).create().show();
-            return;
-        } finally {
-            try {
-                if (null != outputStream) outputStream.close();
-                if (null != tempFile) tempFile.delete();
-            } catch (IOException e) {
-                // Don't do anything
-            }
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index fdab7f2..5b3b28d 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.latin.inputlogic;
 
 import android.graphics.Color;
-import android.inputmethodservice.InputMethodService;
 import android.os.SystemClock;
 import android.text.SpannableString;
 import android.text.Spanned;
@@ -28,32 +27,28 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.inputmethod.CorrectionInfo;
-import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 
-import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
 import com.android.inputmethod.compat.SuggestionSpanUtils;
 import com.android.inputmethod.event.Event;
 import com.android.inputmethod.event.InputTransaction;
+import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
-import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.keyboard.TextDecorator;
-import com.android.inputmethod.keyboard.TextDecoratorUiOperator;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LastComposedWord;
 import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.PrevWordsInfo;
+import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.RichInputConnection;
 import com.android.inputmethod.latin.Suggest;
 import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
-import com.android.inputmethod.latin.define.ProductionFlags;
 import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
@@ -61,13 +56,15 @@
 import com.android.inputmethod.latin.utils.AsyncResultHolder;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
 import java.util.ArrayList;
 import java.util.TreeSet;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+
 /**
  * This class manages the input logic.
  */
@@ -75,7 +72,7 @@
     private static final String TAG = InputLogic.class.getSimpleName();
 
     // TODO : Remove this member when we can.
-    private final LatinIME mLatinIME;
+    final LatinIME mLatinIME;
     private final SuggestionStripViewAccessor mSuggestionStripViewAccessor;
 
     // Never null.
@@ -85,18 +82,10 @@
     // Current space state of the input method. This can be any of the above constants.
     private int mSpaceState;
     // Never null
-    public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+    public SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance();
     public final Suggest mSuggest;
     private final DictionaryFacilitator mDictionaryFacilitator;
 
-    private final TextDecorator mTextDecorator = new TextDecorator(new TextDecorator.Listener() {
-        @Override
-        public void onClickComposingTextToAddToDictionary(final String word) {
-            mLatinIME.addWordToUserDictionary(word);
-            mLatinIME.dismissAddToDictionaryHint();
-        }
-    });
-
     public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
     // This has package visibility so it can be accessed from InputLogicHandler.
     /* package */ final WordComposer mWordComposer;
@@ -144,13 +133,20 @@
      */
     public void startInput(final String combiningSpec, final SettingsValues settingsValues) {
         mEnteredText = null;
+        if (!mWordComposer.getTypedWord().isEmpty()) {
+            // For messaging apps that offer send button, the IME does not get the opportunity
+            // to capture the last word. This block should capture those uncommitted words.
+            // The timestamp at which it is captured is not accurate but close enough.
+            StatsUtils.onWordCommitUserTyped(
+                    mWordComposer.getTypedWord(), mWordComposer.isBatchMode());
+        }
         mWordComposer.restartCombining(combiningSpec);
         resetComposingState(true /* alsoResetLastComposedWord */);
         mDeleteCount = 0;
         mSpaceState = SpaceState.NONE;
         mRecapitalizeStatus.disable(); // Do not perform recapitalize until the cursor is moved once
         mCurrentlyPressedHardwareKeys.clear();
-        mSuggestedWords = SuggestedWords.EMPTY;
+        mSuggestedWords = SuggestedWords.getEmptyInstance();
         // In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying
         // so we try using some heuristics to find out about these and fix them.
         mConnection.tryFixLyingCursorPosition();
@@ -161,13 +157,9 @@
             mInputLogicHandler.reset();
         }
 
-        if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK) {
-            // AcceptTypedWord feature relies on CursorAnchorInfo.
-            if (settingsValues.mShouldShowUiToAcceptTypedWord) {
-                mConnection.requestCursorUpdates(true /* enableMonitor */,
-                        true /* requestImmediateCallback */);
-            }
-            mTextDecorator.reset();
+        if (settingsValues.mShouldShowLxxSuggestionUi) {
+            mConnection.requestCursorUpdates(true /* enableMonitor */,
+                    true /* requestImmediateCallback */);
         }
     }
 
@@ -204,6 +196,8 @@
     public void finishInput() {
         if (mWordComposer.isComposingWord()) {
             mConnection.finishComposingText();
+            StatsUtils.onWordCommitUserTyped(
+                    mWordComposer.getTypedWord(), mWordComposer.isBatchMode());
         }
         resetComposingState(true /* alsoResetLastComposedWord */);
         mInputLogicHandler.reset();
@@ -231,9 +225,7 @@
      * @return the complete transaction object
      */
     public InputTransaction onTextInput(final SettingsValues settingsValues, final Event event,
-            final int keyboardShiftMode,
-            // TODO: remove this argument
-            final LatinIME.UIHandler handler) {
+            final int keyboardShiftMode, final LatinIME.UIHandler handler) {
         final String rawText = event.getTextToCommit().toString();
         final InputTransaction inputTransaction = new InputTransaction(settingsValues, event,
                 SystemClock.uptimeMillis(), mSpaceState,
@@ -247,9 +239,10 @@
         handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_TYPING);
         final String text = performSpecificTldProcessingOnTextInput(rawText);
         if (SpaceState.PHANTOM == mSpaceState) {
-            promotePhantomSpace(settingsValues);
+            insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
         }
         mConnection.commitText(text, 1);
+        StatsUtils.onWordCommitUserTyped(mEnteredText, mWordComposer.isBatchMode());
         mConnection.endBatchEdit();
         // Space state must be updated before calling updateShiftState
         mSpaceState = SpaceState.NONE;
@@ -260,20 +253,6 @@
     }
 
     /**
-     * Determines whether "Touch again to save" should be shown or not.
-     * @param suggestionInfo the suggested word chosen by the user.
-     * @return {@code true} if we should show the "Touch again to save" hint.
-     */
-    private boolean shouldShowAddToDictionaryHint(final SuggestedWordInfo suggestionInfo) {
-        // We should show the "Touch again to save" hint if the user pressed the first entry
-        // AND it's in none of our current dictionaries (main, user or otherwise).
-        return (suggestionInfo.isKindOf(SuggestedWordInfo.KIND_TYPED)
-                || suggestionInfo.isKindOf(SuggestedWordInfo.KIND_OOV_CORRECTION))
-                && !mDictionaryFacilitator.isValidWord(suggestionInfo.mWord, true /* ignoreCase */)
-                && mDictionaryFacilitator.isUserDictionaryEnabled();
-    }
-
-    /**
      * A suggestion was picked from the suggestion strip.
      * @param settingsValues the current values of the settings.
      * @param suggestionInfo the suggestion info.
@@ -285,12 +264,14 @@
     // interface
     public InputTransaction onPickSuggestionManually(final SettingsValues settingsValues,
             final SuggestedWordInfo suggestionInfo, final int keyboardShiftState,
-            // TODO: remove these arguments
             final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
         final SuggestedWords suggestedWords = mSuggestedWords;
         final String suggestion = suggestionInfo.mWord;
         // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
         if (suggestion.length() == 1 && suggestedWords.isPunctuationSuggestions()) {
+            // We still want to log a suggestion click.
+            StatsUtils.onPickSuggestionManually(
+                    mSuggestedWords, suggestionInfo, mDictionaryFacilitator);
             // Word separators are suggested before the user inputs something.
             // Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
             final Event event = Event.createPunctuationSuggestionPickedEvent(suggestionInfo);
@@ -312,7 +293,7 @@
             final int firstChar = Character.codePointAt(suggestion, 0);
             if (!settingsValues.isWordSeparator(firstChar)
                     || settingsValues.isUsuallyPrecededBySpace(firstChar)) {
-                promotePhantomSpace(settingsValues);
+                insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
             }
         }
 
@@ -321,7 +302,7 @@
         // however need to reset the suggestion strip right away, because we know we can't take
         // the risk of calling commitCompletion twice because we don't know how the app will react.
         if (suggestionInfo.isKindOf(SuggestedWordInfo.KIND_APP_DEFINED)) {
-            mSuggestedWords = SuggestedWords.EMPTY;
+            mSuggestedWords = SuggestedWords.getEmptyInstance();
             mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
             inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
             resetComposingState(true /* alsoResetLastComposedWord */);
@@ -330,7 +311,6 @@
             return inputTransaction;
         }
 
-        final boolean shouldShowAddToDictionaryHint = shouldShowAddToDictionaryHint(suggestionInfo);
         commitChosenWord(settingsValues, suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
                 LastComposedWord.NOT_A_SEPARATOR);
         mConnection.endBatchEdit();
@@ -340,13 +320,14 @@
         mSpaceState = SpaceState.PHANTOM;
         inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
 
-        if (shouldShowAddToDictionaryHint) {
-            mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
-        } else {
-            // If we're not showing the "Touch again to save", then update the suggestion strip.
-            // That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
-            handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
-        }
+        // If we're not showing the "Touch again to save", then update the suggestion strip.
+        // That's going to be predictions (or punctuation suggestions), so INPUT_STYLE_NONE.
+        handler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
+
+        StatsUtils.onPickSuggestionManually(
+                mSuggestedWords, suggestionInfo, mDictionaryFacilitator);
+        StatsUtils.onWordCommitSuggestionPickedManually(
+                suggestionInfo.mWord, mWordComposer.isBatchMode());
         return inputTransaction;
     }
 
@@ -416,14 +397,8 @@
 
         // The cursor has been moved : we now accept to perform recapitalization
         mRecapitalizeStatus.enable();
-        // We moved the cursor and need to invalidate the indicator right now.
-        mTextDecorator.reset();
-        // Remaining background color that was used for the add-to-dictionary indicator should be
-        // removed.
-        mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
         // We moved the cursor. If we are touching a word, we need to resume suggestion.
-        mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */,
-                true /* shouldDelay */);
+        mLatinIME.mHandler.postResumeSuggestions(true /* shouldDelay */);
         // Stop the last recapitalization, if started.
         mRecapitalizeStatus.stop();
         return true;
@@ -442,9 +417,8 @@
      *     {@link com.android.inputmethod.keyboard.KeyboardSwitcher#getKeyboardShiftMode()}
      * @return the complete transaction object
      */
-    public InputTransaction onCodeInput(final SettingsValues settingsValues, final Event event,
-            final int keyboardShiftMode,
-            // TODO: remove these arguments
+    public InputTransaction onCodeInput(final SettingsValues settingsValues,
+            @Nonnull final Event event, final int keyboardShiftMode,
             final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
         final Event processedEvent = mWordComposer.processEvent(event);
         final InputTransaction inputTransaction = new InputTransaction(settingsValues,
@@ -491,17 +465,14 @@
     }
 
     public void onStartBatchInput(final SettingsValues settingsValues,
-            // TODO: remove these arguments
             final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
         mInputLogicHandler.onStartBatchInput();
         handler.showGesturePreviewAndSuggestionStrip(
-                SuggestedWords.EMPTY, false /* dismissGestureFloatingPreviewText */);
+                SuggestedWords.getEmptyInstance(), false /* dismissGestureFloatingPreviewText */);
         handler.cancelUpdateSuggestionStrip();
         ++mAutoCommitSequenceNumber;
         mConnection.beginBatchEdit();
-        if (!mWordComposer.isComposingWord()) {
-            mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
-        } else {
+        if (mWordComposer.isComposingWord()) {
             if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
                 // If we are in the middle of a recorrection, we need to commit the recorrection
                 // first so that we can insert the batch input at the current cursor position.
@@ -557,30 +528,7 @@
      * earlier sequence number.
      */
     private int mAutoCommitSequenceNumber = 1;
-    public void onUpdateBatchInput(final SettingsValues settingsValues,
-            final InputPointers batchPointers,
-            // TODO: remove these arguments
-            final KeyboardSwitcher keyboardSwitcher) {
-        if (settingsValues.mPhraseGestureEnabled) {
-            final SuggestedWordInfo candidate = mSuggestedWords.getAutoCommitCandidate();
-            // If these suggested words have been generated with out of date input pointers, then
-            // we skip auto-commit (see comments above on the mSequenceNumber member).
-            if (null != candidate
-                    && mSuggestedWords.mSequenceNumber >= mAutoCommitSequenceNumber) {
-                if (candidate.mSourceDict.shouldAutoCommit(candidate)) {
-                    final String[] commitParts = candidate.mWord.split(Constants.WORD_SEPARATOR, 2);
-                    batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
-                    promotePhantomSpace(settingsValues);
-                    mConnection.commitText(commitParts[0], 0);
-                    mSpaceState = SpaceState.PHANTOM;
-                    keyboardSwitcher.requestUpdatingShiftState(
-                            getCurrentAutoCapsState(settingsValues), getCurrentRecapitalizeState());
-                    mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode(
-                            settingsValues, keyboardSwitcher.getKeyboardShiftMode()));
-                    ++mAutoCommitSequenceNumber;
-                }
-            }
-        }
+    public void onUpdateBatchInput(final InputPointers batchPointers) {
         mInputLogicHandler.onUpdateBatchInput(batchPointers, mAutoCommitSequenceNumber);
     }
 
@@ -589,27 +537,25 @@
         ++mAutoCommitSequenceNumber;
     }
 
-    // TODO: remove this argument
     public void onCancelBatchInput(final LatinIME.UIHandler handler) {
         mInputLogicHandler.onCancelBatchInput();
         handler.showGesturePreviewAndSuggestionStrip(
-                SuggestedWords.EMPTY, true /* dismissGestureFloatingPreviewText */);
+                SuggestedWords.getEmptyInstance(), true /* dismissGestureFloatingPreviewText */);
     }
 
     // TODO: on the long term, this method should become private, but it will be difficult.
     // Especially, how do we deal with InputMethodService.onDisplayCompletions?
-    public void setSuggestedWords(final SuggestedWords suggestedWords,
-            final SettingsValues settingsValues, final LatinIME.UIHandler handler) {
-        if (SuggestedWords.EMPTY != suggestedWords) {
-            final String autoCorrection;
+    public void setSuggestedWords(final SuggestedWords suggestedWords) {
+        if (!suggestedWords.isEmpty()) {
+            final SuggestedWordInfo suggestedWordInfo;
             if (suggestedWords.mWillAutoCorrect) {
-                autoCorrection = suggestedWords.getWord(SuggestedWords.INDEX_OF_AUTO_CORRECTION);
+                suggestedWordInfo = suggestedWords.getInfo(SuggestedWords.INDEX_OF_AUTO_CORRECTION);
             } else {
                 // We can't use suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD)
                 // because it may differ from mWordComposer.mTypedWord.
-                autoCorrection = suggestedWords.mTypedWord;
+                suggestedWordInfo = suggestedWords.mTypedWordInfo;
             }
-            mWordComposer.setAutoCorrection(autoCorrection);
+            mWordComposer.setAutoCorrection(suggestedWordInfo);
         }
         mSuggestedWords = suggestedWords;
         final boolean newAutoCorrectionIndicator = suggestedWords.mWillAutoCorrect;
@@ -666,7 +612,6 @@
      * @param inputTransaction The transaction in progress.
      */
     private void handleFunctionalEvent(final Event event, final InputTransaction inputTransaction,
-            // TODO: remove these arguments
             final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
         switch (event.mKeyCode) {
             case Constants.CODE_DELETE:
@@ -683,7 +628,7 @@
                 break;
             case Constants.CODE_CAPSLOCK:
                 // Note: Changing keyboard to shift lock state is handled in
-                // {@link KeyboardSwitcher#onCodeInput(int)}.
+                // {@link KeyboardSwitcher#onEvent(Event)}.
                 break;
             case Constants.CODE_SYMBOL_SHIFT:
                 // Note: Calling back to the keyboard on the symbol Shift key is handled in
@@ -711,14 +656,13 @@
                 break;
             case Constants.CODE_EMOJI:
                 // Note: Switching emoji keyboard is being handled in
-                // {@link KeyboardState#onCodeInput(int,int)}.
+                // {@link KeyboardState#onEvent(Event,int)}.
                 break;
             case Constants.CODE_ALPHA_FROM_EMOJI:
                 // Note: Switching back from Emoji keyboard to the main keyboard is being
-                // handled in {@link KeyboardState#onCodeInput(int,int)}.
+                // handled in {@link KeyboardState#onEvent(Event,int)}.
                 break;
             case Constants.CODE_SHIFT_ENTER:
-                // TODO: remove this object
                 final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
                         event.mKeyCode, event.mX, event.mY, event.isKeyRepeat());
                 handleNonSpecialCharacterEvent(tmpEvent, inputTransaction, handler);
@@ -742,7 +686,6 @@
      */
     private void handleNonFunctionalEvent(final Event event,
             final InputTransaction inputTransaction,
-            // TODO: remove this argument
             final LatinIME.UIHandler handler) {
         inputTransaction.setDidAffectContents();
         switch (event.mCodePoint) {
@@ -788,18 +731,7 @@
      */
     private void handleNonSpecialCharacterEvent(final Event event,
             final InputTransaction inputTransaction,
-            // TODO: remove this argument
             final LatinIME.UIHandler handler) {
-        if (!mWordComposer.isComposingWord()) {
-            mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
-            // In case the "add to dictionary" hint was still displayed.
-            // TODO: Do we really need to check if we have composing text here?
-            if (mSuggestionStripViewAccessor.isShowingAddToDictionaryHint()) {
-                mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
-                mTextDecorator.reset();
-            }
-        }
-
         final int codePoint = event.mCodePoint;
         mSpaceState = SpaceState.NONE;
         if (inputTransaction.mSettingsValues.isWordSeparator(codePoint)
@@ -843,7 +775,7 @@
                 // Sanity check
                 throw new RuntimeException("Should not be composing here");
             }
-            promotePhantomSpace(settingsValues);
+            insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
         }
 
         if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
@@ -904,7 +836,6 @@
      * @param inputTransaction The transaction in progress.
      */
     private void handleSeparatorEvent(final Event event, final InputTransaction inputTransaction,
-            // TODO: remove this argument
             final LatinIME.UIHandler handler) {
         final int codePoint = event.mCodePoint;
         final SettingsValues settingsValues = inputTransaction.mSettingsValues;
@@ -954,12 +885,13 @@
         }
 
         if (needsPrecedingSpace) {
-            promotePhantomSpace(settingsValues);
+            insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
         }
 
         if (tryPerformDoubleSpacePeriod(event, inputTransaction)) {
             mSpaceState = SpaceState.DOUBLE;
             inputTransaction.setRequiresUpdateSuggestions();
+            StatsUtils.onDoubleSpacePeriod();
         } else if (swapWeakSpace && trySwapSwapperAndSpace(event, inputTransaction)) {
             mSpaceState = SpaceState.SWAP_PUNCTUATION;
             mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
@@ -1011,7 +943,6 @@
      * @param inputTransaction The transaction in progress.
      */
     private void handleBackspaceEvent(final Event event, final InputTransaction inputTransaction,
-            // TODO: remove this argument, put it into settingsValues
             final int currentKeyboardScriptId) {
         mSpaceState = SpaceState.NONE;
         mDeleteCount++;
@@ -1041,10 +972,13 @@
                 mWordComposer.reset();
                 mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
                 if (!TextUtils.isEmpty(rejectedSuggestion)) {
-                    mDictionaryFacilitator.removeWordFromPersonalizedDicts(rejectedSuggestion);
+                    unlearnWord(rejectedSuggestion, inputTransaction.mSettingsValues,
+                            Constants.EVENT_REJECTION);
                 }
+                StatsUtils.onBackspaceWordDelete(rejectedSuggestion.length());
             } else {
                 mWordComposer.applyProcessedEvent(event);
+                StatsUtils.onBackspacePressed(1);
             }
             if (mWordComposer.isComposingWord()) {
                 setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
@@ -1054,7 +988,24 @@
             inputTransaction.setRequiresUpdateSuggestions();
         } else {
             if (mLastComposedWord.canRevertCommit()) {
+                final String lastComposedWord = mLastComposedWord.mTypedWord;
                 revertCommit(inputTransaction, inputTransaction.mSettingsValues);
+                StatsUtils.onRevertAutoCorrect();
+                StatsUtils.onWordCommitUserTyped(lastComposedWord, mWordComposer.isBatchMode());
+                // Restart suggestions when backspacing into a reverted word. This is required for
+                // the final corrected word to be learned, as learning only occurs when suggestions
+                // are active.
+                //
+                // Note: restartSuggestionsOnWordTouchedByCursor is already called for normal
+                // (non-revert) backspace handling.
+                if (inputTransaction.mSettingsValues.isSuggestionsEnabledPerUserSettings()
+                        && inputTransaction.mSettingsValues.mSpacingAndPunctuations
+                                .mCurrentLanguageHasSpaces
+                        && !mConnection.isCursorFollowedByWordCharacter(
+                                inputTransaction.mSettingsValues.mSpacingAndPunctuations)) {
+                    restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
+                            false /* forStartInput */, currentKeyboardScriptId);
+                }
                 return;
             }
             if (mEnteredText != null && mConnection.sameAsTextBeforeCursor(mEnteredText)) {
@@ -1062,6 +1013,7 @@
                 // This is triggered on backspace after a key that inputs multiple characters,
                 // like the smiley key or the .com key.
                 mConnection.deleteSurroundingText(mEnteredText.length(), 0);
+                StatsUtils.onDeleteMultiCharInput(mEnteredText.length());
                 mEnteredText = null;
                 // If we have mEnteredText, then we know that mHasUncommittedTypedChars == false.
                 // In addition we know that spaceState is false, and that we should not be
@@ -1070,21 +1022,26 @@
             }
             if (SpaceState.DOUBLE == inputTransaction.mSpaceState) {
                 cancelDoubleSpacePeriodCountdown();
-                if (mConnection.revertDoubleSpacePeriod()) {
+                if (mConnection.revertDoubleSpacePeriod(
+                        inputTransaction.mSettingsValues.mSpacingAndPunctuations)) {
                     // No need to reset mSpaceState, it has already be done (that's why we
                     // receive it as a parameter)
                     inputTransaction.setRequiresUpdateSuggestions();
                     mWordComposer.setCapitalizedModeAtStartComposingTime(
                             WordComposer.CAPS_MODE_OFF);
+                    StatsUtils.onRevertDoubleSpacePeriod();
                     return;
                 }
             } else if (SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
                 if (mConnection.revertSwapPunctuation()) {
+                    StatsUtils.onRevertSwapPunctuation();
                     // Likewise
                     return;
                 }
             }
 
+            boolean hasUnlearnedWordBeingDeleted = false;
+
             // No cancelling of commit/double space/swap: we have a regular backspace.
             // We should backspace one char and restart suggestion if at the end of a word.
             if (mConnection.hasSelection()) {
@@ -1094,25 +1051,36 @@
                 mConnection.setSelection(mConnection.getExpectedSelectionEnd(),
                         mConnection.getExpectedSelectionEnd());
                 mConnection.deleteSurroundingText(numCharsDeleted, 0);
+                StatsUtils.onBackspaceSelectedText(numCharsDeleted);
             } else {
                 // There is no selection, just delete one character.
-                if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) {
-                    // This should never happen.
-                    Log.e(TAG, "Backspace when we don't know the selection position");
-                }
-                if (inputTransaction.mSettingsValues.isBeforeJellyBean() ||
-                        inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()) {
-                    // There are two possible reasons to send a key event: either the field has
+                if (inputTransaction.mSettingsValues.isBeforeJellyBean()
+                        || inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()
+                        || Constants.NOT_A_CURSOR_POSITION
+                                == mConnection.getExpectedSelectionEnd()) {
+                    // There are three possible reasons to send a key event: either the field has
                     // type TYPE_NULL, in which case the keyboard should send events, or we are
-                    // running in backward compatibility mode. Before Jelly bean, the keyboard
-                    // would simulate a hardware keyboard event on pressing enter or delete. This
-                    // is bad for many reasons (there are race conditions with commits) but some
-                    // applications are relying on this behavior so we continue to support it for
-                    // older apps, so we retain this behavior if the app has target SDK < JellyBean.
+                    // running in backward compatibility mode, or we don't know the cursor position.
+                    // Before Jelly bean, the keyboard would simulate a hardware keyboard event on
+                    // pressing enter or delete. This is bad for many reasons (there are race
+                    // conditions with commits) but some applications are relying on this behavior
+                    // so we continue to support it for older apps, so we retain this behavior if
+                    // the app has target SDK < JellyBean.
+                    // As for the case where we don't know the cursor position, it can happen
+                    // because of bugs in the framework. But the framework should know, so the next
+                    // best thing is to leave it to whatever it thinks is best.
                     sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
+                    int totalDeletedLength = 1;
                     if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
+                        // If this is an accelerated (i.e., double) deletion, then we need to
+                        // consider unlearning here because we may have already reached
+                        // the previous word, and will lose it after next deletion.
+                        hasUnlearnedWordBeingDeleted |= unlearnWordBeingDeleted(
+                                inputTransaction.mSettingsValues, currentKeyboardScriptId);
                         sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
+                        totalDeletedLength++;
                     }
+                    StatsUtils.onBackspacePressed(totalDeletedLength);
                 } else {
                     final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
                     if (codePointBeforeCursor == Constants.NOT_A_CODE) {
@@ -1123,34 +1091,83 @@
                         // catch it and have their broken interface react. If you need the keyboard
                         // to do this, you're doing it wrong -- please fix your app.
                         mConnection.deleteSurroundingText(1, 0);
+                        // TODO: Add a new StatsUtils method onBackspaceWhenNoText()
                         return;
                     }
                     final int lengthToDelete =
                             Character.isSupplementaryCodePoint(codePointBeforeCursor) ? 2 : 1;
                     mConnection.deleteSurroundingText(lengthToDelete, 0);
+                    int totalDeletedLength = lengthToDelete;
                     if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
+                        // If this is an accelerated (i.e., double) deletion, then we need to
+                        // consider unlearning here because we may have already reached
+                        // the previous word, and will lose it after next deletion.
+                        hasUnlearnedWordBeingDeleted |= unlearnWordBeingDeleted(
+                                inputTransaction.mSettingsValues, currentKeyboardScriptId);
                         final int codePointBeforeCursorToDeleteAgain =
                                 mConnection.getCodePointBeforeCursor();
                         if (codePointBeforeCursorToDeleteAgain != Constants.NOT_A_CODE) {
                             final int lengthToDeleteAgain = Character.isSupplementaryCodePoint(
                                     codePointBeforeCursorToDeleteAgain) ? 2 : 1;
                             mConnection.deleteSurroundingText(lengthToDeleteAgain, 0);
+                            totalDeletedLength += lengthToDeleteAgain;
                         }
                     }
+                    StatsUtils.onBackspacePressed(totalDeletedLength);
                 }
             }
-            if (inputTransaction.mSettingsValues
-                    .isSuggestionsEnabledPerUserSettings()
+            if (!hasUnlearnedWordBeingDeleted) {
+                // Consider unlearning the word being deleted (if we have not done so already).
+                unlearnWordBeingDeleted(
+                        inputTransaction.mSettingsValues, currentKeyboardScriptId);
+            }
+            if (inputTransaction.mSettingsValues.isSuggestionsEnabledPerUserSettings()
                     && inputTransaction.mSettingsValues.mSpacingAndPunctuations
                             .mCurrentLanguageHasSpaces
                     && !mConnection.isCursorFollowedByWordCharacter(
                             inputTransaction.mSettingsValues.mSpacingAndPunctuations)) {
                 restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
-                        true /* shouldIncludeResumedWordInSuggestions */, currentKeyboardScriptId);
+                        false /* forStartInput */, currentKeyboardScriptId);
             }
         }
     }
 
+    boolean unlearnWordBeingDeleted(
+            final SettingsValues settingsValues,final int currentKeyboardScriptId) {
+        // If we just started backspacing to delete a previous word (but have not
+        // entered the composing state yet), unlearn the word.
+        // TODO: Consider tracking whether or not this word was typed by the user.
+        if (!mConnection.hasSelection()
+                && settingsValues.isSuggestionsEnabledPerUserSettings()
+                && settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
+                && !mConnection.isCursorFollowedByWordCharacter(
+                        settingsValues.mSpacingAndPunctuations)) {
+            final TextRange range = mConnection.getWordRangeAtCursor(
+                    settingsValues.mSpacingAndPunctuations,
+                    currentKeyboardScriptId);
+            if (range == null) {
+                // Happens if we don't have an input connection at all.
+                return false;
+            }
+            final String wordBeingDeleted = range.mWord.toString();
+            if (!wordBeingDeleted.isEmpty()) {
+                unlearnWord(wordBeingDeleted, settingsValues,
+                        Constants.EVENT_BACKSPACE);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void unlearnWord(final String word, final SettingsValues settingsValues, final int eventType) {
+        final NgramContext ngramContext = mConnection.getNgramContextFromNthPreviousWord(
+            settingsValues.mSpacingAndPunctuations, 2);
+        final long timeStampInSeconds = TimeUnit.MILLISECONDS.toSeconds(
+            System.currentTimeMillis());
+        mDictionaryFacilitator.unlearnFromUserHistory(
+            word, ngramContext, timeStampInSeconds, eventType);
+    }
+
     /**
      * Handle a press on the language switch key (the "globe key")
      */
@@ -1253,7 +1270,9 @@
         if (null == lastTwo) return false;
         final int length = lastTwo.length();
         if (length < 2) return false;
-        if (lastTwo.charAt(length - 1) != Constants.CODE_SPACE) return false;
+        if (lastTwo.charAt(length - 1) != Constants.CODE_SPACE) {
+            return false;
+        }
         // We know there is a space in pos -1, and we have at least two chars. If we have only two
         // chars, isSurrogatePairs can't return true as charAt(1) is a space, so this is fine.
         final int firstCodePoint =
@@ -1336,7 +1355,7 @@
     }
 
     private void performAdditionToUserHistoryDictionary(final SettingsValues settingsValues,
-            final String suggestion, final PrevWordsInfo prevWordsInfo) {
+            final String suggestion, @Nonnull final NgramContext ngramContext) {
         // If correction is not enabled, we don't add words to the user history dictionary.
         // That's to avoid unintended additions in some sensitive fields, or fields that
         // expect to receive non-words.
@@ -1348,7 +1367,7 @@
         final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
                 System.currentTimeMillis());
         mDictionaryFacilitator.addToUserHistory(suggestion, wasAutoCapitalized,
-                prevWordsInfo, timeStampInSeconds, settingsValues.mBlockPotentiallyOffensive);
+                ngramContext, timeStampInSeconds, settingsValues.mBlockPotentiallyOffensive);
     }
 
     public void performUpdateSuggestionStripSync(final SettingsValues settingsValues,
@@ -1360,7 +1379,7 @@
                         + "requested!");
             }
             // Clear the suggestions strip.
-            mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.EMPTY);
+            mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.getEmptyInstance());
             return;
         }
 
@@ -1374,14 +1393,20 @@
                 new OnGetSuggestedWordsCallback() {
                     @Override
                     public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
-                        final String typedWord = mWordComposer.getTypedWord();
+                        final String typedWordString = mWordComposer.getTypedWord();
+                        final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(
+                                typedWordString, "" /* prevWordsContext */,
+                                SuggestedWordInfo.MAX_SCORE,
+                                SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
+                                SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+                                SuggestedWordInfo.NOT_A_CONFIDENCE);
                         // Show new suggestions if we have at least one. Otherwise keep the old
                         // suggestions with the new typed word. Exception: if the length of the
                         // typed word is <= 1 (after a deletion typically) we clear old suggestions.
-                        if (suggestedWords.size() > 1 || typedWord.length() <= 1) {
+                        if (suggestedWords.size() > 1 || typedWordString.length() <= 1) {
                             holder.set(suggestedWords);
                         } else {
-                            holder.set(retrieveOlderSuggestions(typedWord, mSuggestedWords));
+                            holder.set(retrieveOlderSuggestions(typedWordInfo, mSuggestedWords));
                         }
                     }
                 }
@@ -1400,12 +1425,12 @@
      * do nothing.
      *
      * @param settingsValues the current values of the settings.
-     * @param shouldIncludeResumedWordInSuggestions whether to include the word on which we resume
-     *   suggestions in the suggestion list.
+     * @param forStartInput whether we're doing this in answer to starting the input (as opposed
+     *   to a cursor move, for example). In ICS, there is a platform bug that we need to work
+     *   around only when we come here at input start time.
      */
-    // TODO: make this private.
     public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues,
-            final boolean shouldIncludeResumedWordInSuggestions,
+            final boolean forStartInput,
             // TODO: remove this argument, put it into settingsValues
             final int currentKeyboardScriptId) {
         // HACK: We may want to special-case some apps that exhibit bad behavior in case of
@@ -1452,15 +1477,14 @@
         final int numberOfCharsInWordBeforeCursor = range.getNumberOfCharsInWordBeforeCursor();
         if (numberOfCharsInWordBeforeCursor > expectedCursorPosition) return;
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
-        final String typedWord = range.mWord.toString();
-        if (shouldIncludeResumedWordInSuggestions) {
-            suggestions.add(new SuggestedWordInfo(typedWord,
-                    SuggestedWords.MAX_SUGGESTIONS + 1,
-                    SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
-                    SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
-                    SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
-        }
-        if (!isResumableWord(settingsValues, typedWord)) {
+        final String typedWordString = range.mWord.toString();
+        final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString,
+                "" /* prevWordsContext */, SuggestedWords.MAX_SUGGESTIONS + 1,
+                SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
+                SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+                SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
+        suggestions.add(typedWordInfo);
+        if (!isResumableWord(settingsValues, typedWordString)) {
             mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
             return;
         }
@@ -1468,9 +1492,9 @@
         for (final SuggestionSpan span : range.getSuggestionSpansAtWord()) {
             for (final String s : span.getSuggestions()) {
                 ++i;
-                if (!TextUtils.equals(s, typedWord)) {
+                if (!TextUtils.equals(s, typedWordString)) {
                     suggestions.add(new SuggestedWordInfo(s,
-                            SuggestedWords.MAX_SUGGESTIONS - i,
+                            "" /* prevWordsContext */, SuggestedWords.MAX_SUGGESTIONS - i,
                             SuggestedWordInfo.KIND_RESUMED, Dictionary.DICTIONARY_RESUMED,
                             SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                             SuggestedWordInfo.NOT_A_CONFIDENCE
@@ -1478,47 +1502,25 @@
                 }
             }
         }
-        final int[] codePoints = StringUtils.toCodePointArray(typedWord);
-        // We want the previous word for suggestion. If we have chars in the word
-        // before the cursor, then we want the word before that, hence 2; otherwise,
-        // we want the word immediately before the cursor, hence 1.
-        final PrevWordsInfo prevWordsInfo = getPrevWordsInfoFromNthPreviousWordForSuggestion(
-                settingsValues.mSpacingAndPunctuations,
-                0 == numberOfCharsInWordBeforeCursor ? 1 : 2);
+        final int[] codePoints = StringUtils.toCodePointArray(typedWordString);
         mWordComposer.setComposingWord(codePoints,
                 mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
         mWordComposer.setCursorPositionWithinWord(
-                typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor));
-        mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
+        typedWordString.codePointCount(0, numberOfCharsInWordBeforeCursor));
+        if (forStartInput) {
+            mConnection.maybeMoveTheCursorAroundAndRestoreToWorkaroundABug();
+        }
         mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
                 expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
-        if (suggestions.size() <= (shouldIncludeResumedWordInSuggestions ? 1 : 0)) {
+        if (suggestions.size() <= 1) {
             // If there weren't any suggestion spans on this word, suggestions#size() will be 1
             // if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
             // have no useful suggestions, so we will try to compute some for it instead.
             mInputLogicHandler.getSuggestedWords(Suggest.SESSION_ID_TYPING,
                     SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
                         @Override
-                        public void onGetSuggestedWords(
-                                final SuggestedWords suggestedWordsIncludingTypedWord) {
-                            final SuggestedWords suggestedWords;
-                            if (suggestedWordsIncludingTypedWord.size() > 1
-                                    && !shouldIncludeResumedWordInSuggestions) {
-                                // We were able to compute new suggestions for this word.
-                                // Remove the typed word, since we don't want to display it in this
-                                // case. The #getSuggestedWordsExcludingTypedWordForRecorrection()
-                                // method sets willAutoCorrect to false.
-                                suggestedWords = suggestedWordsIncludingTypedWord
-                                        .getSuggestedWordsExcludingTypedWordForRecorrection();
-                            } else {
-                                // No saved suggestions, and we were unable to compute any good one
-                                // either. Rather than displaying an empty suggestion strip, we'll
-                                // display the original word alone in the middle.
-                                // Since there is only one word, willAutoCorrect is false.
-                                suggestedWords = suggestedWordsIncludingTypedWord;
-                            }
-                            mIsAutoCorrectionIndicatorOn = false;
-                            mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+                        public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
+                            doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
                         }});
         } else {
             // We found suggestion spans in the word. We'll create the SuggestedWords out of
@@ -1526,14 +1528,18 @@
             // color of the word in the suggestion strip changes according to this parameter,
             // and false gives the correct color.
             final SuggestedWords suggestedWords = new SuggestedWords(suggestions,
-                    null /* rawSuggestions */, typedWord, false /* typedWordValid */,
+                    null /* rawSuggestions */, typedWordInfo, false /* typedWordValid */,
                     false /* willAutoCorrect */, false /* isObsoleteSuggestions */,
                     SuggestedWords.INPUT_STYLE_RECORRECTION, SuggestedWords.NOT_A_SEQUENCE_NUMBER);
-            mIsAutoCorrectionIndicatorOn = false;
-            mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+            doShowSuggestionsAndClearAutoCorrectionIndicator(suggestedWords);
         }
     }
 
+    void doShowSuggestionsAndClearAutoCorrectionIndicator(final SuggestedWords suggestedWords) {
+        mIsAutoCorrectionIndicatorOn = false;
+        mLatinIME.mHandler.showSuggestionStrip(suggestedWords);
+    }
+
     /**
      * Reverts a previous commit with auto-correction.
      *
@@ -1551,6 +1557,10 @@
         final String committedWordString = committedWord.toString();
         final int cancelLength = committedWord.length();
         final String separatorString = mLastComposedWord.mSeparatorString;
+        // If our separator is a space, we won't actually commit it,
+        // but set the space state to PHANTOM so that a space will be inserted
+        // on the next keypress
+        final boolean usePhantomSpace = separatorString.equals(Constants.STRING_SPACE);
         // We want java chars, not codepoints for the following.
         final int separatorLength = separatorString.length();
         // TODO: should we check our saved separator against the actual contents of the text view?
@@ -1569,9 +1579,11 @@
         }
         mConnection.deleteSurroundingText(deleteLength, 0);
         if (!TextUtils.isEmpty(committedWord)) {
-            mDictionaryFacilitator.removeWordFromPersonalizedDicts(committedWordString);
+            unlearnWord(committedWordString, inputTransaction.mSettingsValues,
+                    Constants.EVENT_REVERT);
         }
-        final String stringToCommit = originallyTypedWord + separatorString;
+        final String stringToCommit = originallyTypedWord +
+                (usePhantomSpace ? "" : separatorString);
         final SpannableString textToCommit = new SpannableString(stringToCommit);
         if (committedWord instanceof SpannableString) {
             final SpannableString committedWordWithSuggestionSpans = (SpannableString)committedWord;
@@ -1583,15 +1595,11 @@
             // First, add the committed word to the list of suggestions.
             suggestions.add(committedWordString);
             for (final Object span : spans) {
-                // If this is a suggestion span, we check that the locale is the right one, and
-                // that the word is not the committed word. That should mostly be the case.
+                // If this is a suggestion span, we check that the word is not the committed word.
+                // That should mostly be the case.
                 // Given this, we add it to the list of suggestions, otherwise we discard it.
                 if (span instanceof SuggestionSpan) {
                     final SuggestionSpan suggestionSpan = (SuggestionSpan)span;
-                    if (!suggestionSpan.getLocale().equals(
-                            inputTransaction.mSettingsValues.mLocale.toString())) {
-                        continue;
-                    }
                     for (final String suggestion : suggestionSpan.getSuggestions()) {
                         if (!suggestion.equals(committedWordString)) {
                             suggestions.add(suggestion);
@@ -1604,24 +1612,17 @@
                 }
             }
             // Add the suggestion list to the list of suggestions.
-            textToCommit.setSpan(new SuggestionSpan(inputTransaction.mSettingsValues.mLocale,
-                    suggestions.toArray(new String[suggestions.size()]), 0 /* flags */),
+            textToCommit.setSpan(new SuggestionSpan(mLatinIME /* context */,
+                    inputTransaction.mSettingsValues.mLocale,
+                    suggestions.toArray(new String[suggestions.size()]), 0 /* flags */,
+                    null /* notificationTargetClass */),
                     0 /* start */, lastCharIndex /* end */, 0 /* flags */);
         }
 
-        final boolean shouldShowAddToDictionaryForTypedWord =
-                shouldShowAddToDictionaryForTypedWord(mLastComposedWord, settingsValues);
-
         if (inputTransaction.mSettingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
-            // For languages with spaces, we revert to the typed string, but the cursor is still
-            // after the separator so we don't resume suggestions. If the user wants to correct
-            // the word, they have to press backspace again.
-            if (shouldShowAddToDictionaryForTypedWord) {
-                mConnection.commitTextWithBackgroundColor(textToCommit, 1,
-                        settingsValues.mTextHighlightColorForAddToDictionaryIndicator,
-                        originallyTypedWordString.length());
-            } else {
-                mConnection.commitText(textToCommit, 1);
+            mConnection.commitText(textToCommit, 1);
+            if (usePhantomSpace) {
+                mSpaceState = SpaceState.PHANTOM;
             }
         } else {
             // For languages without spaces, we revert the typed string but the cursor is flush
@@ -1629,32 +1630,13 @@
             final int[] codePoints = StringUtils.toCodePointArray(stringToCommit);
             mWordComposer.setComposingWord(codePoints,
                     mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
-            if (shouldShowAddToDictionaryForTypedWord) {
-                setComposingTextInternalWithBackgroundColor(textToCommit, 1,
-                        settingsValues.mTextHighlightColorForAddToDictionaryIndicator,
-                        originallyTypedWordString.length());
-            } else {
-                setComposingTextInternal(textToCommit, 1);
-            }
+            setComposingTextInternal(textToCommit, 1);
         }
         // Don't restart suggestion yet. We'll restart if the user deletes the separator.
         mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
 
-        if (shouldShowAddToDictionaryForTypedWord) {
-            // Due to the API limitation as of L, we cannot reliably retrieve the reverted text
-            // when the separator causes line breaking. Until this API limitation is addressed in
-            // the framework, show the indicator only when the separator doesn't contain
-            // line-breaking characters.
-            if (!StringUtils.hasLineBreakCharacter(separatorString)) {
-                mTextDecorator.showAddToDictionaryIndicator(originallyTypedWordString,
-                        mConnection.getExpectedSelectionStart(),
-                        mConnection.getExpectedSelectionEnd());
-            }
-            mSuggestionStripViewAccessor.showAddToDictionaryHint(originallyTypedWordString);
-        } else {
-            // We have a separator between the word and the cursor: we should show predictions.
-            inputTransaction.setRequiresUpdateSuggestions();
-        }
+        // We have a separator between the word and the cursor: we should show predictions.
+        inputTransaction.setRequiresUpdateSuggestions();
     }
 
     /**
@@ -1720,26 +1702,25 @@
     }
 
     /**
-     * Get information fo previous words from the nth previous word before the cursor as context
+     * Get n-gram context from the nth previous word before the cursor as context
      * for the suggestion process.
      * @param spacingAndPunctuations the current spacing and punctuations settings.
      * @param nthPreviousWord reverse index of the word to get (1-indexed)
      * @return the information of previous words
      */
-    // TODO: Make this private
-    public PrevWordsInfo getPrevWordsInfoFromNthPreviousWordForSuggestion(
+    public NgramContext getNgramContextFromNthPreviousWordForSuggestion(
             final SpacingAndPunctuations spacingAndPunctuations, final int nthPreviousWord) {
         if (spacingAndPunctuations.mCurrentLanguageHasSpaces) {
             // If we are typing in a language with spaces we can just look up the previous
             // word information from textview.
-            return mConnection.getPrevWordsInfoFromNthPreviousWord(
+            return mConnection.getNgramContextFromNthPreviousWord(
                     spacingAndPunctuations, nthPreviousWord);
-        } else {
-            return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ?
-                    PrevWordsInfo.BEGINNING_OF_SENTENCE :
-                            new PrevWordsInfo(new PrevWordsInfo.WordInfo(
-                                    mLastComposedWord.mCommittedWord.toString()));
         }
+        if (LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord) {
+            return NgramContext.BEGINNING_OF_SENTENCE;
+        }
+        return new NgramContext(new NgramContext.WordInfo(
+                mLastComposedWord.mCommittedWord.toString()));
     }
 
     /**
@@ -1792,9 +1773,8 @@
         // If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT.
         if (Constants.CODE_PERIOD == codePointBeforeCursor) {
             return text.substring(1);
-        } else {
-            return text;
         }
+        return text;
     }
 
     /**
@@ -1845,21 +1825,21 @@
      * Make a {@link com.android.inputmethod.latin.SuggestedWords} object containing a typed word
      * and obsolete suggestions.
      * See {@link com.android.inputmethod.latin.SuggestedWords#getTypedWordAndPreviousSuggestions(
-     *      String, com.android.inputmethod.latin.SuggestedWords)}.
-     * @param typedWord The typed word as a string.
+     *      SuggestedWordInfo, com.android.inputmethod.latin.SuggestedWords)}.
+     * @param typedWordInfo The typed word as a SuggestedWordInfo.
      * @param previousSuggestedWords The previously suggested words.
      * @return Obsolete suggestions with the newly typed word.
      */
-    private SuggestedWords retrieveOlderSuggestions(final String typedWord,
+    static SuggestedWords retrieveOlderSuggestions(final SuggestedWordInfo typedWordInfo,
             final SuggestedWords previousSuggestedWords) {
-        final SuggestedWords oldSuggestedWords =
-                previousSuggestedWords.isPunctuationSuggestions() ? SuggestedWords.EMPTY
-                        : previousSuggestedWords;
+        final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions()
+                ? SuggestedWords.getEmptyInstance() : previousSuggestedWords;
         final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
-                SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords);
+                SuggestedWords.getTypedWordAndPreviousSuggestions(typedWordInfo, oldSuggestedWords);
         return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */,
-                false /* typedWordValid */, false /* hasAutoCorrectionCandidate */,
-                true /* isObsoleteSuggestions */, oldSuggestedWords.mInputStyle);
+                typedWordInfo, false /* typedWordValid */, false /* hasAutoCorrectionCandidate */,
+                true /* isObsoleteSuggestions */, oldSuggestedWords.mInputStyle,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
     }
 
     /**
@@ -1936,14 +1916,14 @@
     }
 
     /**
-     * Promote a phantom space to an actual space.
+     * Insert an automatic space, if the options allow it.
      *
-     * This essentially inserts a space, and that's it. It just checks the options and the text
-     * before the cursor are appropriate before doing it.
+     * This checks the options and the text before the cursor are appropriate before inserting
+     * an automatic space.
      *
      * @param settingsValues the current values of the settings.
      */
-    private void promotePhantomSpace(final SettingsValues settingsValues) {
+    private void insertAutomaticSpaceIfOptionsAndTextAllow(final SettingsValues settingsValues) {
         if (settingsValues.shouldInsertSpacesAutomatically()
                 && settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
                 && !mConnection.textBeforeCursorLooksLikeURL()) {
@@ -1957,36 +1937,17 @@
      * @param suggestedWords suggestedWords to use.
      */
     public void onUpdateTailBatchInputCompleted(final SettingsValues settingsValues,
-            final SuggestedWords suggestedWords,
-            // TODO: remove this argument
-            final KeyboardSwitcher keyboardSwitcher) {
+            final SuggestedWords suggestedWords, final KeyboardSwitcher keyboardSwitcher) {
         final String batchInputText = suggestedWords.isEmpty() ? null : suggestedWords.getWord(0);
         if (TextUtils.isEmpty(batchInputText)) {
             return;
         }
         mConnection.beginBatchEdit();
         if (SpaceState.PHANTOM == mSpaceState) {
-            promotePhantomSpace(settingsValues);
+            insertAutomaticSpaceIfOptionsAndTextAllow(settingsValues);
         }
-        final SuggestedWordInfo autoCommitCandidate = mSuggestedWords.getAutoCommitCandidate();
-        // Commit except the last word for phrase gesture if the top suggestion is eligible for auto
-        // commit.
-        if (settingsValues.mPhraseGestureEnabled && null != autoCommitCandidate) {
-            // Find the last space
-            final int indexOfLastSpace = batchInputText.lastIndexOf(Constants.CODE_SPACE) + 1;
-            if (0 != indexOfLastSpace) {
-                mConnection.commitText(batchInputText.substring(0, indexOfLastSpace), 1);
-                final SuggestedWords suggestedWordsForLastWordOfPhraseGesture =
-                        suggestedWords.getSuggestedWordsForLastWordOfPhraseGesture();
-                mLatinIME.showSuggestionStrip(suggestedWordsForLastWordOfPhraseGesture);
-            }
-            final String lastWord = batchInputText.substring(indexOfLastSpace);
-            mWordComposer.setBatchInputWord(lastWord);
-            setComposingTextInternal(lastWord, 1);
-        } else {
-            mWordComposer.setBatchInputWord(batchInputText);
-            setComposingTextInternal(batchInputText, 1);
-        }
+        mWordComposer.setBatchInputWord(batchInputText);
+        setComposingTextInternal(batchInputText, 1);
         mConnection.endBatchEdit();
         // Space state must be updated before calling updateShiftState
         mSpaceState = SpaceState.PHANTOM;
@@ -2009,13 +1970,14 @@
      * @param settingsValues the current values of the settings.
      * @param separatorString the separator that's causing the commit, or NOT_A_SEPARATOR if none.
      */
-    // TODO: Make this private
     public void commitTyped(final SettingsValues settingsValues, final String separatorString) {
         if (!mWordComposer.isComposingWord()) return;
         final String typedWord = mWordComposer.getTypedWord();
         if (typedWord.length() > 0) {
+            final boolean isBatchMode = mWordComposer.isBatchMode();
             commitChosenWord(settingsValues, typedWord,
                     LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, separatorString);
+            StatsUtils.onWordCommitUserTyped(typedWord, isBatchMode);
         }
     }
 
@@ -2036,9 +1998,7 @@
      * @param separator the separator that's causing the commit to happen.
      */
     private void commitCurrentAutoCorrection(final SettingsValues settingsValues,
-            final String separator,
-            // TODO: Remove this argument.
-            final LatinIME.UIHandler handler) {
+            final String separator, final LatinIME.UIHandler handler) {
         // Complete any pending suggestions query first
         if (handler.hasPendingUpdateSuggestions()) {
             handler.cancelUpdateSuggestionStrip();
@@ -2052,18 +2012,19 @@
             // INPUT_STYLE_TYPING.
             performUpdateSuggestionStripSync(settingsValues, SuggestedWords.INPUT_STYLE_TYPING);
         }
-        final String typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull();
+        final SuggestedWordInfo autoCorrectionOrNull = mWordComposer.getAutoCorrectionOrNull();
         final String typedWord = mWordComposer.getTypedWord();
-        final String autoCorrection = (typedAutoCorrection != null)
-                ? typedAutoCorrection : typedWord;
-        if (autoCorrection != null) {
+        final String stringToCommit = (autoCorrectionOrNull != null)
+                ? autoCorrectionOrNull.mWord : typedWord;
+        if (stringToCommit != null) {
             if (TextUtils.isEmpty(typedWord)) {
                 throw new RuntimeException("We have an auto-correction but the typed word "
                         + "is empty? Impossible! I must commit suicide.");
             }
-            commitChosenWord(settingsValues, autoCorrection,
+            final boolean isBatchMode = mWordComposer.isBatchMode();
+            commitChosenWord(settingsValues, stringToCommit,
                     LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separator);
-            if (!typedWord.equals(autoCorrection)) {
+            if (!typedWord.equals(stringToCommit)) {
                 // This will make the correction flash for a short while as a visual clue
                 // to the user that auto-correction happened. It has no other effect; in particular
                 // note that this won't affect the text inside the text field AT ALL: it only makes
@@ -2071,8 +2032,16 @@
                 // of the auto-correction flash. At this moment, the "typedWord" argument is
                 // ignored by TextView.
                 mConnection.commitCorrection(new CorrectionInfo(
-                        mConnection.getExpectedSelectionEnd() - autoCorrection.length(),
-                        typedWord, autoCorrection));
+                        mConnection.getExpectedSelectionEnd() - stringToCommit.length(),
+                        typedWord, stringToCommit));
+                String prevWordsContext = (autoCorrectionOrNull != null)
+                        ? autoCorrectionOrNull.mPrevWordsContext
+                        : "";
+                StatsUtils.onAutoCorrection(typedWord, stringToCommit, isBatchMode,
+                        mDictionaryFacilitator, prevWordsContext);
+                StatsUtils.onWordCommitAutoCorrect(stringToCommit, isBatchMode);
+            } else {
+                StatsUtils.onWordCommitUserTyped(stringToCommit, isBatchMode);
             }
         }
     }
@@ -2091,20 +2060,20 @@
         final CharSequence chosenWordWithSuggestions =
                 SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
                         suggestedWords);
-        // When we are composing word, get previous words information from the 2nd previous word
-        // because the 1st previous word is the word to be committed. Otherwise get previous words
-        // information from the 1st previous word.
-        final PrevWordsInfo prevWordsInfo = mConnection.getPrevWordsInfoFromNthPreviousWord(
+        // When we are composing word, get n-gram context from the 2nd previous word because the
+        // 1st previous word is the word to be committed. Otherwise get n-gram context from the 1st
+        // previous word.
+        final NgramContext ngramContext = mConnection.getNgramContextFromNthPreviousWord(
                 settingsValues.mSpacingAndPunctuations, mWordComposer.isComposingWord() ? 2 : 1);
         mConnection.commitText(chosenWordWithSuggestions, 1);
         // Add the word to the user history dictionary
-        performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWordsInfo);
+        performAdditionToUserHistoryDictionary(settingsValues, chosenWord, ngramContext);
         // TODO: figure out here if this is an auto-correct or if the best word is actually
         // what user typed. Note: currently this is done much later in
         // LastComposedWord#didCommitTypedWord by string equality of the remembered
         // strings.
         mLastComposedWord = mWordComposer.commitWord(commitType,
-                chosenWordWithSuggestions, separatorString, prevWordsInfo);
+                chosenWordWithSuggestions, separatorString, ngramContext);
     }
 
     /**
@@ -2118,11 +2087,8 @@
      * @param remainingTries How many times we may try again before giving up.
      * @return whether true if the caches were successfully reset, false otherwise.
      */
-    // TODO: make this private
     public boolean retryResetCachesAndReturnSuccess(final boolean tryResumeSuggestions,
-            final int remainingTries,
-            // TODO: remove these arguments
-            final LatinIME.UIHandler handler) {
+            final int remainingTries, final LatinIME.UIHandler handler) {
         final boolean shouldFinishComposition = mConnection.hasSelection()
                 || !mConnection.isCursorPositionKnown();
         if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(
@@ -2137,30 +2103,25 @@
         }
         mConnection.tryFixLyingCursorPosition();
         if (tryResumeSuggestions) {
-            // This is triggered when starting input anew, so we want to include the resumed
-            // word in suggestions.
-            handler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
-                    true /* shouldDelay */);
+            handler.postResumeSuggestions(true /* shouldDelay */);
         }
         return true;
     }
 
     public void getSuggestedWords(final SettingsValues settingsValues,
-            final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle,
+            final Keyboard keyboard, final int keyboardShiftMode, final int inputStyle,
             final int sequenceNumber, final OnGetSuggestedWordsCallback callback) {
         mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions(
                 getActualCapsMode(settingsValues, keyboardShiftMode));
         mSuggest.getSuggestedWords(mWordComposer,
-                getPrevWordsInfoFromNthPreviousWordForSuggestion(
+                getNgramContextFromNthPreviousWordForSuggestion(
                         settingsValues.mSpacingAndPunctuations,
                         // Get the word on which we should search the bigrams. If we are composing
                         // a word, it's whatever is *before* the half-committed word in the buffer,
                         // hence 2; if we aren't, we should just skip whitespace if any, so 1.
                         mWordComposer.isComposingWord() ? 2 : 1),
-                proximityInfo,
-                new SettingsValuesForSuggestion(settingsValues.mBlockPotentiallyOffensive,
-                        settingsValues.mPhraseGestureEnabled,
-                        settingsValues.mAdditionalFeaturesSettingValues),
+                keyboard,
+                new SettingsValuesForSuggestion(settingsValues.mBlockPotentiallyOffensive),
                 settingsValues.mAutoCorrectionEnabledPerUserSettings,
                 inputStyle, sequenceNumber, callback);
     }
@@ -2171,7 +2132,7 @@
      *
      * <p>Currently using this method is optional and you can still directly call
      * {@link RichInputConnection#setComposingText(CharSequence, int)}, but it is recommended to
-     * use this method whenever possible to optimize the behavior of {@link TextDecorator}.<p>
+     * use this method whenever possible.<p>
      * <p>TODO: Should we move this mechanism to {@link RichInputConnection}?</p>
      *
      * @param newComposingText the composing text to be set
@@ -2216,70 +2177,44 @@
         mConnection.setComposingText(composingTextToBeSet, newCursorPosition);
     }
 
-    //////////////////////////////////////////////////////////////////////////////////////////////
-    // Following methods are tentatively placed in this class for the integration with
-    // TextDecorator.
-    // TODO: Decouple things that are not related to the input logic.
-    //////////////////////////////////////////////////////////////////////////////////////////////
-
     /**
-     * Sets the UI operator for {@link TextDecorator}.
-     * @param uiOperator the UI operator which should be associated with {@link TextDecorator}.
+     * Gets an object allowing private IME commands to be sent to the
+     * underlying editor.
+     * @return An object for sending private commands to the underlying editor.
      */
-    public void setTextDecoratorUi(final TextDecoratorUiOperator uiOperator) {
-        mTextDecorator.setUiOperator(uiOperator);
+    public PrivateCommandPerformer getPrivateCommandPerformer() {
+        return mConnection;
     }
 
     /**
-     * Must be called from {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is
-     * called.
-     * @param info The wrapper object with which we can access cursor/anchor info.
+     * Gets the expected index of the first char of the composing span within the editor's text.
+     * Returns a negative value in case there appears to be no valid composing span.
+     *
+     * @see #getComposingLength()
+     * @see RichInputConnection#hasSelection()
+     * @see RichInputConnection#isCursorPositionKnown()
+     * @see RichInputConnection#getExpectedSelectionStart()
+     * @see RichInputConnection#getExpectedSelectionEnd()
+     * @return The expected index in Java chars of the first char of the composing span.
      */
-    public void onUpdateCursorAnchorInfo(final CursorAnchorInfoCompatWrapper info) {
-        mTextDecorator.onUpdateCursorAnchorInfo(info);
+    // TODO: try and see if we can get rid of this method. Ideally the users of this class should
+    // never need to know this.
+    public int getComposingStart() {
+        if (!mConnection.isCursorPositionKnown() || mConnection.hasSelection()) {
+            return -1;
+        }
+        return mConnection.getExpectedSelectionStart() - mWordComposer.size();
     }
 
     /**
-     * Must be called when {@link InputMethodService#updateFullscreenMode} is called.
-     * @param isFullscreen {@code true} if the input method is in full-screen mode.
+     * Gets the expected length in Java chars of the composing span.
+     * May be 0 if there is no valid composing span.
+     * @see #getComposingStart()
+     * @return The expected length of the composing span.
      */
-    public void onUpdateFullscreenMode(final boolean isFullscreen) {
-        mTextDecorator.notifyFullScreenMode(isFullscreen);
-    }
-
-    /**
-     * Must be called from {@link LatinIME#addWordToUserDictionary(String)}.
-     */
-    public void onAddWordToUserDictionary() {
-        mConnection.removeBackgroundColorFromHighlightedTextIfNecessary();
-        mTextDecorator.reset();
-    }
-
-    /**
-     * Returns whether the add to dictionary indicator should be shown or not.
-     * @param lastComposedWord the last composed word information.
-     * @param settingsValues the current settings value.
-     * @return {@code true} if the commit indicator should be shown.
-     */
-    private boolean shouldShowAddToDictionaryForTypedWord(final LastComposedWord lastComposedWord,
-            final SettingsValues settingsValues) {
-        if (!mConnection.isCursorAnchorInfoMonitorEnabled()) {
-            // We cannot help in this case because we are heavily relying on this new API.
-            return false;
-        }
-        if (!settingsValues.mShouldShowUiToAcceptTypedWord) {
-            return false;
-        }
-        if (TextUtils.isEmpty(lastComposedWord.mTypedWord)) {
-            return false;
-        }
-        if (TextUtils.equals(lastComposedWord.mTypedWord, lastComposedWord.mCommittedWord)) {
-            return false;
-        }
-        if (!mDictionaryFacilitator.isUserDictionaryEnabled()) {
-            return false;
-        }
-        return !mDictionaryFacilitator.isValidWord(lastComposedWord.mTypedWord,
-                true /* ignoreCase */);
+    // TODO: try and see if we can get rid of this method. Ideally the users of this class should
+    // never need to know this.
+    public int getComposingLength() {
+        return mWordComposer.size();
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index c6f83d0..ddc4ad9 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -21,11 +21,10 @@
 import android.os.Message;
 
 import com.android.inputmethod.compat.LooperCompatUtils;
-import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LatinIME;
-import com.android.inputmethod.latin.Suggest;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
+import com.android.inputmethod.latin.common.InputPointers;
 
 /**
  * A helper to manage deferred tasks for the input logic.
@@ -62,7 +61,7 @@
                 final OnGetSuggestedWordsCallback callback) {}
     };
 
-    private InputLogicHandler() {
+    InputLogicHandler() {
         mNonUIThreadHandler = null;
         mLatinIME = null;
         mInputLogic = null;
@@ -134,30 +133,38 @@
                 return;
             }
             mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
+            final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
+                @Override
+                public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
+                    showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
+                }
+            };
             getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
-                    : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber,
-                    new OnGetSuggestedWordsCallback() {
-                        @Override
-                        public void onGetSuggestedWords(SuggestedWords suggestedWords) {
-                            // We're now inside the callback. This always runs on the Non-UI thread,
-                            // no matter what thread updateBatchInput was originally called on.
-                            if (suggestedWords.isEmpty()) {
-                                // Use old suggestions if we don't have any new ones.
-                                // Previous suggestions are found in InputLogic#mSuggestedWords.
-                                // Since these are the most recent ones and we just recomputed
-                                // new ones to update them, then the previous ones are there.
-                                suggestedWords = mInputLogic.mSuggestedWords;
-                            }
-                            mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWords,
-                                    isTailBatchInput /* dismissGestureFloatingPreviewText */);
-                            if (isTailBatchInput) {
-                                mInBatchInput = false;
-                                // The following call schedules onEndBatchInputInternal
-                                // to be called on the UI thread.
-                                mLatinIME.mHandler.showTailBatchInputResult(suggestedWords);
-                            }
-                        }
-                    });
+                    : SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
+        }
+    }
+
+    void showGestureSuggestionsWithPreviewVisuals(final SuggestedWords suggestedWordsForBatchInput,
+            final boolean isTailBatchInput) {
+        final SuggestedWords suggestedWordsToShowSuggestions;
+        // We're now inside the callback. This always runs on the Non-UI thread,
+        // no matter what thread updateBatchInput was originally called on.
+        if (suggestedWordsForBatchInput.isEmpty()) {
+            // Use old suggestions if we don't have any new ones.
+            // Previous suggestions are found in InputLogic#mSuggestedWords.
+            // Since these are the most recent ones and we just recomputed
+            // new ones to update them, then the previous ones are there.
+            suggestedWordsToShowSuggestions = mInputLogic.mSuggestedWords;
+        } else {
+            suggestedWordsToShowSuggestions = suggestedWordsForBatchInput;
+        }
+        mLatinIME.mHandler.showGesturePreviewAndSuggestionStrip(suggestedWordsToShowSuggestions,
+                isTailBatchInput /* dismissGestureFloatingPreviewText */);
+        if (isTailBatchInput) {
+            mInBatchInput = false;
+            // The following call schedules onEndBatchInputInternal
+            // to be called on the UI thread.
+            mLatinIME.mHandler.showTailBatchInputResult(suggestedWordsToShowSuggestions);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java b/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java
new file mode 100644
index 0000000..42eaa9c
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.inputlogic;
+
+import android.os.Bundle;
+
+/**
+ * Provides an interface matching
+ * {@link android.view.inputmethod.InputConnection#performPrivateCommand(String,Bundle)}.
+ */
+public interface PrivateCommandPerformer {
+    /**
+     * API to send private commands from an input method to its connected
+     * editor. This can be used to provide domain-specific features that are
+     * only known between certain input methods and their clients.
+     *
+     * @param action Name of the command to be performed. This must be a scoped
+     *            name, i.e. prefixed with a package name you own, so that
+     *            different developers will not create conflicting commands.
+     * @param data Any data to include with the command.
+     * @return true if the command was sent (regardless of whether the
+     * associated editor understood it), false if the input connection is no
+     * longer valid.
+     */
+    boolean performPrivateCommand(String action, Bundle data);
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java
index df447fd..4d253b0 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DictionaryHeader.java
@@ -19,13 +19,24 @@
 import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * Class representing dictionary header.
  */
 public final class DictionaryHeader {
     public final int mBodyOffset;
+    @Nonnull
     public final DictionaryOptions mDictionaryOptions;
+    @Nonnull
     public final FormatOptions mFormatOptions;
+    @Nonnull
+    public final String mLocaleString;
+    @Nonnull
+    public final String mVersionString;
+    @Nonnull
+    public final String mIdString;
 
     // Note that these are corresponding definitions in native code in latinime::HeaderPolicy
     // and latinime::HeaderReadWriteUtils.
@@ -38,49 +49,40 @@
     public static final String DICTIONARY_DATE_KEY = "date";
     public static final String HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO";
     public static final String USES_FORGETTING_CURVE_KEY = "USES_FORGETTING_CURVE";
-    public static final String FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY =
-            "FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP";
     public static final String FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY =
             "FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID";
-    public static final String FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY =
-            "FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS";
-    public static final String MAX_UNIGRAM_COUNT_KEY = "MAX_UNIGRAM_COUNT";
-    public static final String MAX_BIGRAM_COUNT_KEY = "MAX_BIGRAM_COUNT";
+    public static final String MAX_UNIGRAM_COUNT_KEY = "MAX_UNIGRAM_ENTRY_COUNT";
+    public static final String MAX_BIGRAM_COUNT_KEY = "MAX_BIGRAM_ENTRY_COUNT";
+    public static final String MAX_TRIGRAM_COUNT_KEY = "MAX_TRIGRAM_ENTRY_COUNT";
     public static final String ATTRIBUTE_VALUE_TRUE = "1";
+    public static final String CODE_POINT_TABLE_KEY = "codePointTable";
 
-    public DictionaryHeader(final int headerSize, final DictionaryOptions dictionaryOptions,
-            final FormatOptions formatOptions) throws UnsupportedFormatException {
+    public DictionaryHeader(final int headerSize,
+            @Nonnull final DictionaryOptions dictionaryOptions,
+            @Nonnull final FormatOptions formatOptions) throws UnsupportedFormatException {
         mDictionaryOptions = dictionaryOptions;
         mFormatOptions = formatOptions;
         mBodyOffset = formatOptions.mVersion < FormatSpec.VERSION4 ? headerSize : 0;
-        if (null == getLocaleString()) {
+        final String localeString = dictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY);
+        if (null == localeString) {
             throw new UnsupportedFormatException("Cannot create a FileHeader without a locale");
         }
-        if (null == getVersion()) {
+        final String versionString = dictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY);
+        if (null == versionString) {
             throw new UnsupportedFormatException(
                     "Cannot create a FileHeader without a version");
         }
-        if (null == getId()) {
+        final String idString = dictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY);
+        if (null == idString) {
             throw new UnsupportedFormatException("Cannot create a FileHeader without an ID");
         }
-    }
-
-    // Helper method to get the locale as a String
-    public String getLocaleString() {
-        return mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_KEY);
-    }
-
-    // Helper method to get the version String
-    public String getVersion() {
-        return mDictionaryOptions.mAttributes.get(DICTIONARY_VERSION_KEY);
-    }
-
-    // Helper method to get the dictionary ID as a String
-    public String getId() {
-        return mDictionaryOptions.mAttributes.get(DICTIONARY_ID_KEY);
+        mLocaleString = localeString;
+        mVersionString = versionString;
+        mIdString = idString;
     }
 
     // Helper method to get the description
+    @Nullable
     public String getDescription() {
         // TODO: Right now each dictionary file comes with a description in its own language.
         // It will display as is no matter the device's locale. It should be internationalized.
diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
index a2ae74b..e422c4c 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.latin.makedict;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 
 import java.util.Date;
 import java.util.HashMap;
@@ -36,9 +36,7 @@
      * sion
      *
      * o |
-     * p | not used                                3 bits
-     * t | each unigram and bigram entry has a time stamp?
-     * i |                                         1 bit, 1 = yes, 0 = no : CONTAINS_TIMESTAMP_FLAG
+     * p | not used, 2 bytes.
      * o |
      * nflags
      *
@@ -48,7 +46,7 @@
      * d |
      * ersize
      *
-     *   | attributes list
+     * attributes list
      *
      * attributes list is:
      * <key>   = | string of characters at the char format described below, with the terminator used
@@ -86,27 +84,16 @@
      */
 
     /* Node (FusionDictionary.PtNode) layout is as follows:
-     *   | is moved ?             2 bits, 11 = no          : FLAG_IS_NOT_MOVED
-     *   |                          This must be the same as FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES
-     *   |                                01 = yes         : FLAG_IS_MOVED
-     * f |                      the new address is stored in the same place as the parent address
-     * l | is deleted?                    10 = yes         : FLAG_IS_DELETED
+     *   | CHILDREN_ADDRESS_TYPE  2 bits, 11          : FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES
+     *   |                                10          : FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES
+     * f |                                01          : FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE
+     * l |                                00          : FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS
      * a | has several chars ?         1 bit, 1 = yes, 0 = no   : FLAG_HAS_MULTIPLE_CHARS
      * g | has a terminal ?            1 bit, 1 = yes, 0 = no   : FLAG_IS_TERMINAL
      * s | has shortcut targets ?      1 bit, 1 = yes, 0 = no   : FLAG_HAS_SHORTCUT_TARGETS
      *   | has bigrams ?               1 bit, 1 = yes, 0 = no   : FLAG_HAS_BIGRAMS
      *   | is not a word ?             1 bit, 1 = yes, 0 = no   : FLAG_IS_NOT_A_WORD
-     *   | is blacklisted ?            1 bit, 1 = yes, 0 = no   : FLAG_IS_BLACKLISTED
-     *
-     * p |
-     * a | parent address, 3byte
-     * r | 1 byte = bbbbbbbb match
-     * e |   case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte)
-     * n |   otherwise => (bbbbbbbb << 16) + (next byte << 8) + next byte
-     * t | This address is relative to the head of the PtNode.
-     * a | If the node doesn't have a parent, this field is set to 0.
-     * d |
-     * dress
+     *   | is possibly offensive ?     1 bit, 1 = yes, 0 = no   : FLAG_IS_POSSIBLY_OFFENSIVE
      *
      * c | IF FLAG_HAS_MULTIPLE_CHARS
      * h |   char, char, char, char    n * (1 or 3 bytes) : use PtNodeInfo for i/o helpers
@@ -121,15 +108,10 @@
      * q |
      *
      * c |
-     * h | children address, 3 bytes
-     * i | 1 byte = bbbbbbbb match
-     * l |   case 1xxxxxxx => -((0xxxxxxx << 16) + (next byte << 8) + next byte)
-     * d |   otherwise => (bbbbbbbb<<16) + (next byte << 8) + next byte
-     * r | if this node doesn't have children, this field is set to 0.
-     * e |   (see BinaryDictEncoderUtils#writeVariableSignedAddress)
-     * n | This address is relative to the position of this field.
-     * a |
-     * ddress
+     * h | children address, CHILDREN_ADDRESS_TYPE bytes
+     * i | This address is relative to the position of this field.
+     * l |
+     * drenaddress
      *
      *   | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS
      *   | shortcut string list
@@ -179,31 +161,30 @@
 
     public static final int MAGIC_NUMBER = 0x9BC13AFE;
     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
+    // From version 2.01 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.
     // When we bump up the dictionary format version, we should update
     // ExpandableDictionary.needsToMigrateDictionary() and
     // ExpandableDictionary.matchesExpectedBinaryDictFormatVersionForThisType().
     public static final int VERSION2 = 2;
-    // Dictionary version used for testing.
-    public static final int VERSION4_ONLY_FOR_TESTING = 399;
-    public static final int VERSION401 = 401;
-    public static final int VERSION4 = 402;
-    public static final int VERSION4_DEV = 403;
-    static final int MINIMUM_SUPPORTED_VERSION = VERSION2;
-    static final int MAXIMUM_SUPPORTED_VERSION = VERSION4_DEV;
+    public static final int VERSION201 = 201;
+    public static final int VERSION202 = 202;
+    // format version for Fava Dictionaries.
+    public static final int VERSION_DELIGHT3 = 86736212;
+    public static final int VERSION402 = 402;
+    public static final int VERSION403 = 403;
+    public static final int VERSION4 = VERSION403;
+    public static final int MINIMUM_SUPPORTED_STATIC_VERSION = VERSION202;
+    public static final int MAXIMUM_SUPPORTED_STATIC_VERSION = VERSION_DELIGHT3;
+    static final int MINIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4;
+    static final int MAXIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION403;
 
     // TODO: Make this value adaptative to content data, store it in the header, and
     // use it in the reading code.
-    static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
-
-    static final int PARENT_ADDRESS_SIZE = 3;
-    static final int FORWARD_LINK_ADDRESS_SIZE = 3;
+    static final int MAX_WORD_LENGTH = DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH;
 
     // These flags are used only in the static dictionary.
     static final int MASK_CHILDREN_ADDRESS_TYPE = 0xC0;
@@ -218,14 +199,7 @@
     static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08;
     static final int FLAG_HAS_BIGRAMS = 0x04;
     static final int FLAG_IS_NOT_A_WORD = 0x02;
-    static final int FLAG_IS_BLACKLISTED = 0x01;
-
-    // These flags are used only in the dynamic dictionary.
-    static final int MASK_MOVE_AND_DELETE_FLAG = 0xC0;
-    static final int FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE = 0x40;
-    static final int FLAG_IS_MOVED = 0x00 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE;
-    static final int FLAG_IS_NOT_MOVED = 0x80 | FIXED_BIT_OF_DYNAMIC_UPDATE_MOVE;
-    static final int FLAG_IS_DELETED = 0x80;
+    static final int FLAG_IS_POSSIBLY_OFFENSIVE = 0x01;
 
     static final int FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT = 0x80;
     static final int FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE = 0x40;
@@ -240,52 +214,12 @@
     static final int PTNODE_TERMINATOR_SIZE = 1;
     static final int PTNODE_FLAGS_SIZE = 1;
     static final int PTNODE_FREQUENCY_SIZE = 1;
-    static final int PTNODE_TERMINAL_ID_SIZE = 4;
     static final int PTNODE_MAX_ADDRESS_SIZE = 3;
     static final int PTNODE_ATTRIBUTE_FLAGS_SIZE = 1;
     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. 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";
-    // tat = Terminal Address Table
-    static final String TERMINAL_ADDRESS_TABLE_FILE_EXTENSION = ".tat";
-    static final String BIGRAM_FILE_EXTENSION = ".bigram";
-    static final String SHORTCUT_FILE_EXTENSION = ".shortcut";
-    static final String LOOKUP_TABLE_FILE_SUFFIX = "_lookup";
-    static final String CONTENT_TABLE_FILE_SUFFIX = "_index";
-    static final int FLAGS_IN_FREQ_FILE_SIZE = 1;
-    static final int FREQUENCY_AND_FLAGS_SIZE = 2;
-    static final int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
-    static final int UNIGRAM_TIMESTAMP_SIZE = 4;
-    static final int UNIGRAM_COUNTER_SIZE = 1;
-    static final int UNIGRAM_LEVEL_SIZE = 1;
-
-    // With the English main dictionary as of October 2013, the size of bigram address table is
-    // is 345KB with the block size being 16.
-    // This is 54% of that of full address table.
-    static final int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
-    static final int BIGRAM_CONTENT_COUNT = 1;
-    static final int BIGRAM_FREQ_CONTENT_INDEX = 0;
-    static final String BIGRAM_FREQ_CONTENT_ID = "_freq";
-    static final int BIGRAM_TIMESTAMP_SIZE = 4;
-    static final int BIGRAM_COUNTER_SIZE = 1;
-    static final int BIGRAM_LEVEL_SIZE = 1;
-
-    static final int SHORTCUT_CONTENT_COUNT = 1;
-    static final int SHORTCUT_CONTENT_INDEX = 0;
-    // With the English main dictionary as of October 2013, the size of shortcut address table is
-    // 26KB with the block size being 64.
-    // This is only 4.4% of that of full address table.
-    static final int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
-    static final String SHORTCUT_CONTENT_ID = "_shortcut";
-
     static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
-    static final int NO_PARENT_ADDRESS = 0;
-    static final int NO_FORWARD_LINK_ADDRESS = 0;
     static final int INVALID_CHARACTER = -1;
 
     static final int MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT = 0x7F; // 127
@@ -302,14 +236,13 @@
 
     // This option needs to be the same numeric value as the one in binary_format.h.
     static final int NOT_VALID_WORD = -99;
-    static final int SIGNED_CHILDREN_ADDRESS_SIZE = 3;
 
     static final int UINT8_MAX = 0xFF;
     static final int UINT16_MAX = 0xFFFF;
     static final int UINT24_MAX = 0xFFFFFF;
-    static final int SINT24_MAX = 0x7FFFFF;
     static final int MSB8 = 0x80;
-    static final int MSB24 = 0x800000;
+    static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20;
+    static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF;
 
     /**
      * Options about file format.
diff --git a/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java
new file mode 100644
index 0000000..b1d19dc
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/makedict/NgramProperty.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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.makedict;
+
+import com.android.inputmethod.latin.NgramContext;
+
+public class NgramProperty {
+    public final WeightedString mTargetWord;
+    public final NgramContext mNgramContext;
+
+    public NgramProperty(final WeightedString targetWord, final NgramContext ngramContext) {
+        mTargetWord = targetWord;
+        mNgramContext = ngramContext;
+    }
+
+    @Override
+    public int hashCode() {
+        return mTargetWord.hashCode() ^ mNgramContext.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) return true;
+        if (!(o instanceof NgramProperty)) return false;
+        final NgramProperty n = (NgramProperty)o;
+        return mTargetWord.equals(n.mTargetWord) && mNgramContext.equals(n.mNgramContext);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
index 5fcbb63..03c2ece 100644
--- a/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
+++ b/java/src/com/android/inputmethod/latin/makedict/ProbabilityInfo.java
@@ -40,11 +40,8 @@
         if (probabilityInfo2 == null) {
             return probabilityInfo1;
         }
-        if (probabilityInfo1.mProbability > probabilityInfo2.mProbability) {
-            return probabilityInfo1;
-        } else {
-            return probabilityInfo2;
-        }
+        return (probabilityInfo1.mProbability > probabilityInfo2.mProbability) ? probabilityInfo1
+                : probabilityInfo2;
     }
 
     public ProbabilityInfo(final int probability) {
@@ -67,9 +64,8 @@
     public int hashCode() {
         if (hasHistoricalInfo()) {
             return Arrays.hashCode(new Object[] { mProbability, mTimestamp, mLevel, mCount });
-        } else {
-            return Arrays.hashCode(new Object[] { mProbability });
         }
+        return Arrays.hashCode(new Object[] { mProbability });
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index cd78e22..264e757 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -18,12 +18,17 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.CombinedFormatUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 
+import javax.annotation.Nullable;
+
 /**
  * Utility class for a word with a probability.
  *
@@ -32,31 +37,35 @@
 public final class WordProperty implements Comparable<WordProperty> {
     public final String mWord;
     public final ProbabilityInfo mProbabilityInfo;
-    public final ArrayList<WeightedString> mShortcutTargets;
-    public final ArrayList<WeightedString> mBigrams;
+    public final ArrayList<NgramProperty> mNgrams;
     // TODO: Support mIsBeginningOfSentence.
     public final boolean mIsBeginningOfSentence;
     public final boolean mIsNotAWord;
-    public final boolean mIsBlacklistEntry;
-    public final boolean mHasShortcuts;
-    public final boolean mHasBigrams;
+    public final boolean mIsPossiblyOffensive;
+    public final boolean mHasNgrams;
 
     private int mHashCode = 0;
 
+    // TODO: Support n-gram.
     @UsedForTesting
     public WordProperty(final String word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams,
-            final boolean isNotAWord, final boolean isBlacklistEntry) {
+            @Nullable final ArrayList<WeightedString> bigrams,
+            final boolean isNotAWord, final boolean isPossiblyOffensive) {
         mWord = word;
         mProbabilityInfo = probabilityInfo;
-        mShortcutTargets = shortcutTargets;
-        mBigrams = bigrams;
+        if (null == bigrams) {
+            mNgrams = null;
+        } else {
+            mNgrams = new ArrayList<>();
+            final NgramContext ngramContext = new NgramContext(new WordInfo(mWord));
+            for (final WeightedString bigramTarget : bigrams) {
+                mNgrams.add(new NgramProperty(bigramTarget, ngramContext));
+            }
+        }
         mIsBeginningOfSentence = false;
         mIsNotAWord = isNotAWord;
-        mIsBlacklistEntry = isBlacklistEntry;
-        mHasBigrams = bigrams != null && !bigrams.isEmpty();
-        mHasShortcuts = shortcutTargets != null && !shortcutTargets.isEmpty();
+        mIsPossiblyOffensive = isPossiblyOffensive;
+        mHasNgrams = bigrams != null && !bigrams.isEmpty();
     }
 
     private static ProbabilityInfo createProbabilityInfoFromArray(final int[] probabilityInfo) {
@@ -70,36 +79,54 @@
     // Construct word property using information from native code.
     // This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
     public WordProperty(final int[] codePoints, final boolean isNotAWord,
-            final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts,
+            final boolean isPossiblyOffensive, final boolean hasBigram,
             final boolean isBeginningOfSentence, final int[] probabilityInfo,
-            final ArrayList<int[]> bigramTargets, final ArrayList<int[]> bigramProbabilityInfo,
-            final ArrayList<int[]> shortcutTargets,
-            final ArrayList<Integer> shortcutProbabilities) {
+            final ArrayList<int[][]> ngramPrevWordsArray,
+            final ArrayList<boolean[]> ngramPrevWordIsBeginningOfSentenceArray,
+            final ArrayList<int[]> ngramTargets, final ArrayList<int[]> ngramProbabilityInfo) {
         mWord = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
         mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
-        mShortcutTargets = new ArrayList<>();
-        mBigrams = new ArrayList<>();
+        final ArrayList<NgramProperty> ngrams = new ArrayList<>();
         mIsBeginningOfSentence = isBeginningOfSentence;
         mIsNotAWord = isNotAWord;
-        mIsBlacklistEntry = isBlacklisted;
-        mHasShortcuts = hasShortcuts;
-        mHasBigrams = hasBigram;
+        mIsPossiblyOffensive = isPossiblyOffensive;
+        mHasNgrams = hasBigram;
 
-        final int bigramTargetCount = bigramTargets.size();
-        for (int i = 0; i < bigramTargetCount; i++) {
-            final String bigramTargetString =
-                    StringUtils.getStringFromNullTerminatedCodePointArray(bigramTargets.get(i));
-            mBigrams.add(new WeightedString(bigramTargetString,
-                    createProbabilityInfoFromArray(bigramProbabilityInfo.get(i))));
+        final int relatedNgramCount = ngramTargets.size();
+        for (int i = 0; i < relatedNgramCount; i++) {
+            final String ngramTargetString =
+                    StringUtils.getStringFromNullTerminatedCodePointArray(ngramTargets.get(i));
+            final WeightedString ngramTarget = new WeightedString(ngramTargetString,
+                    createProbabilityInfoFromArray(ngramProbabilityInfo.get(i)));
+            final int[][] prevWords = ngramPrevWordsArray.get(i);
+            final boolean[] isBeginningOfSentenceArray =
+                    ngramPrevWordIsBeginningOfSentenceArray.get(i);
+            final WordInfo[] wordInfoArray = new WordInfo[prevWords.length];
+            for (int j = 0; j < prevWords.length; j++) {
+                wordInfoArray[j] = isBeginningOfSentenceArray[j]
+                        ? WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO
+                        : new WordInfo(StringUtils.getStringFromNullTerminatedCodePointArray(
+                                prevWords[j]));
+            }
+            final NgramContext ngramContext = new NgramContext(wordInfoArray);
+            ngrams.add(new NgramProperty(ngramTarget, ngramContext));
         }
+        mNgrams = ngrams.isEmpty() ? null : ngrams;
+    }
 
-        final int shortcutTargetCount = shortcutTargets.size();
-        for (int i = 0; i < shortcutTargetCount; i++) {
-            final String shortcutTargetString =
-                    StringUtils.getStringFromNullTerminatedCodePointArray(shortcutTargets.get(i));
-            mShortcutTargets.add(
-                    new WeightedString(shortcutTargetString, shortcutProbabilities.get(i)));
+    // TODO: Remove
+    @UsedForTesting
+    public ArrayList<WeightedString> getBigrams() {
+        if (null == mNgrams) {
+            return null;
         }
+        final ArrayList<WeightedString> bigrams = new ArrayList<>();
+        for (final NgramProperty ngram : mNgrams) {
+            if (ngram.mNgramContext.getPrevWordCount() == 1) {
+                bigrams.add(ngram.mTargetWord);
+            }
+        }
+        return bigrams;
     }
 
     public int getProbability() {
@@ -110,10 +137,9 @@
         return Arrays.hashCode(new Object[] {
                 word.mWord,
                 word.mProbabilityInfo,
-                word.mShortcutTargets.hashCode(),
-                word.mBigrams.hashCode(),
+                word.mNgrams,
                 word.mIsNotAWord,
-                word.mIsBlacklistEntry
+                word.mIsPossiblyOffensive
         });
     }
 
@@ -141,10 +167,18 @@
         if (o == this) return true;
         if (!(o instanceof WordProperty)) return false;
         WordProperty w = (WordProperty)o;
-        return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
-                && mShortcutTargets.equals(w.mShortcutTargets) && mBigrams.equals(w.mBigrams)
-                && mIsNotAWord == w.mIsNotAWord && mIsBlacklistEntry == w.mIsBlacklistEntry
-                && mHasBigrams == w.mHasBigrams && mHasShortcuts && w.mHasBigrams;
+        return mProbabilityInfo.equals(w.mProbabilityInfo)
+                && mWord.equals(w.mWord) && equals(mNgrams, w.mNgrams)
+                && mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive
+                && mHasNgrams == w.mHasNgrams;
+    }
+
+    // TDOO: Have a utility method like java.util.Objects.equals.
+    private static <T> boolean equals(final ArrayList<T> a, final ArrayList<T> b) {
+        if (null == a) {
+            return null == b;
+        }
+        return a.equals(b);
     }
 
     @Override
@@ -157,7 +191,7 @@
 
     @UsedForTesting
     public boolean isValid() {
-        return getProbability() != BinaryDictionary.NOT_A_PROBABILITY;
+        return getProbability() != Dictionary.NOT_A_PROBABILITY;
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/network/AuthException.java b/java/src/com/android/inputmethod/latin/network/AuthException.java
new file mode 100644
index 0000000..1bce4c1
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/network/AuthException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+/**
+ * Authentication exception. When this exception is thrown, the client may
+ * try to refresh the authentication token and try again.
+ */
+public class AuthException extends Exception {
+    public AuthException() {
+        super();
+    }
+
+    public AuthException(Throwable throwable) {
+        super(throwable);
+    }
+
+    public AuthException(String detailMessage) {
+        super(detailMessage);
+    }
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java
new file mode 100644
index 0000000..079d07e
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/network/BlockingHttpClient.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import android.util.Log;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * A client for executing HTTP requests synchronously.
+ * This must never be called from the main thread.
+ */
+public class BlockingHttpClient {
+    private static final boolean DEBUG = false;
+    private static final String TAG = BlockingHttpClient.class.getSimpleName();
+
+    private final HttpURLConnection mConnection;
+
+    /**
+     * Interface that handles processing the response for a request.
+     */
+    public interface ResponseProcessor<T> {
+        /**
+         * Called when the HTTP request finishes successfully.
+         * The {@link InputStream} is closed by the client after the method finishes,
+         * so any processing must be done in this method itself.
+         *
+         * @param response An input stream that can be used to read the HTTP response.
+         */
+         T onSuccess(InputStream response) throws IOException;
+    }
+
+    public BlockingHttpClient(HttpURLConnection connection) {
+        mConnection = connection;
+    }
+
+    /**
+     * Executes the request on the underlying {@link HttpURLConnection}.
+     *
+     * @param request The request payload, if any, or null.
+     * @param responseProcessor A processor for the HTTP response.
+     */
+    public <T> T execute(@Nullable byte[] request, @Nonnull ResponseProcessor<T> responseProcessor)
+            throws IOException, AuthException, HttpException {
+        if (DEBUG) {
+            Log.d(TAG, "execute: " + mConnection.getURL());
+        }
+        try {
+            if (request != null) {
+                if (DEBUG) {
+                    Log.d(TAG, "request size: " + request.length);
+                }
+                OutputStream out = new BufferedOutputStream(mConnection.getOutputStream());
+                out.write(request);
+                out.flush();
+                out.close();
+            }
+
+            final int responseCode = mConnection.getResponseCode();
+            if (responseCode != HttpURLConnection.HTTP_OK) {
+                Log.w(TAG, "Response error: " +  responseCode + ", Message: "
+                        + mConnection.getResponseMessage());
+                if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
+                    throw new AuthException(mConnection.getResponseMessage());
+                }
+                throw new HttpException(responseCode);
+            }
+            if (DEBUG) {
+                Log.d(TAG, "request executed successfully");
+            }
+            return responseProcessor.onSuccess(mConnection.getInputStream());
+        } finally {
+            mConnection.disconnect();
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/network/HttpException.java b/java/src/com/android/inputmethod/latin/network/HttpException.java
new file mode 100644
index 0000000..b9d8b63
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/network/HttpException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+/**
+ * The HttpException exception represents a XML/HTTP fault with a HTTP status code.
+ */
+public class HttpException extends Exception {
+
+    /**
+     * The HTTP status code.
+     */
+    private final int mStatusCode;
+
+    /**
+     * @param statusCode int HTTP status code.
+     */
+    public HttpException(int statusCode) {
+        super("Response Code: " + statusCode);
+        mStatusCode = statusCode;
+    }
+
+    /**
+     * @return the HTTP status code related to this exception.
+     */
+    @UsedForTesting
+    public int getHttpStatusCode() {
+        return mStatusCode;
+    }
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java
new file mode 100644
index 0000000..df54bf4
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilder.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import android.text.TextUtils;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+/**
+ * Builder for {@link HttpURLConnection}s.
+ *
+ * TODO: Remove @UsedForTesting after this is actually used.
+ */
+@UsedForTesting
+public class HttpUrlConnectionBuilder {
+    private static final int DEFAULT_TIMEOUT_MILLIS = 5 * 1000;
+
+    /**
+     * Request header key for authentication.
+     */
+    public static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
+
+    /**
+     * Request header key for cache control.
+     */
+    public static final String KEY_CACHE_CONTROL = "Cache-Control";
+    /**
+     * Request header value for cache control indicating no caching.
+     * @see #KEY_CACHE_CONTROL
+     */
+    public static final String VALUE_NO_CACHE = "no-cache";
+
+    /**
+     * Indicates that the request is unidirectional - upload-only.
+     * TODO: Remove @UsedForTesting after this is actually used.
+     */
+    @UsedForTesting
+    public static final int MODE_UPLOAD_ONLY = 1;
+    /**
+     * Indicates that the request is unidirectional - download only.
+     * TODO: Remove @UsedForTesting after this is actually used.
+     */
+    @UsedForTesting
+    public static final int MODE_DOWNLOAD_ONLY = 2;
+    /**
+     * Indicates that the request is bi-directional.
+     * TODO: Remove @UsedForTesting after this is actually used.
+     */
+    @UsedForTesting
+    public static final int MODE_BI_DIRECTIONAL = 3;
+
+    private final HashMap<String, String> mHeaderMap = new HashMap<>();
+
+    private URL mUrl;
+    private int mConnectTimeoutMillis = DEFAULT_TIMEOUT_MILLIS;
+    private int mReadTimeoutMillis = DEFAULT_TIMEOUT_MILLIS;
+    private int mContentLength = -1;
+    private boolean mUseCache;
+    private int mMode;
+
+    /**
+     * Sets the URL that'll be used for the request.
+     * This *must* be set before calling {@link #build()}
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setUrl(String url) throws MalformedURLException {
+        if (TextUtils.isEmpty(url)) {
+            throw new IllegalArgumentException("URL must not be empty");
+        }
+        mUrl = new URL(url);
+        return this;
+    }
+
+    /**
+     * Sets the connect timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setConnectTimeout(int timeoutMillis) {
+        if (timeoutMillis < 0) {
+            throw new IllegalArgumentException("connect-timeout must be >= 0, but was "
+                    + timeoutMillis);
+        }
+        mConnectTimeoutMillis = timeoutMillis;
+        return this;
+    }
+
+    /**
+     * Sets the read timeout. Defaults to {@value #DEFAULT_TIMEOUT_MILLIS} milliseconds.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setReadTimeout(int timeoutMillis) {
+        if (timeoutMillis < 0) {
+            throw new IllegalArgumentException("read-timeout must be >= 0, but was "
+                    + timeoutMillis);
+        }
+        mReadTimeoutMillis = timeoutMillis;
+        return this;
+    }
+
+    /**
+     * Adds an entry to the request header.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder addHeader(String key, String value) {
+        mHeaderMap.put(key, value);
+        return this;
+    }
+
+    /**
+     * Sets an authentication token.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setAuthToken(String value) {
+        mHeaderMap.put(HTTP_HEADER_AUTHORIZATION, value);
+        return this;
+    }
+
+    /**
+     * Sets the request to be executed such that the input is not buffered.
+     * This may be set when the request size is known beforehand.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setFixedLengthForStreaming(int length) {
+        mContentLength = length;
+        return this;
+    }
+
+    /**
+     * Indicates if the request can use cached responses or not.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setUseCache(boolean useCache) {
+        mUseCache = useCache;
+        return this;
+    }
+
+    /**
+     * The request mode.
+     * Sets the request mode to be one of: upload-only, download-only or bidirectional.
+     *
+     * @see #MODE_UPLOAD_ONLY
+     * @see #MODE_DOWNLOAD_ONLY
+     * @see #MODE_BI_DIRECTIONAL
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used
+     */
+    @UsedForTesting
+    public HttpUrlConnectionBuilder setMode(int mode) {
+        if (mode != MODE_UPLOAD_ONLY
+                && mode != MODE_DOWNLOAD_ONLY
+                && mode != MODE_BI_DIRECTIONAL) {
+            throw new IllegalArgumentException("Invalid mode specified:" + mode);
+        }
+        mMode = mode;
+        return this;
+    }
+
+    /**
+     * Builds the {@link HttpURLConnection} instance that can be used to execute the request.
+     *
+     * TODO: Remove @UsedForTesting after this method is actually used.
+     */
+    @UsedForTesting
+    public HttpURLConnection build() throws IOException {
+        if (mUrl == null) {
+            throw new IllegalArgumentException("A URL must be specified!");
+        }
+        final HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
+        connection.setConnectTimeout(mConnectTimeoutMillis);
+        connection.setReadTimeout(mReadTimeoutMillis);
+        connection.setUseCaches(mUseCache);
+        switch (mMode) {
+            case MODE_UPLOAD_ONLY:
+                connection.setDoInput(true);
+                connection.setDoOutput(false);
+                break;
+            case MODE_DOWNLOAD_ONLY:
+                connection.setDoInput(false);
+                connection.setDoOutput(true);
+                break;
+            case MODE_BI_DIRECTIONAL:
+                connection.setDoInput(true);
+                connection.setDoOutput(true);
+                break;
+        }
+        for (final Entry<String, String> entry : mHeaderMap.entrySet()) {
+            connection.addRequestProperty(entry.getKey(), entry.getValue());
+        }
+        if (mContentLength >= 0) {
+            connection.setFixedLengthStreamingMode(mContentLength);
+        }
+        return connection;
+    }
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
deleted file mode 100644
index ac55b93..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.content.Context;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-
-import java.io.File;
-import java.util.Locale;
-
-public class ContextualDictionary extends ExpandableBinaryDictionary {
-    /* package */ static final String NAME = ContextualDictionary.class.getSimpleName();
-
-    private ContextualDictionary(final Context context, final Locale locale,
-            final File dictFile) {
-        super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_CONTEXTUAL,
-                dictFile);
-        // Always reset the contents.
-        clear();
-    }
-
-    @UsedForTesting
-    public static ContextualDictionary getDictionary(final Context context, final Locale locale,
-            final File dictFile, final String dictNamePrefix) {
-        return new ContextualDictionary(context, locale, dictFile);
-    }
-
-    @Override
-    public boolean isValidWord(final String word) {
-        // Strings out of this dictionary should not be considered existing words.
-        return false;
-    }
-
-    @Override
-    protected void loadInitialContentsLocked() {
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
deleted file mode 100644
index 1ba7b36..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ /dev/null
@@ -1,89 +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 android.content.Context;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-
-import java.io.File;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * This class is a base class of a dictionary that supports decaying for the personalized language
- * model.
- */
-public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableBinaryDictionary {
-    private static final boolean DBG_DUMP_ON_CLOSE = false;
-
-    /** Any pair being typed or picked */
-    public static final int FREQUENCY_FOR_TYPED = 2;
-
-    public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED;
-    public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY;
-
-    /** The locale for this dictionary. */
-    public final Locale mLocale;
-
-    protected DecayingExpandableBinaryDictionaryBase(final Context context,
-            final String dictName, final Locale locale, final String dictionaryType,
-            final File dictFile) {
-        super(context, dictName, locale, dictionaryType, dictFile);
-        mLocale = locale;
-        if (mLocale != null && mLocale.toString().length() > 1) {
-            reloadDictionaryIfRequired();
-        }
-    }
-
-    @Override
-    public void close() {
-        if (DBG_DUMP_ON_CLOSE) {
-            dumpAllWordsForDebug();
-        }
-        // Flush pending writes.
-        asyncFlushBinaryDictionary();
-        super.close();
-    }
-
-    @Override
-    protected Map<String, String> getHeaderAttributeMap() {
-        final Map<String, String> attributeMap = super.getHeaderAttributeMap();
-        attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        return attributeMap;
-    }
-
-    @Override
-    protected void loadInitialContentsLocked() {
-        // No initial contents.
-    }
-
-    /* package */ void runGCIfRequired() {
-        runGCIfRequired(false /* mindsBlockByGC */);
-    }
-
-    @Override
-    public boolean isValidWord(final String word) {
-        // Strings out of this dictionary should not be considered existing words.
-        return false;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
deleted file mode 100644
index 221bb9a..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
+++ /dev/null
@@ -1,67 +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 android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Broadcast receiver for periodically updating decaying dictionaries.
- */
-public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
-    /**
-     * The root domain for the personalization.
-     */
-    private static final String PERSONALIZATION_DOMAIN =
-            "com.android.inputmethod.latin.personalization";
-
-    /**
-     * The action of the intent to tell the time to decay dictionaries.
-     */
-    private static final String DICTIONARY_DECAY_INTENT_ACTION =
-            PERSONALIZATION_DOMAIN + ".DICT_DECAY";
-
-    /**
-     * Interval to update for decaying dictionaries.
-     */
-    /* package */ static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60);
-
-    public static void setUpIntervalAlarmForDictionaryDecaying(Context context) {
-        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
-        final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION);
-        updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class);
-        final long alarmTime =  System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL;
-        final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0 /* requestCode */,
-                updateIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-        if (null != alarmManager) alarmManager.setInexactRepeating(AlarmManager.RTC,
-                alarmTime, DICTIONARY_DECAY_INTERVAL, pendingIntent);
-    }
-
-    @Override
-    public void onReceive(final Context context, final Intent intent) {
-        final String action = intent.getAction();
-        if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) {
-            PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries();
-            PersonalizationHelper.runGCOnAllOpenedPersonalizationDictionaries();
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java
deleted file mode 100644
index 9d72de8..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDataChunk.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-public class PersonalizationDataChunk {
-    public final boolean mInputByUser;
-    public final List<String> mTokens;
-    public final int mTimestampInSeconds;
-    public final String mPackageName;
-    public final Locale mlocale = null;
-
-    public PersonalizationDataChunk(boolean inputByUser, final List<String> tokens,
-            final int timestampInSeconds, final String packageName) {
-        mInputByUser = inputByUser;
-        mTokens = Collections.unmodifiableList(tokens);
-        mTimestampInSeconds = timestampInSeconds;
-        mPackageName = packageName;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
deleted file mode 100644
index f2ad22a..0000000
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ /dev/null
@@ -1,41 +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 android.content.Context;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Dictionary;
-
-import java.io.File;
-import java.util.Locale;
-
-public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
-    /* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName();
-
-    // TODO: Make this constructor private
-    /* package */ PersonalizationDictionary(final Context context, final Locale locale) {
-        super(context, getDictName(NAME, locale, null /* dictFile */), locale,
-                Dictionary.TYPE_PERSONALIZATION, null /* dictFile */);
-    }
-
-    @UsedForTesting
-    public static PersonalizationDictionary getDictionary(final Context context,
-            final Locale locale, final File dictFile, final String dictNamePrefix) {
-        return PersonalizationHelper.getPersonalizationDictionary(context, locale);
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 331f85e..298e46c 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -19,130 +19,76 @@
 import android.content.Context;
 import android.util.Log;
 
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
 
 import java.io.File;
 import java.io.FilenameFilter;
 import java.lang.ref.SoftReference;
 import java.util.Locale;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Helps handle and manage personalized dictionaries such as {@link UserHistoryDictionary}.
+ */
 public class PersonalizationHelper {
     private static final String TAG = PersonalizationHelper.class.getSimpleName();
     private static final boolean DEBUG = false;
+
     private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
             sLangUserHistoryDictCache = new ConcurrentHashMap<>();
-    private static final ConcurrentHashMap<String, SoftReference<PersonalizationDictionary>>
-            sLangPersonalizationDictCache = new ConcurrentHashMap<>();
 
+    @Nonnull
     public static UserHistoryDictionary getUserHistoryDictionary(
-            final Context context, final Locale locale) {
-        final String localeStr = locale.toString();
+            final Context context, final Locale locale, @Nullable final String accountName) {
+        String lookupStr = locale.toString();
+        if (accountName != null) {
+            lookupStr += "." + accountName;
+        }
         synchronized (sLangUserHistoryDictCache) {
-            if (sLangUserHistoryDictCache.containsKey(localeStr)) {
+            if (sLangUserHistoryDictCache.containsKey(lookupStr)) {
                 final SoftReference<UserHistoryDictionary> ref =
-                        sLangUserHistoryDictCache.get(localeStr);
+                        sLangUserHistoryDictCache.get(lookupStr);
                 final UserHistoryDictionary dict = ref == null ? null : ref.get();
                 if (dict != null) {
                     if (DEBUG) {
-                        Log.w(TAG, "Use cached UserHistoryDictionary for " + locale);
+                        Log.d(TAG, "Use cached UserHistoryDictionary with lookup: " + lookupStr);
                     }
                     dict.reloadDictionaryIfRequired();
                     return dict;
                 }
             }
-            final UserHistoryDictionary dict = new UserHistoryDictionary(context, locale);
-            sLangUserHistoryDictCache.put(localeStr, new SoftReference<>(dict));
+            final UserHistoryDictionary dict = new UserHistoryDictionary(
+                    context, locale, accountName);
+            sLangUserHistoryDictCache.put(lookupStr, new SoftReference<>(dict));
             return dict;
         }
     }
 
-    private static int sCurrentTimestampForTesting = 0;
-    public static void currentTimeChangedForTesting(final int currentTimestamp) {
-        if (TimeUnit.MILLISECONDS.toSeconds(
-                DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL)
-                        < currentTimestamp - sCurrentTimestampForTesting) {
-            runGCOnAllOpenedUserHistoryDictionaries();
-            runGCOnAllOpenedPersonalizationDictionaries();
-        }
-    }
-
-    public static void runGCOnAllOpenedUserHistoryDictionaries() {
-        runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache);
-    }
-
-    public static void runGCOnAllOpenedPersonalizationDictionaries() {
-        runGCOnAllDictionariesIfRequired(sLangPersonalizationDictCache);
-    }
-
-    private static <T extends DecayingExpandableBinaryDictionaryBase>
-            void runGCOnAllDictionariesIfRequired(
-                    final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) {
-        for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry
-                : dictionaryMap.entrySet()) {
-            final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get();
-            if (dict != null) {
-                dict.runGCIfRequired();
-            } else {
-                dictionaryMap.remove(entry.getKey());
-            }
-        }
-    }
-
-    public static PersonalizationDictionary getPersonalizationDictionary(
-            final Context context, final Locale locale) {
-        final String localeStr = locale.toString();
-        synchronized (sLangPersonalizationDictCache) {
-            if (sLangPersonalizationDictCache.containsKey(localeStr)) {
-                final SoftReference<PersonalizationDictionary> ref =
-                        sLangPersonalizationDictCache.get(localeStr);
-                final PersonalizationDictionary dict = ref == null ? null : ref.get();
-                if (dict != null) {
-                    if (DEBUG) {
-                        Log.w(TAG, "Use cached PersonalizationDictionary for " + locale);
-                    }
-                    return dict;
-                }
-            }
-            final PersonalizationDictionary dict = new PersonalizationDictionary(context, locale);
-            sLangPersonalizationDictCache.put(localeStr, new SoftReference<>(dict));
-            return dict;
-        }
-    }
-
-    public static void removeAllPersonalizationDictionaries(final Context context) {
-        removeAllDictionaries(context, sLangPersonalizationDictCache,
-                PersonalizationDictionary.NAME);
-    }
-
     public static void removeAllUserHistoryDictionaries(final Context context) {
-        removeAllDictionaries(context, sLangUserHistoryDictCache,
-                UserHistoryDictionary.NAME);
-    }
-
-    private static <T extends DecayingExpandableBinaryDictionaryBase> void removeAllDictionaries(
-            final Context context, final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap,
-            final String dictNamePrefix) {
-        synchronized (dictionaryMap) {
-            for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry
-                    : dictionaryMap.entrySet()) {
+        synchronized (sLangUserHistoryDictCache) {
+            for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry
+                    : sLangUserHistoryDictCache.entrySet()) {
                 if (entry.getValue() != null) {
-                    final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get();
+                    final UserHistoryDictionary dict = entry.getValue().get();
                     if (dict != null) {
                         dict.clear();
                     }
                 }
             }
-            dictionaryMap.clear();
+            sLangUserHistoryDictCache.clear();
             final File filesDir = context.getFilesDir();
             if (filesDir == null) {
                 Log.e(TAG, "context.getFilesDir() returned null.");
                 return;
             }
-            if (!FileUtils.deleteFilteredFiles(filesDir, new DictFilter(dictNamePrefix))) {
-                Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: "
-                        + filesDir.getAbsolutePath() + ", dictNamePrefix: " + dictNamePrefix);
+            final boolean filesDeleted = FileUtils.deleteFilteredFiles(
+                    filesDir, new DictFilter(UserHistoryDictionary.NAME));
+            if (!filesDeleted) {
+                Log.e(TAG, "Cannot remove dictionary files. filesDir: " + filesDir.getAbsolutePath()
+                        + ", dictNamePrefix: " + UserHistoryDictionary.NAME);
             }
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 34d4d4e..cbf0829 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -17,72 +17,120 @@
 package com.android.inputmethod.latin.personalization;
 
 import android.content.Context;
-import android.text.TextUtils;
 
+import com.android.inputmethod.annotations.ExternallyReferenced;
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.BinaryDictionary;
 import com.android.inputmethod.latin.Dictionary;
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.utils.DistracterFilter;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
+import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
 
 import java.io.File;
 import java.util.Locale;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
- * Locally gathers stats about the words user types and various other signals like auto-correction
- * cancellation or manual picks. This allows the keyboard to adapt to the typist over time.
+ * Locally gathers statistics about the words user types and various other signals like
+ * auto-correction cancellation or manual picks. This allows the keyboard to adapt to the
+ * typist over time.
  */
-public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
-    /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
+public class UserHistoryDictionary extends ExpandableBinaryDictionary {
+    static final String NAME = UserHistoryDictionary.class.getSimpleName();
 
     // TODO: Make this constructor private
-    /* package */ UserHistoryDictionary(final Context context, final Locale locale) {
-        super(context, getDictName(NAME, locale, null /* dictFile */), locale,
-                Dictionary.TYPE_USER_HISTORY, null /* dictFile */);
+    UserHistoryDictionary(final Context context, final Locale locale,
+            @Nullable final String account) {
+        super(context, getUserHistoryDictName(NAME, locale, null /* dictFile */, account), locale, Dictionary.TYPE_USER_HISTORY, null);
+        if (mLocale != null && mLocale.toString().length() > 1) {
+            reloadDictionaryIfRequired();
+        }
     }
 
+    /**
+     * @returns the name of the {@link UserHistoryDictionary}.
+     */
     @UsedForTesting
+    static String getUserHistoryDictName(final String name, final Locale locale,
+            @Nullable final File dictFile, @Nullable final String account) {
+        if (!ProductionFlags.ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY) {
+            return getDictName(name, locale, dictFile);
+        }
+        return getUserHistoryDictNamePerAccount(name, locale, dictFile, account);
+    }
+
+    /**
+     * Uses the currently signed in account to determine the dictionary name.
+     */
+    private static String getUserHistoryDictNamePerAccount(final String name, final Locale locale,
+            @Nullable final File dictFile, @Nullable final String account) {
+        if (dictFile != null) {
+            return dictFile.getName();
+        }
+        String dictName = name + "." + locale.toString();
+        if (account != null) {
+            dictName += "." + account;
+        }
+        return dictName;
+    }
+
+    // Note: This method is called by {@link DictionaryFacilitator} using Java reflection.
+    @SuppressWarnings("unused")
+    @ExternallyReferenced
     public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
-            final File dictFile, final String dictNamePrefix) {
-        return PersonalizationHelper.getUserHistoryDictionary(context, locale);
+            final File dictFile, final String dictNamePrefix, @Nullable final String account) {
+        return PersonalizationHelper.getUserHistoryDictionary(context, locale, account);
     }
 
     /**
      * Add a word to the user history dictionary.
      *
      * @param userHistoryDictionary the user history dictionary
-     * @param prevWordsInfo the information of previous words
+     * @param ngramContext the n-gram context
      * @param word the word the user inputted
      * @param isValid whether the word is valid or not
      * @param timestamp the timestamp when the word has been inputted
-     * @param distracterFilter the filter to check whether the word is a distracter
      */
     public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary,
-            final PrevWordsInfo prevWordsInfo, final String word, final boolean isValid,
-            final int timestamp, final DistracterFilter distracterFilter) {
-        final CharSequence prevWord = prevWordsInfo.mPrevWordsInfo[0].mWord;
-        if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH ||
-                (prevWord != null && prevWord.length() > Constants.DICTIONARY_MAX_WORD_LENGTH)) {
+            @Nonnull final NgramContext ngramContext, final String word, final boolean isValid,
+            final int timestamp) {
+        if (word.length() > BinaryDictionary.DICTIONARY_MAX_WORD_LENGTH) {
             return;
         }
-        final int frequency = isValid ?
-                FREQUENCY_FOR_WORDS_IN_DICTS : FREQUENCY_FOR_WORDS_NOT_IN_DICTS;
-        userHistoryDictionary.addUnigramEntryWithCheckingDistracter(word, frequency,
-                null /* shortcutTarget */, 0 /* shortcutFreq */, false /* isNotAWord */,
-                false /* isBlacklisted */, timestamp, distracterFilter);
-        // Do not insert a word as a bigram of itself
-        if (TextUtils.equals(word, prevWord)) {
-            return;
-        }
-        if (null != prevWord) {
-            if (prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence) {
-                // Beginning-of-Sentence n-gram entry is treated as a n-gram entry of invalid word.
-                userHistoryDictionary.addNgramEntry(prevWordsInfo, word,
-                        FREQUENCY_FOR_WORDS_NOT_IN_DICTS, timestamp);
-            } else {
-                userHistoryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp);
-            }
-        }
+        userHistoryDictionary.updateEntriesForWord(ngramContext, word,
+                isValid, 1 /* count */, timestamp);
+    }
+
+    @Override
+    public void close() {
+        // Flush pending writes.
+        asyncFlushBinaryDictionary();
+        super.close();
+    }
+
+    @Override
+    protected Map<String, String> getHeaderAttributeMap() {
+        final Map<String, String> attributeMap = super.getHeaderAttributeMap();
+        attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
+                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
+        attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
+                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
+        return attributeMap;
+    }
+
+    @Override
+    protected void loadInitialContentsLocked() {
+        // No initial contents.
+    }
+
+    @Override
+    public boolean isValidWord(final String word) {
+        // Strings out of this dictionary should not be considered existing words.
+        return false;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
new file mode 100644
index 0000000..a2ae0ef
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ACCOUNT_NAME;
+import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnShowListener;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.TwoStatePreference;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.accounts.AccountStateChangedListener;
+import com.android.inputmethod.latin.accounts.LoginAccountUtils;
+import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.utils.ManagedProfileUtils;
+
+import javax.annotation.Nullable;
+
+/**
+ * "Accounts & Privacy" settings sub screen.
+ *
+ * This settings sub screen handles the following preferences:
+ * <li> Account selection/management for IME </li>
+ * <li> Sync preferences </li>
+ * <li> Privacy preferences </li>
+ */
+public final class AccountsSettingsFragment extends SubScreenFragment {
+    private static final String PREF_ENABLE_SYNC_NOW = "pref_enable_cloud_sync";
+    private static final String PREF_SYNC_NOW = "pref_sync_now";
+    private static final String PREF_CLEAR_SYNC_DATA = "pref_clear_sync_data";
+
+    static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
+
+    /**
+     * Onclick listener for sync now pref.
+     */
+    private final Preference.OnPreferenceClickListener mSyncNowListener =
+            new SyncNowListener();
+    /**
+     * Onclick listener for delete sync pref.
+     */
+    private final Preference.OnPreferenceClickListener mDeleteSyncDataListener =
+            new DeleteSyncDataListener();
+
+    /**
+     * Onclick listener for enable sync pref.
+     */
+    private final Preference.OnPreferenceClickListener mEnableSyncClickListener =
+            new EnableSyncClickListener();
+
+    /**
+     * Enable sync checkbox pref.
+     */
+    private TwoStatePreference mEnableSyncPreference;
+
+    /**
+     * Enable sync checkbox pref.
+     */
+    private Preference mSyncNowPreference;
+
+    /**
+     * Clear sync data pref.
+     */
+    private Preference mClearSyncDataPreference;
+
+    /**
+     * Account switcher preference.
+     */
+    private Preference mAccountSwitcher;
+
+
+    @Override
+    public void onCreate(final Bundle icicle) {
+        super.onCreate(icicle);
+        addPreferencesFromResource(R.xml.prefs_screen_accounts);
+
+        if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) {
+            final Preference enableMetricsLogging =
+                    findPreference(Settings.PREF_ENABLE_METRICS_LOGGING);
+            final Resources res = getResources();
+            if (enableMetricsLogging != null) {
+                final String enableMetricsLoggingTitle = res.getString(
+                        R.string.enable_metrics_logging, getApplicationName());
+                enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
+            }
+        } else {
+            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
+        }
+
+        if (!ProductionFlags.ENABLE_USER_HISTORY_DICTIONARY_SYNC) {
+            removeSyncPreferences();
+        } else {
+            // Temporarily disable the preferences till we can
+            // check that we don't have a work profile.
+            disableSyncPreferences();
+            new ManagedProfileCheckerTask(this).execute();
+        }
+    }
+
+    /**
+     * Task to check work profile. If found, it removes the sync prefs. If not,
+     * it enables them.
+     */
+    private static class ManagedProfileCheckerTask extends AsyncTask<Void, Void, Void> {
+        private final AccountsSettingsFragment mFragment;
+
+        private ManagedProfileCheckerTask(final AccountsSettingsFragment fragment) {
+            mFragment = fragment;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            if (ManagedProfileUtils.getInstance().hasWorkProfile(mFragment.getActivity())) {
+                mFragment.removeSyncPreferences();
+            } else {
+                mFragment.refreshAccountAndDependentPreferences(
+                        mFragment.getSignedInAccountName());
+            }
+            return null;
+        }
+    }
+
+    private void enableSyncPreferences() {
+        mAccountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
+        if (mAccountSwitcher == null) {
+            // Preference has been removed because the device has a managed profile.
+            return;
+        }
+        mAccountSwitcher.setEnabled(true);
+
+        mEnableSyncPreference = (TwoStatePreference) findPreference(PREF_ENABLE_SYNC_NOW);
+        mEnableSyncPreference.setEnabled(true);
+        mEnableSyncPreference.setOnPreferenceClickListener(mEnableSyncClickListener);
+
+        mSyncNowPreference = findPreference(PREF_SYNC_NOW);
+        mSyncNowPreference.setEnabled(true);
+        mSyncNowPreference.setOnPreferenceClickListener(mSyncNowListener);
+
+        mClearSyncDataPreference = findPreference(PREF_CLEAR_SYNC_DATA);
+        mSyncNowPreference.setEnabled(true);
+        mClearSyncDataPreference.setOnPreferenceClickListener(mDeleteSyncDataListener);
+    }
+
+    private void disableSyncPreferences() {
+        mAccountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
+        if (mAccountSwitcher == null) {
+            // Preference has been removed because the device has a managed profile.
+            return;
+        }
+        mAccountSwitcher.setEnabled(false);
+
+        mEnableSyncPreference = (TwoStatePreference) findPreference(PREF_ENABLE_SYNC_NOW);
+        mEnableSyncPreference.setEnabled(false);
+
+        mSyncNowPreference = findPreference(PREF_SYNC_NOW);
+        mSyncNowPreference.setEnabled(false);
+
+        mClearSyncDataPreference = findPreference(PREF_CLEAR_SYNC_DATA);
+        mSyncNowPreference.setEnabled(false);
+    }
+
+    private void removeSyncPreferences() {
+        removePreference(PREF_ACCCOUNT_SWITCHER);
+        removePreference(PREF_ENABLE_CLOUD_SYNC);
+        removePreference(PREF_SYNC_NOW);
+        removePreference(PREF_CLEAR_SYNC_DATA);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        refreshAccountAndDependentPreferences(getSignedInAccountName());
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
+        if (TextUtils.equals(key, PREF_ACCOUNT_NAME)) {
+            refreshAccountAndDependentPreferences(prefs.getString(PREF_ACCOUNT_NAME, null));
+        } else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) {
+            final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
+            mEnableSyncPreference = (TwoStatePreference) findPreference(PREF_ENABLE_SYNC_NOW);
+            if (syncEnabled) {
+                mEnableSyncPreference.setSummary(R.string.cloud_sync_summary);
+            } else {
+                mEnableSyncPreference.setSummary(R.string.cloud_sync_summary_disabled);
+            }
+            AccountStateChangedListener.onSyncPreferenceChanged(getSignedInAccountName(),
+                    syncEnabled);
+        }
+    }
+
+    /**
+     * Summarizes what account is being used and turns off dependent preferences if no account
+     * is currently selected.
+     */
+    private void refreshAccountAndDependentPreferences(@Nullable final String currentAccount) {
+        // TODO(cvnguyen): Write tests.
+        if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
+            return;
+        }
+
+        final String[] accountsForLogin =
+                LoginAccountUtils.getAccountsForLogin(getActivity());
+
+        if (accountsForLogin.length > 0) {
+            enableSyncPreferences();
+            if (mAccountSwitcher == null) {
+                return;
+            }
+            mAccountSwitcher.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(final Preference preference) {
+                    if (accountsForLogin.length > 0) {
+                        // TODO: Add addition of account.
+                        createAccountPicker(accountsForLogin, currentAccount,
+                                new AccountChangedListener(null)).show();
+                    }
+                    return true;
+                }
+            });
+        } else {
+            mAccountSwitcher.setEnabled(false);
+            disableSyncPreferences();
+            mEnableSyncPreference.setSummary(getString(R.string.add_account_to_enable_sync));
+        }
+
+        if (currentAccount == null) {
+            // No account is currently selected; switch enable sync preference off.
+            mAccountSwitcher.setSummary(getString(R.string.no_accounts_selected));
+            mEnableSyncPreference.setChecked(false);
+        } else {
+            // Set the currently selected account as the summary text.
+            mAccountSwitcher.setSummary(getString(R.string.account_selected, currentAccount));
+        }
+    }
+
+    @Nullable
+    String getSignedInAccountName() {
+        return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
+    }
+
+    boolean isSyncEnabled() {
+        return getSharedPreferences().getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
+    }
+
+    /**
+     * Creates an account picker dialog showing the given accounts in a list and selecting
+     * the selected account by default.  The list of accounts must not be null/empty.
+     *
+     * Package-private for testing.
+     *
+     * @param accounts list of accounts on the device.
+     * @param selectedAccount currently selected account
+     * @param positiveButtonClickListener listener that gets called when positive button is
+     * clicked
+     */
+    @UsedForTesting
+    AlertDialog createAccountPicker(final String[] accounts,
+            final String selectedAccount,
+            final DialogInterface.OnClickListener positiveButtonClickListener) {
+        if (accounts == null || accounts.length == 0) {
+            throw new IllegalArgumentException("List of accounts must not be empty");
+        }
+
+        // See if the currently selected account is in the list.
+        // If it is, the entry is selected, and a sign-out button is provided.
+        // If it isn't, select the 0th account by default which will get picked up
+        // if the user presses OK.
+        int index = 0;
+        boolean isSignedIn = false;
+        for (int i = 0;  i < accounts.length; i++) {
+            if (TextUtils.equals(accounts[i], selectedAccount)) {
+                index = i;
+                isSignedIn = true;
+                break;
+            }
+        }
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+                .setTitle(R.string.account_select_title)
+                .setSingleChoiceItems(accounts, index, null)
+                .setPositiveButton(R.string.account_select_ok, positiveButtonClickListener)
+                .setNegativeButton(R.string.account_select_cancel, null);
+        if (isSignedIn) {
+            builder.setNeutralButton(R.string.account_select_sign_out, positiveButtonClickListener);
+        }
+        return builder.create();
+    }
+
+    /**
+     * Listener for a account selection changes from the picker.
+     * Persists/removes the account to/from shared preferences and sets up sync if required.
+     */
+    class AccountChangedListener implements DialogInterface.OnClickListener {
+        /**
+         * Represents preference that should be changed based on account chosen.
+         */
+        private TwoStatePreference mDependentPreference;
+
+        AccountChangedListener(final TwoStatePreference dependentPreference) {
+            mDependentPreference = dependentPreference;
+        }
+
+        @Override
+        public void onClick(final DialogInterface dialog, final int which) {
+            final String oldAccount = getSignedInAccountName();
+            switch (which) {
+                case DialogInterface.BUTTON_POSITIVE: // Signed in
+                    final ListView lv = ((AlertDialog)dialog).getListView();
+                    final String newAccount =
+                            (String) lv.getItemAtPosition(lv.getCheckedItemPosition());
+                    getSharedPreferences()
+                            .edit()
+                            .putString(PREF_ACCOUNT_NAME, newAccount)
+                            .apply();
+                    AccountStateChangedListener.onAccountSignedIn(oldAccount, newAccount);
+                    if (mDependentPreference != null) {
+                        mDependentPreference.setChecked(true);
+                    }
+                    break;
+                case DialogInterface.BUTTON_NEUTRAL: // Signed out
+                    AccountStateChangedListener.onAccountSignedOut(oldAccount);
+                    getSharedPreferences()
+                            .edit()
+                            .remove(PREF_ACCOUNT_NAME)
+                            .apply();
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Listener that initiates the process of sync in the background.
+     */
+    class SyncNowListener implements Preference.OnPreferenceClickListener {
+        @Override
+        public boolean onPreferenceClick(final Preference preference) {
+            AccountStateChangedListener.forceSync(getSignedInAccountName());
+            return true;
+        }
+    }
+
+    /**
+     * Listener that initiates the process of deleting user's data from the cloud.
+     */
+    class DeleteSyncDataListener implements Preference.OnPreferenceClickListener {
+        @Override
+        public boolean onPreferenceClick(final Preference preference) {
+            final AlertDialog confirmationDialog = new AlertDialog.Builder(getActivity())
+                    .setTitle(R.string.clear_sync_data_title)
+                    .setMessage(R.string.clear_sync_data_confirmation)
+                    .setPositiveButton(R.string.clear_sync_data_ok,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(final DialogInterface dialog, final int which) {
+                                    if (which == DialogInterface.BUTTON_POSITIVE) {
+                                        AccountStateChangedListener.forceDelete(
+                                                getSignedInAccountName());
+                                    }
+                                }
+                             })
+                    .setNegativeButton(R.string.cloud_sync_cancel, null /* OnClickListener */)
+                    .create();
+            confirmationDialog.show();
+            return true;
+        }
+    }
+
+    /**
+     * Listens to events when user clicks on "Enable sync" feature.
+     */
+    class EnableSyncClickListener implements OnShowListener, Preference.OnPreferenceClickListener {
+        // TODO(cvnguyen): Write tests.
+        @Override
+        public boolean onPreferenceClick(final Preference preference) {
+            final TwoStatePreference syncPreference = (TwoStatePreference) preference;
+            if (syncPreference.isChecked()) {
+                // Uncheck for now.
+                syncPreference.setChecked(false);
+
+                // Show opt-in.
+                final AlertDialog optInDialog = new AlertDialog.Builder(getActivity())
+                        .setTitle(R.string.cloud_sync_title)
+                        .setMessage(R.string.cloud_sync_opt_in_text)
+                        .setPositiveButton(R.string.account_select_ok,
+                                new DialogInterface.OnClickListener() {
+                                    @Override
+                                    public void onClick(final DialogInterface dialog,
+                                            final int which) {
+                                        if (which == DialogInterface.BUTTON_POSITIVE) {
+                                            final Context context = getActivity();
+                                            final String[] accountsForLogin =
+                                                    LoginAccountUtils.getAccountsForLogin(context);
+                                            createAccountPicker(accountsForLogin,
+                                                    getSignedInAccountName(),
+                                                    new AccountChangedListener(syncPreference))
+                                                    .show();
+                                        }
+                                    }
+                         })
+                         .setNegativeButton(R.string.cloud_sync_cancel, null)
+                         .create();
+                optInDialog.setOnShowListener(this);
+                optInDialog.show();
+            }
+            return true;
+        }
+
+        @Override
+        public void onShow(DialogInterface dialog) {
+            TextView messageView = (TextView) ((AlertDialog) dialog).findViewById(
+                    android.R.id.message);
+            if (messageView != null) {
+                messageView.setMovementMethod(LinkMovementMethod.getInstance());
+            }
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java
index 00f2c73..f2e1aed 100644
--- a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java
@@ -23,12 +23,10 @@
 import android.os.Bundle;
 import android.preference.ListPreference;
 import android.preference.Preference;
-import android.preference.TwoStatePreference;
 
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.define.ProductionFlags;
-import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
 
 /**
  * "Advanced" settings sub screen.
@@ -89,26 +87,9 @@
                     Settings.readKeyPreviewPopupEnabled(prefs, res));
         }
 
-        if (!res.getBoolean(R.bool.config_setup_wizard_available)) {
-            removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
-        }
-
-        if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) {
-            final Preference enableMetricsLogging =
-                    findPreference(Settings.PREF_ENABLE_METRICS_LOGGING);
-            if (enableMetricsLogging != null) {
-                final int applicationLabelRes = context.getApplicationInfo().labelRes;
-                final String applicationName = res.getString(applicationLabelRes);
-                final String enableMetricsLoggingTitle = res.getString(
-                        R.string.enable_metrics_logging, applicationName);
-                enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
-            }
-        } else {
-            removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
-        }
-
         setupKeypressVibrationDurationSettings();
         setupKeypressSoundVolumeSettings();
+        setupKeyLongpressTimeoutSettings();
         refreshEnablingsOfKeypressSoundAndVibrationSettings();
     }
 
@@ -116,11 +97,6 @@
     public void onResume() {
         super.onResume();
         final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
-        final TwoStatePreference showSetupWizardIcon =
-                (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
-        if (showSetupWizardIcon != null) {
-            showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity()));
-        }
         updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
     }
 
@@ -130,8 +106,6 @@
         if (key.equals(Settings.PREF_POPUP_ON)) {
             setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
                     Settings.readKeyPreviewPopupEnabled(prefs, res));
-        } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) {
-            LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity());
         }
         updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
         refreshEnablingsOfKeypressSoundAndVibrationSettings();
@@ -245,4 +219,43 @@
             }
         });
     }
+
+    private void setupKeyLongpressTimeoutSettings() {
+        final SharedPreferences prefs = getSharedPreferences();
+        final Resources res = getResources();
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
+                Settings.PREF_KEY_LONGPRESS_TIMEOUT);
+        if (pref == null) {
+            return;
+        }
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putInt(key, value).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return Settings.readKeyLongpressTimeout(prefs, res);
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return Settings.readDefaultKeyLongpressTimeout(res);
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                return res.getString(R.string.abbreviation_unit_milliseconds, value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {}
+        });
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java
index f5e4d33..554edc8 100644
--- a/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AppearanceSettingsFragment.java
@@ -19,7 +19,8 @@
 import android.os.Bundle;
 
 import com.android.inputmethod.latin.R;
-
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.define.ProductionFlags;
 
 /**
  * "Appearance" settings sub screen.
@@ -29,6 +30,10 @@
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
         addPreferencesFromResource(R.xml.prefs_screen_appearance);
+        if (!ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED ||
+                Constants.isPhone(Settings.readScreenMetrics(getResources()))) {
+            removePreference(Settings.PREF_ENABLE_SPLIT_KEYBOARD);
+        }
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
index ec29a7e..62834cd 100644
--- a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
@@ -24,8 +24,8 @@
 import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.os.Bundle;
-import android.preference.ListPreference;
 import android.preference.Preference;
+import android.preference.TwoStatePreference;
 
 import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
 import com.android.inputmethod.latin.R;
@@ -49,7 +49,7 @@
  */
 public final class CorrectionSettingsFragment extends SubScreenFragment {
     private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false;
-    private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS =
+    private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS =
             DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
             || Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
 
@@ -61,8 +61,6 @@
         final Context context = getActivity();
         final PackageManager pm = context.getPackageManager();
 
-        ensureConsistencyOfAutoCorrectionSettings();
-
         final Preference dictionaryLink = findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
         final Intent intent = dictionaryLink.getIntent();
         intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName());
@@ -74,7 +72,7 @@
         final Preference editPersonalDictionary =
                 findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY);
         final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent();
-        final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS ? null
+        final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS ? null
                 : pm.resolveActivity(
                         editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY);
         if (ri == null) {
@@ -82,21 +80,6 @@
         }
     }
 
-    @Override
-    public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
-        ensureConsistencyOfAutoCorrectionSettings();
-    }
-
-    private void ensureConsistencyOfAutoCorrectionSettings() {
-        final String autoCorrectionOff = getString(
-                R.string.auto_correction_threshold_mode_index_off);
-        final ListPreference autoCorrectionThresholdPref = (ListPreference)findPreference(
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD);
-        final String currentSetting = autoCorrectionThresholdPref.getValue();
-        setPreferenceEnabled(
-                Settings.PREF_BIGRAM_PREDICTIONS, !currentSetting.equals(autoCorrectionOff));
-    }
-
     private void overwriteUserDictionaryPreference(final Preference userDictionaryPreference) {
         final Activity activity = getActivity();
         final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity);
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
new file mode 100644
index 0000000..21ea8f8
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStylePreference.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.Preference;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
+
+import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.compat.ViewCompatUtils;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.TreeSet;
+
+final class CustomInputStylePreference extends DialogPreference
+        implements DialogInterface.OnCancelListener {
+    private static final boolean DEBUG_SUBTYPE_ID = false;
+
+    interface Listener {
+        public void onRemoveCustomInputStyle(CustomInputStylePreference stylePref);
+        public void onSaveCustomInputStyle(CustomInputStylePreference stylePref);
+        public void onAddCustomInputStyle(CustomInputStylePreference stylePref);
+        public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
+        public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
+    }
+
+    private static final String KEY_PREFIX = "subtype_pref_";
+    private static final String KEY_NEW_SUBTYPE = KEY_PREFIX + "new";
+
+    private InputMethodSubtype mSubtype;
+    private InputMethodSubtype mPreviousSubtype;
+
+    private final Listener mProxy;
+    private Spinner mSubtypeLocaleSpinner;
+    private Spinner mKeyboardLayoutSetSpinner;
+
+    public static CustomInputStylePreference newIncompleteSubtypePreference(
+            final Context context, final Listener proxy) {
+        return new CustomInputStylePreference(context, null, proxy);
+    }
+
+    public CustomInputStylePreference(final Context context, final InputMethodSubtype subtype,
+            final Listener proxy) {
+        super(context, null);
+        setDialogLayoutResource(R.layout.additional_subtype_dialog);
+        setPersistent(false);
+        mProxy = proxy;
+        setSubtype(subtype);
+    }
+
+    public void show() {
+        showDialog(null);
+    }
+
+    public final boolean isIncomplete() {
+        return mSubtype == null;
+    }
+
+    public InputMethodSubtype getSubtype() {
+        return mSubtype;
+    }
+
+    public void setSubtype(final InputMethodSubtype subtype) {
+        mPreviousSubtype = mSubtype;
+        mSubtype = subtype;
+        if (isIncomplete()) {
+            setTitle(null);
+            setDialogTitle(R.string.add_style);
+            setKey(KEY_NEW_SUBTYPE);
+        } else {
+            final String displayName =
+                    SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
+            setTitle(displayName);
+            setDialogTitle(displayName);
+            setKey(KEY_PREFIX + subtype.getLocale() + "_"
+                    + SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype));
+        }
+    }
+
+    public void revert() {
+        setSubtype(mPreviousSubtype);
+    }
+
+    public boolean hasBeenModified() {
+        return mSubtype != null && !mSubtype.equals(mPreviousSubtype);
+    }
+
+    @Override
+    protected View onCreateDialogView() {
+        final View v = super.onCreateDialogView();
+        mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
+        mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
+        mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
+        mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
+        // All keyboard layout names are in the Latin script and thus left to right. That means
+        // the view would align them to the left even if the system locale is RTL, but that
+        // would look strange. To fix this, we align them to the view's start, which will be
+        // natural for any direction.
+        ViewCompatUtils.setTextAlignment(
+                mKeyboardLayoutSetSpinner, ViewCompatUtils.TEXT_ALIGNMENT_VIEW_START);
+        return v;
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(final AlertDialog.Builder builder) {
+        builder.setCancelable(true).setOnCancelListener(this);
+        if (isIncomplete()) {
+            builder.setPositiveButton(R.string.add, this)
+                    .setNegativeButton(android.R.string.cancel, this);
+        } else {
+            builder.setPositiveButton(R.string.save, this)
+                    .setNeutralButton(android.R.string.cancel, this)
+                    .setNegativeButton(R.string.remove, this);
+            final SubtypeLocaleItem localeItem = new SubtypeLocaleItem(mSubtype);
+            final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(mSubtype);
+            setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
+            setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
+        }
+    }
+
+    private static void setSpinnerPosition(final Spinner spinner, final Object itemToSelect) {
+        final SpinnerAdapter adapter = spinner.getAdapter();
+        final int count = adapter.getCount();
+        for (int i = 0; i < count; i++) {
+            final Object item = spinner.getItemAtPosition(i);
+            if (item.equals(itemToSelect)) {
+                spinner.setSelection(i);
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void onCancel(final DialogInterface dialog) {
+        if (isIncomplete()) {
+            mProxy.onRemoveCustomInputStyle(this);
+        }
+    }
+
+    @Override
+    public void onClick(final DialogInterface dialog, final int which) {
+        super.onClick(dialog, which);
+        switch (which) {
+        case DialogInterface.BUTTON_POSITIVE:
+            final boolean isEditing = !isIncomplete();
+            final SubtypeLocaleItem locale =
+                    (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
+            final KeyboardLayoutSetItem layout =
+                    (KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
+            final InputMethodSubtype subtype =
+                    AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                            locale.mLocaleString, layout.mLayoutName);
+            setSubtype(subtype);
+            notifyChanged();
+            if (isEditing) {
+                mProxy.onSaveCustomInputStyle(this);
+            } else {
+                mProxy.onAddCustomInputStyle(this);
+            }
+            break;
+        case DialogInterface.BUTTON_NEUTRAL:
+            // Nothing to do
+            break;
+        case DialogInterface.BUTTON_NEGATIVE:
+            mProxy.onRemoveCustomInputStyle(this);
+            break;
+        }
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        final Dialog dialog = getDialog();
+        if (dialog == null || !dialog.isShowing()) {
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.mSubtype = mSubtype;
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(final Parcelable state) {
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        final SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setSubtype(myState.mSubtype);
+    }
+
+    static final class SavedState extends Preference.BaseSavedState {
+        InputMethodSubtype mSubtype;
+
+        public SavedState(final Parcelable superState) {
+            super(superState);
+        }
+
+        @Override
+        public void writeToParcel(final Parcel dest, final int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeParcelable(mSubtype, 0);
+        }
+
+        public SavedState(final Parcel source) {
+            super(source);
+            mSubtype = (InputMethodSubtype)source.readParcelable(null);
+        }
+
+        @SuppressWarnings("hiding")
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+                    @Override
+                    public SavedState createFromParcel(final Parcel source) {
+                        return new SavedState(source);
+                    }
+
+                    @Override
+                    public SavedState[] newArray(final int size) {
+                        return new SavedState[size];
+                    }
+                };
+    }
+
+    static final class SubtypeLocaleItem implements Comparable<SubtypeLocaleItem> {
+        public final String mLocaleString;
+        private final String mDisplayName;
+
+        public SubtypeLocaleItem(final InputMethodSubtype subtype) {
+            mLocaleString = subtype.getLocale();
+            mDisplayName = SubtypeLocaleUtils.getSubtypeLocaleDisplayNameInSystemLocale(
+                    mLocaleString);
+        }
+
+        // {@link ArrayAdapter<T>} that hosts the instance of this class needs {@link #toString()}
+        // to get display name.
+        @Override
+        public String toString() {
+            return mDisplayName;
+        }
+
+        @Override
+        public int compareTo(final SubtypeLocaleItem o) {
+            return mLocaleString.compareTo(o.mLocaleString);
+        }
+    }
+
+    static final class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
+        private static final String TAG_SUBTYPE = SubtypeLocaleAdapter.class.getSimpleName();
+
+        public SubtypeLocaleAdapter(final Context context) {
+            super(context, android.R.layout.simple_spinner_item);
+            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+            final TreeSet<SubtypeLocaleItem> items = new TreeSet<>();
+            final InputMethodInfo imi = RichInputMethodManager.getInstance()
+                    .getInputMethodInfoOfThisIme();
+            final int count = imi.getSubtypeCount();
+            for (int i = 0; i < count; i++) {
+                final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                if (DEBUG_SUBTYPE_ID) {
+                    Log.d(TAG_SUBTYPE, String.format("%-6s 0x%08x %11d %s",
+                            subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype)));
+                }
+                if (InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)) {
+                    items.add(new SubtypeLocaleItem(subtype));
+                }
+            }
+            // TODO: Should filter out already existing combinations of locale and layout.
+            addAll(items);
+        }
+    }
+
+    static final class KeyboardLayoutSetItem {
+        public final String mLayoutName;
+        private final String mDisplayName;
+
+        public KeyboardLayoutSetItem(final InputMethodSubtype subtype) {
+            mLayoutName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
+            mDisplayName = SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
+        }
+
+        // {@link ArrayAdapter<T>} that hosts the instance of this class needs {@link #toString()}
+        // to get display name.
+        @Override
+        public String toString() {
+            return mDisplayName;
+        }
+    }
+
+    static final class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
+        public KeyboardLayoutSetAdapter(final Context context) {
+            super(context, android.R.layout.simple_spinner_item);
+            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
+            final String[] predefinedKeyboardLayoutSet = context.getResources().getStringArray(
+                    R.array.predefined_layouts);
+            // TODO: Should filter out already existing combinations of locale and layout.
+            for (final String layout : predefinedKeyboardLayoutSet) {
+                // This is a dummy subtype with NO_LANGUAGE, only for display.
+                final InputMethodSubtype subtype =
+                        AdditionalSubtypeUtils.createDummyAdditionalSubtype(
+                                SubtypeLocaleUtils.NO_LANGUAGE, layout);
+                add(new KeyboardLayoutSetItem(subtype));
+            }
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
index 9bc3986..46fcc71 100644
--- a/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CustomInputStyleSettingsFragment.java
@@ -17,37 +17,27 @@
 package com.android.inputmethod.latin.settings;
 
 import android.app.AlertDialog;
-import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.preference.DialogPreference;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.support.v4.view.ViewCompat;
 import android.text.TextUtils;
-import android.util.Pair;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-import android.widget.SpinnerAdapter;
 import android.widget.Toast;
 
-import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
-import com.android.inputmethod.compat.ViewCompatUtils;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
@@ -56,13 +46,18 @@
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.ArrayList;
-import java.util.TreeSet;
 
-public final class CustomInputStyleSettingsFragment extends PreferenceFragment {
+public final class CustomInputStyleSettingsFragment extends PreferenceFragment
+        implements CustomInputStylePreference.Listener {
+    private static final String TAG = CustomInputStyleSettingsFragment.class.getSimpleName();
+    // Note: We would like to turn this debug flag true in order to see what input styles are
+    // defined in a bug-report.
+    private static final boolean DEBUG_CUSTOM_INPUT_STYLES = true;
+
     private RichInputMethodManager mRichImm;
     private SharedPreferences mPrefs;
-    private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
-    private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
+    private CustomInputStylePreference.SubtypeLocaleAdapter mSubtypeLocaleAdapter;
+    private CustomInputStylePreference.KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
 
     private boolean mIsAddingNewSubtype;
     private AlertDialog mSubtypeEnablerNotificationDialog;
@@ -73,326 +68,6 @@
             "is_subtype_enabler_notification_dialog_open";
     private static final String KEY_SUBTYPE_FOR_SUBTYPE_ENABLER = "subtype_for_subtype_enabler";
 
-    static final class SubtypeLocaleItem extends Pair<String, String>
-            implements Comparable<SubtypeLocaleItem> {
-        public SubtypeLocaleItem(final String localeString, final String displayName) {
-            super(localeString, displayName);
-        }
-
-        public SubtypeLocaleItem(final String localeString) {
-            this(localeString,
-                    SubtypeLocaleUtils.getSubtypeLocaleDisplayNameInSystemLocale(localeString));
-        }
-
-        @Override
-        public String toString() {
-            return second;
-        }
-
-        @Override
-        public int compareTo(final SubtypeLocaleItem o) {
-            return first.compareTo(o.first);
-        }
-    }
-
-    static final class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
-        private static final String TAG = SubtypeLocaleAdapter.class.getSimpleName();
-        private static final boolean DEBUG_SUBTYPE_ID = false;
-
-        public SubtypeLocaleAdapter(final Context context) {
-            super(context, android.R.layout.simple_spinner_item);
-            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-
-            final TreeSet<SubtypeLocaleItem> items = new TreeSet<>();
-            final InputMethodInfo imi = RichInputMethodManager.getInstance()
-                    .getInputMethodInfoOfThisIme();
-            final int count = imi.getSubtypeCount();
-            for (int i = 0; i < count; i++) {
-                final InputMethodSubtype subtype = imi.getSubtypeAt(i);
-                if (DEBUG_SUBTYPE_ID) {
-                    android.util.Log.d(TAG, String.format("%-6s 0x%08x %11d %s",
-                            subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
-                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype)));
-                }
-                if (InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)) {
-                    items.add(createItem(context, subtype.getLocale()));
-                }
-            }
-            // TODO: Should filter out already existing combinations of locale and layout.
-            addAll(items);
-        }
-
-        public static SubtypeLocaleItem createItem(final Context context,
-                final String localeString) {
-            if (localeString.equals(SubtypeLocaleUtils.NO_LANGUAGE)) {
-                final String displayName = context.getString(R.string.subtype_no_language);
-                return new SubtypeLocaleItem(localeString, displayName);
-            }
-            return new SubtypeLocaleItem(localeString);
-        }
-    }
-
-    static final class KeyboardLayoutSetItem extends Pair<String, String> {
-        public KeyboardLayoutSetItem(final InputMethodSubtype subtype) {
-            super(SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype),
-                    SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype));
-        }
-
-        @Override
-        public String toString() {
-            return second;
-        }
-    }
-
-    static final class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
-        public KeyboardLayoutSetAdapter(final Context context) {
-            super(context, android.R.layout.simple_spinner_item);
-            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-
-            // TODO: Should filter out already existing combinations of locale and layout.
-            for (final String layout : SubtypeLocaleUtils.getPredefinedKeyboardLayoutSet()) {
-                // This is a dummy subtype with NO_LANGUAGE, only for display.
-                final InputMethodSubtype subtype =
-                        AdditionalSubtypeUtils.createDummyAdditionalSubtype(
-                                SubtypeLocaleUtils.NO_LANGUAGE, layout);
-                add(new KeyboardLayoutSetItem(subtype));
-            }
-        }
-    }
-
-    private interface SubtypeDialogProxy {
-        public void onRemovePressed(SubtypePreference subtypePref);
-        public void onSavePressed(SubtypePreference subtypePref);
-        public void onAddPressed(SubtypePreference subtypePref);
-        public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
-        public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
-    }
-
-    static final class SubtypePreference extends DialogPreference
-            implements DialogInterface.OnCancelListener {
-        private static final String KEY_PREFIX = "subtype_pref_";
-        private static final String KEY_NEW_SUBTYPE = KEY_PREFIX + "new";
-
-        private InputMethodSubtype mSubtype;
-        private InputMethodSubtype mPreviousSubtype;
-
-        private final SubtypeDialogProxy mProxy;
-        private Spinner mSubtypeLocaleSpinner;
-        private Spinner mKeyboardLayoutSetSpinner;
-
-        public static SubtypePreference newIncompleteSubtypePreference(final Context context,
-                final SubtypeDialogProxy proxy) {
-            return new SubtypePreference(context, null, proxy);
-        }
-
-        public SubtypePreference(final Context context, final InputMethodSubtype subtype,
-                final SubtypeDialogProxy proxy) {
-            super(context, null);
-            setDialogLayoutResource(R.layout.additional_subtype_dialog);
-            setPersistent(false);
-            mProxy = proxy;
-            setSubtype(subtype);
-        }
-
-        public void show() {
-            showDialog(null);
-        }
-
-        public final boolean isIncomplete() {
-            return mSubtype == null;
-        }
-
-        public InputMethodSubtype getSubtype() {
-            return mSubtype;
-        }
-
-        public void setSubtype(final InputMethodSubtype subtype) {
-            mPreviousSubtype = mSubtype;
-            mSubtype = subtype;
-            if (isIncomplete()) {
-                setTitle(null);
-                setDialogTitle(R.string.add_style);
-                setKey(KEY_NEW_SUBTYPE);
-            } else {
-                final String displayName =
-                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype);
-                setTitle(displayName);
-                setDialogTitle(displayName);
-                setKey(KEY_PREFIX + subtype.getLocale() + "_"
-                        + SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype));
-            }
-        }
-
-        public void revert() {
-            setSubtype(mPreviousSubtype);
-        }
-
-        public boolean hasBeenModified() {
-            return mSubtype != null && !mSubtype.equals(mPreviousSubtype);
-        }
-
-        @Override
-        protected View onCreateDialogView() {
-            final View v = super.onCreateDialogView();
-            mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
-            mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
-            mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
-            mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
-            // All keyboard layout names are in the Latin script and thus left to right. That means
-            // the view would align them to the left even if the system locale is RTL, but that
-            // would look strange. To fix this, we align them to the view's start, which will be
-            // natural for any direction.
-            ViewCompatUtils.setTextAlignment(
-                    mKeyboardLayoutSetSpinner, ViewCompatUtils.TEXT_ALIGNMENT_VIEW_START);
-            return v;
-        }
-
-        @Override
-        protected void onPrepareDialogBuilder(final AlertDialog.Builder builder) {
-            final Context context = builder.getContext();
-            builder.setCancelable(true).setOnCancelListener(this);
-            if (isIncomplete()) {
-                builder.setPositiveButton(R.string.add, this)
-                        .setNegativeButton(android.R.string.cancel, this);
-            } else {
-                builder.setPositiveButton(R.string.save, this)
-                        .setNeutralButton(android.R.string.cancel, this)
-                        .setNegativeButton(R.string.remove, this);
-                final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
-                        context, mSubtype.getLocale());
-                final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(mSubtype);
-                setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
-                setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
-            }
-        }
-
-        private static void setSpinnerPosition(final Spinner spinner, final Object itemToSelect) {
-            final SpinnerAdapter adapter = spinner.getAdapter();
-            final int count = adapter.getCount();
-            for (int i = 0; i < count; i++) {
-                final Object item = spinner.getItemAtPosition(i);
-                if (item.equals(itemToSelect)) {
-                    spinner.setSelection(i);
-                    return;
-                }
-            }
-        }
-
-        @Override
-        public void onCancel(final DialogInterface dialog) {
-            if (isIncomplete()) {
-                mProxy.onRemovePressed(this);
-            }
-        }
-
-        @Override
-        public void onClick(final DialogInterface dialog, final int which) {
-            super.onClick(dialog, which);
-            switch (which) {
-            case DialogInterface.BUTTON_POSITIVE:
-                final boolean isEditing = !isIncomplete();
-                final SubtypeLocaleItem locale =
-                        (SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
-                final KeyboardLayoutSetItem layout =
-                        (KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
-                final InputMethodSubtype subtype =
-                        AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                                locale.first, layout.first);
-                setSubtype(subtype);
-                notifyChanged();
-                if (isEditing) {
-                    mProxy.onSavePressed(this);
-                } else {
-                    mProxy.onAddPressed(this);
-                }
-                break;
-            case DialogInterface.BUTTON_NEUTRAL:
-                // Nothing to do
-                break;
-            case DialogInterface.BUTTON_NEGATIVE:
-                mProxy.onRemovePressed(this);
-                break;
-            }
-        }
-
-        private static int getSpinnerPosition(final Spinner spinner) {
-            if (spinner == null) return -1;
-            return spinner.getSelectedItemPosition();
-        }
-
-        private static void setSpinnerPosition(final Spinner spinner, final int position) {
-            if (spinner == null || position < 0) return;
-            spinner.setSelection(position);
-        }
-
-        @Override
-        protected Parcelable onSaveInstanceState() {
-            final Parcelable superState = super.onSaveInstanceState();
-            final Dialog dialog = getDialog();
-            if (dialog == null || !dialog.isShowing()) {
-                return superState;
-            }
-
-            final SavedState myState = new SavedState(superState);
-            myState.mSubtype = mSubtype;
-            myState.mSubtypeLocaleSelectedPos = getSpinnerPosition(mSubtypeLocaleSpinner);
-            myState.mKeyboardLayoutSetSelectedPos = getSpinnerPosition(mKeyboardLayoutSetSpinner);
-            return myState;
-        }
-
-        @Override
-        protected void onRestoreInstanceState(final Parcelable state) {
-            if (!(state instanceof SavedState)) {
-                super.onRestoreInstanceState(state);
-                return;
-            }
-
-            final SavedState myState = (SavedState) state;
-            super.onRestoreInstanceState(myState.getSuperState());
-            setSpinnerPosition(mSubtypeLocaleSpinner, myState.mSubtypeLocaleSelectedPos);
-            setSpinnerPosition(mKeyboardLayoutSetSpinner, myState.mKeyboardLayoutSetSelectedPos);
-            setSubtype(myState.mSubtype);
-        }
-
-        static final class SavedState extends Preference.BaseSavedState {
-            InputMethodSubtype mSubtype;
-            int mSubtypeLocaleSelectedPos;
-            int mKeyboardLayoutSetSelectedPos;
-
-            public SavedState(final Parcelable superState) {
-                super(superState);
-            }
-
-            @Override
-            public void writeToParcel(final Parcel dest, final int flags) {
-                super.writeToParcel(dest, flags);
-                dest.writeInt(mSubtypeLocaleSelectedPos);
-                dest.writeInt(mKeyboardLayoutSetSelectedPos);
-                dest.writeParcelable(mSubtype, 0);
-            }
-
-            public SavedState(final Parcel source) {
-                super(source);
-                mSubtypeLocaleSelectedPos = source.readInt();
-                mKeyboardLayoutSetSelectedPos = source.readInt();
-                mSubtype = (InputMethodSubtype)source.readParcelable(null);
-            }
-
-            public static final Parcelable.Creator<SavedState> CREATOR =
-                    new Parcelable.Creator<SavedState>() {
-                        @Override
-                        public SavedState createFromParcel(final Parcel source) {
-                            return new SavedState(source);
-                        }
-
-                        @Override
-                        public SavedState[] newArray(final int size) {
-                            return new SavedState[size];
-                        }
-                    };
-        }
-    }
-
     public CustomInputStyleSettingsFragment() {
         // Empty constructor for fragment generation.
     }
@@ -440,18 +115,22 @@
     @Override
     public void onActivityCreated(final Bundle savedInstanceState) {
         final Context context = getActivity();
-        mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
-        mKeyboardLayoutSetAdapter = new KeyboardLayoutSetAdapter(context);
+        mSubtypeLocaleAdapter = new CustomInputStylePreference.SubtypeLocaleAdapter(context);
+        mKeyboardLayoutSetAdapter =
+                new CustomInputStylePreference.KeyboardLayoutSetAdapter(context);
 
         final String prefSubtypes =
                 Settings.readPrefAdditionalSubtypes(mPrefs, getResources());
+        if (DEBUG_CUSTOM_INPUT_STYLES) {
+            Log.i(TAG, "Load custom input styles: " + prefSubtypes);
+        }
         setPrefSubtypes(prefSubtypes, context);
 
         mIsAddingNewSubtype = (savedInstanceState != null)
                 && savedInstanceState.containsKey(KEY_IS_ADDING_NEW_SUBTYPE);
         if (mIsAddingNewSubtype) {
             getPreferenceScreen().addPreference(
-                    SubtypePreference.newIncompleteSubtypePreference(context, mSubtypeProxy));
+                    CustomInputStylePreference.newIncompleteSubtypePreference(context, this));
         }
 
         super.onActivityCreated(savedInstanceState);
@@ -460,8 +139,6 @@
                 KEY_IS_SUBTYPE_ENABLER_NOTIFICATION_DIALOG_OPEN)) {
             mSubtypePreferenceKeyForSubtypeEnabler = savedInstanceState.getString(
                     KEY_SUBTYPE_FOR_SUBTYPE_ENABLER);
-            final SubtypePreference subtypePref = (SubtypePreference)findPreference(
-                    mSubtypePreferenceKeyForSubtypeEnabler);
             mSubtypeEnablerNotificationDialog = createDialog();
             mSubtypeEnablerNotificationDialog.show();
         }
@@ -481,62 +158,60 @@
         }
     }
 
-    private final SubtypeDialogProxy mSubtypeProxy = new SubtypeDialogProxy() {
-        @Override
-        public void onRemovePressed(final SubtypePreference subtypePref) {
-            mIsAddingNewSubtype = false;
-            final PreferenceGroup group = getPreferenceScreen();
-            group.removePreference(subtypePref);
+    @Override
+    public void onRemoveCustomInputStyle(final CustomInputStylePreference stylePref) {
+        mIsAddingNewSubtype = false;
+        final PreferenceGroup group = getPreferenceScreen();
+        group.removePreference(stylePref);
+        mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
+    }
+
+    @Override
+    public void onSaveCustomInputStyle(final CustomInputStylePreference stylePref) {
+        final InputMethodSubtype subtype = stylePref.getSubtype();
+        if (!stylePref.hasBeenModified()) {
+            return;
+        }
+        if (findDuplicatedSubtype(subtype) == null) {
             mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
+            return;
         }
 
-        @Override
-        public void onSavePressed(final SubtypePreference subtypePref) {
-            final InputMethodSubtype subtype = subtypePref.getSubtype();
-            if (!subtypePref.hasBeenModified()) {
-                return;
-            }
-            if (findDuplicatedSubtype(subtype) == null) {
-                mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
-                return;
-            }
+        // Saved subtype is duplicated.
+        final PreferenceGroup group = getPreferenceScreen();
+        group.removePreference(stylePref);
+        stylePref.revert();
+        group.addPreference(stylePref);
+        showSubtypeAlreadyExistsToast(subtype);
+    }
 
-            // Saved subtype is duplicated.
-            final PreferenceGroup group = getPreferenceScreen();
-            group.removePreference(subtypePref);
-            subtypePref.revert();
-            group.addPreference(subtypePref);
-            showSubtypeAlreadyExistsToast(subtype);
+    @Override
+    public void onAddCustomInputStyle(final CustomInputStylePreference stylePref) {
+        mIsAddingNewSubtype = false;
+        final InputMethodSubtype subtype = stylePref.getSubtype();
+        if (findDuplicatedSubtype(subtype) == null) {
+            mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
+            mSubtypePreferenceKeyForSubtypeEnabler = stylePref.getKey();
+            mSubtypeEnablerNotificationDialog = createDialog();
+            mSubtypeEnablerNotificationDialog.show();
+            return;
         }
 
-        @Override
-        public void onAddPressed(final SubtypePreference subtypePref) {
-            mIsAddingNewSubtype = false;
-            final InputMethodSubtype subtype = subtypePref.getSubtype();
-            if (findDuplicatedSubtype(subtype) == null) {
-                mRichImm.setAdditionalInputMethodSubtypes(getSubtypes());
-                mSubtypePreferenceKeyForSubtypeEnabler = subtypePref.getKey();
-                mSubtypeEnablerNotificationDialog = createDialog();
-                mSubtypeEnablerNotificationDialog.show();
-                return;
-            }
+        // Newly added subtype is duplicated.
+        final PreferenceGroup group = getPreferenceScreen();
+        group.removePreference(stylePref);
+        showSubtypeAlreadyExistsToast(subtype);
+    }
 
-            // Newly added subtype is duplicated.
-            final PreferenceGroup group = getPreferenceScreen();
-            group.removePreference(subtypePref);
-            showSubtypeAlreadyExistsToast(subtype);
-        }
+    @Override
+    public CustomInputStylePreference.SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
+        return mSubtypeLocaleAdapter;
+    }
 
-        @Override
-        public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
-            return mSubtypeLocaleAdapter;
-        }
-
-        @Override
-        public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
-            return mKeyboardLayoutSetAdapter;
-        }
-    };
+    @Override
+    public CustomInputStylePreference.KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
+        return mKeyboardLayoutSetAdapter;
+    }
 
     private void showSubtypeAlreadyExistsToast(final InputMethodSubtype subtype) {
         final Context context = getActivity();
@@ -554,6 +229,7 @@
     }
 
     private AlertDialog createDialog() {
+        final String imeId = mRichImm.getInputMethodIdOfThisIme();
         final AlertDialog.Builder builder = new AlertDialog.Builder(
                 DialogUtils.getPlatformDialogThemeContext(getActivity()));
         builder.setTitle(R.string.custom_input_styles_title)
@@ -563,7 +239,7 @@
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
-                                mRichImm.getInputMethodIdOfThisIme(),
+                                imeId,
                                 Intent.FLAG_ACTIVITY_NEW_TASK
                                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -583,8 +259,8 @@
         final InputMethodSubtype[] subtypesArray =
                 AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtypes);
         for (final InputMethodSubtype subtype : subtypesArray) {
-            final SubtypePreference pref = new SubtypePreference(
-                    context, subtype, mSubtypeProxy);
+            final CustomInputStylePreference pref =
+                    new CustomInputStylePreference(context, subtype, this);
             group.addPreference(pref);
         }
     }
@@ -595,8 +271,8 @@
         final int count = group.getPreferenceCount();
         for (int i = 0; i < count; i++) {
             final Preference pref = group.getPreference(i);
-            if (pref instanceof SubtypePreference) {
-                final SubtypePreference subtypePref = (SubtypePreference)pref;
+            if (pref instanceof CustomInputStylePreference) {
+                final CustomInputStylePreference subtypePref = (CustomInputStylePreference)pref;
                 // We should not save newly adding subtype to preference because it is incomplete.
                 if (subtypePref.isIncomplete()) continue;
                 subtypes.add(subtypePref.getSubtype());
@@ -611,6 +287,9 @@
         final String oldSubtypes = Settings.readPrefAdditionalSubtypes(mPrefs, getResources());
         final InputMethodSubtype[] subtypes = getSubtypes();
         final String prefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(subtypes);
+        if (DEBUG_CUSTOM_INPUT_STYLES) {
+            Log.i(TAG, "Save custom input styles: " + prefSubtypes);
+        }
         if (prefSubtypes.equals(oldSubtypes)) {
             return;
         }
@@ -627,8 +306,8 @@
     public boolean onOptionsItemSelected(final MenuItem item) {
         final int itemId = item.getItemId();
         if (itemId == R.id.action_add_style) {
-            final SubtypePreference newSubtype =
-                    SubtypePreference.newIncompleteSubtypePreference(getActivity(), mSubtypeProxy);
+            final CustomInputStylePreference newSubtype =
+                    CustomInputStylePreference.newIncompleteSubtypePreference(getActivity(), this);
             getPreferenceScreen().addPreference(newSubtype);
             newSubtype.show();
             mIsAddingNewSubtype = true;
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index 48f4c75..6fffb8e 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -16,29 +16,36 @@
 
 package com.android.inputmethod.latin.settings;
 
+/**
+ * Debug settings for the application.
+ *
+ * Note: Even though these settings are stored in the default shared preferences file,
+ * they shouldn't be restored across devices.
+ * If a new key is added here, it should also be blacklisted for restore in
+ * {@link LocalSettingsConstants}.
+ */
 public final class DebugSettings {
     public static final String PREF_DEBUG_MODE = "debug_mode";
     public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
-    public static final String PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY =
-            "force_physical_keyboard_special_key";
-    public static final String PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD =
-            "pref_show_ui_to_accept_typed_word";
     public static final String PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS =
             "pref_has_custom_key_preview_animation_params";
-    public static final String PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE =
-            "pref_key_preview_show_up_start_x_scale";
-    public static final String PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE =
-            "pref_key_preview_show_up_start_y_scale";
+    public static final String PREF_RESIZE_KEYBOARD = "pref_resize_keyboard";
+    public static final String PREF_KEYBOARD_HEIGHT_SCALE = "pref_keyboard_height_scale";
+    public static final String PREF_KEY_PREVIEW_DISMISS_DURATION =
+            "pref_key_preview_dismiss_duration";
     public static final String PREF_KEY_PREVIEW_DISMISS_END_X_SCALE =
             "pref_key_preview_dismiss_end_x_scale";
     public static final String PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE =
             "pref_key_preview_dismiss_end_y_scale";
     public static final String PREF_KEY_PREVIEW_SHOW_UP_DURATION =
             "pref_key_preview_show_up_duration";
-    public static final String PREF_KEY_PREVIEW_DISMISS_DURATION =
-            "pref_key_preview_dismiss_duration";
+    public static final String PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE =
+            "pref_key_preview_show_up_start_x_scale";
+    public static final String PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE =
+            "pref_key_preview_show_up_start_y_scale";
+    public static final String PREF_SHOULD_SHOW_LXX_SUGGESTION_UI =
+            "pref_should_show_lxx_suggestion_ui";
     public static final String PREF_SLIDING_KEY_INPUT_PREVIEW = "pref_sliding_key_input_preview";
-    public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
 
     private DebugSettings() {
         // This class is not publicly instantiable.
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
index 5640e20..3785537 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettingsFragment.java
@@ -28,9 +28,8 @@
 import android.preference.TwoStatePreference;
 
 import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
-import com.android.inputmethod.latin.DictionaryFacilitator;
+import com.android.inputmethod.latin.DictionaryFacilitatorImpl;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.debug.ExternalDictionaryGetterForDebug;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 
@@ -43,12 +42,10 @@
  */
 public final class DebugSettingsFragment extends SubScreenFragment
         implements OnPreferenceClickListener {
-    private static final String PREF_READ_EXTERNAL_DICTIONARY = "read_external_dictionary";
     private static final String PREF_KEY_DUMP_DICTS = "pref_key_dump_dictionaries";
     private static final String PREF_KEY_DUMP_DICT_PREFIX = "pref_key_dump_dictionaries";
 
     private boolean mServiceNeedsRestart = false;
-    private Preference mReadExternalDictionaryPref;
     private TwoStatePreference mDebugMode;
 
     @Override
@@ -56,24 +53,18 @@
         super.onCreate(icicle);
         addPreferencesFromResource(R.xml.prefs_screen_debug);
 
-        if (!Settings.HAS_UI_TO_ACCEPT_TYPED_WORD) {
-            removePreference(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD);
-        }
-
-        mReadExternalDictionaryPref = findPreference(PREF_READ_EXTERNAL_DICTIONARY);
-        if (mReadExternalDictionaryPref != null) {
-            mReadExternalDictionaryPref.setOnPreferenceClickListener(this);
+        if (!Settings.SHOULD_SHOW_LXX_SUGGESTION_UI) {
+            removePreference(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI);
         }
 
         final PreferenceGroup dictDumpPreferenceGroup =
                 (PreferenceGroup)findPreference(PREF_KEY_DUMP_DICTS);
-        for (final String dictName : DictionaryFacilitator.DICT_TYPE_TO_CLASS.keySet()) {
+        for (final String dictName : DictionaryFacilitatorImpl.DICT_TYPE_TO_CLASS.keySet()) {
             final Preference pref = new DictDumpPreference(getActivity(), dictName);
             pref.setOnPreferenceClickListener(this);
             dictDumpPreferenceGroup.addPreference(pref);
         }
         final Resources res = getResources();
-        setupKeyLongpressTimeoutSettings();
         setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
                 res.getInteger(R.integer.config_key_preview_show_up_duration));
         setupKeyPreviewAnimationDuration(DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
@@ -90,6 +81,8 @@
                 defaultKeyPreviewDismissEndScale);
         setupKeyPreviewAnimationScale(DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
                 defaultKeyPreviewDismissEndScale);
+        setupKeyboardHeight(
+                DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, SettingsValues.DEFAULT_SIZE_SCALE);
 
         mServiceNeedsRestart = false;
         mDebugMode = (TwoStatePreference) findPreference(DebugSettings.PREF_DEBUG_MODE);
@@ -110,11 +103,6 @@
     @Override
     public boolean onPreferenceClick(final Preference pref) {
         final Context context = getActivity();
-        if (pref == mReadExternalDictionaryPref) {
-            ExternalDictionaryGetterForDebug.chooseAndInstallDictionary(context);
-            mServiceNeedsRestart = true;
-            return true;
-        }
         if (pref instanceof DictDumpPreference) {
             final DictDumpPreference dictDumpPref = (DictDumpPreference)pref;
             final String dictName = dictDumpPref.mDictName;
@@ -143,8 +131,7 @@
             mServiceNeedsRestart = true;
             return;
         }
-        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)
-                || key.equals(DebugSettings.PREF_FORCE_PHYSICAL_KEYBOARD_SPECIAL_KEY)) {
+        if (key.equals(DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH)) {
             mServiceNeedsRestart = true;
             return;
         }
@@ -163,45 +150,6 @@
         }
     }
 
-    private void setupKeyLongpressTimeoutSettings() {
-        final SharedPreferences prefs = getSharedPreferences();
-        final Resources res = getResources();
-        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(
-                DebugSettings.PREF_KEY_LONGPRESS_TIMEOUT);
-        if (pref == null) {
-            return;
-        }
-        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
-            @Override
-            public void writeValue(final int value, final String key) {
-                prefs.edit().putInt(key, value).apply();
-            }
-
-            @Override
-            public void writeDefaultValue(final String key) {
-                prefs.edit().remove(key).apply();
-            }
-
-            @Override
-            public int readValue(final String key) {
-                return Settings.readKeyLongpressTimeout(prefs, res);
-            }
-
-            @Override
-            public int readDefaultValue(final String key) {
-                return Settings.readDefaultKeyLongpressTimeout(res);
-            }
-
-            @Override
-            public String getValueText(final int value) {
-                return res.getString(R.string.abbreviation_unit_milliseconds, value);
-            }
-
-            @Override
-            public void feedbackValue(final int value) {}
-        });
-    }
-
     private void setupKeyPreviewAnimationScale(final String prefKey, final float defaultValue) {
         final SharedPreferences prefs = getSharedPreferences();
         final Resources res = getResources();
@@ -291,4 +239,50 @@
             public void feedbackValue(final int value) {}
         });
     }
+
+    private void setupKeyboardHeight(final String prefKey, final float defaultValue) {
+        final SharedPreferences prefs = getSharedPreferences();
+        final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference(prefKey);
+        if (pref == null) {
+            return;
+        }
+        pref.setInterface(new SeekBarDialogPreference.ValueProxy() {
+            private static final float PERCENTAGE_FLOAT = 100.0f;
+            private float getValueFromPercentage(final int percentage) {
+                return percentage / PERCENTAGE_FLOAT;
+            }
+
+            private int getPercentageFromValue(final float floatValue) {
+                return (int)(floatValue * PERCENTAGE_FLOAT);
+            }
+
+            @Override
+            public void writeValue(final int value, final String key) {
+                prefs.edit().putFloat(key, getValueFromPercentage(value)).apply();
+            }
+
+            @Override
+            public void writeDefaultValue(final String key) {
+                prefs.edit().remove(key).apply();
+            }
+
+            @Override
+            public int readValue(final String key) {
+                return getPercentageFromValue(Settings.readKeyboardHeight(prefs, defaultValue));
+            }
+
+            @Override
+            public int readDefaultValue(final String key) {
+                return getPercentageFromValue(defaultValue);
+            }
+
+            @Override
+            public String getValueText(final int value) {
+                return String.format(Locale.ROOT, "%d%%", value);
+            }
+
+            @Override
+            public void feedbackValue(final int value) {}
+        });
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
index 832fbf6..22b0655 100644
--- a/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/GestureSettingsFragment.java
@@ -16,7 +16,6 @@
 
 package com.android.inputmethod.latin.settings;
 
-import android.content.SharedPreferences;
 import android.os.Bundle;
 
 import com.android.inputmethod.latin.R;
diff --git a/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java
new file mode 100644
index 0000000..5c416ab
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/LocalSettingsConstants.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+/**
+ * Collection of device specific preference constants.
+ */
+public class LocalSettingsConstants {
+    // Preference file for storing preferences that are tied to a device
+    // and are not backed up.
+    public static final String PREFS_FILE = "local_prefs";
+
+    // Preference key for the current account.
+    // Do not restore.
+    public static final String PREF_ACCOUNT_NAME = "pref_account_name";
+    // Preference key for enabling cloud sync feature.
+    // Do not restore.
+    public static final String PREF_ENABLE_CLOUD_SYNC = "pref_enable_cloud_sync";
+
+    // List of preference keys to skip from being restored by backup agent.
+    // These preferences are tied to a device and hence should not be restored.
+    // e.g. account name.
+    // Ideally they could have been kept in a separate file that wasn't backed up
+    // however the preference UI currently only deals with the default
+    // shared preferences which makes it non-trivial to move these out to
+    // a different shared preferences file.
+    public static final String[] PREFS_TO_SKIP_RESTORING = new String[] {
+        PREF_ACCOUNT_NAME,
+        PREF_ENABLE_CLOUD_SYNC,
+        // The debug settings are not restored on a new device.
+        // If a feature relies on these, it should ensure that the defaults are
+        // correctly set for it to work on a new device.
+        DebugSettings.PREF_DEBUG_MODE,
+        DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH,
+        DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS,
+        DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE,
+        DebugSettings.PREF_KEY_PREVIEW_DISMISS_DURATION,
+        DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_X_SCALE,
+        DebugSettings.PREF_KEY_PREVIEW_DISMISS_END_Y_SCALE,
+        DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
+        DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_X_SCALE,
+        DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_START_Y_SCALE,
+        DebugSettings.PREF_RESIZE_KEYBOARD,
+        DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI,
+        DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW
+    };
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
deleted file mode 100644
index b073c50..0000000
--- a/java/src/com/android/inputmethod/latin/settings/MultiLingualSettingsFragment.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 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.settings;
-
-import android.os.Bundle;
-
-import com.android.inputmethod.latin.R;
-
-import java.util.ArrayList;
-
-/**
- * "Multilingual options" settings sub screen.
- *
- * This settings sub screen handles the following input preferences.
- * - Language switch key
- * - Switch to other input methods
- */
-public final class MultiLingualSettingsFragment extends SubScreenFragment {
-    @Override
-    public void onCreate(final Bundle icicle) {
-        super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.prefs_screen_multilingual);
-        if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
-            removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY);
-            removePreference(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST);
-        }
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java b/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java
deleted file mode 100644
index 31a20c4..0000000
--- a/java/src/com/android/inputmethod/latin/settings/NativeSuggestOptions.java
+++ /dev/null
@@ -1,66 +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.settings;
-
-public class NativeSuggestOptions {
-    // Need to update suggest_options.h when you add, remove or reorder options.
-    private static final int IS_GESTURE = 0;
-    private static final int USE_FULL_EDIT_DISTANCE = 1;
-    private static final int BLOCK_OFFENSIVE_WORDS = 2;
-    private static final int SPACE_AWARE_GESTURE_ENABLED = 3;
-    private static final int OPTIONS_SIZE = 4;
-
-    private final int[] mOptions = new int[OPTIONS_SIZE
-            + AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE];
-
-    public void setIsGesture(final boolean value) {
-        setBooleanOption(IS_GESTURE, value);
-    }
-
-    public void setUseFullEditDistance(final boolean value) {
-        setBooleanOption(USE_FULL_EDIT_DISTANCE, value);
-    }
-
-    public void setBlockOffensiveWords(final boolean value) {
-        setBooleanOption(BLOCK_OFFENSIVE_WORDS, value);
-    }
-
-    public void setSpaceAwareGestureEnabled(final boolean value) {
-        setBooleanOption(SPACE_AWARE_GESTURE_ENABLED, value);
-    }
-
-    public void setAdditionalFeaturesOptions(final int[] additionalOptions) {
-        if (additionalOptions == null) {
-            return;
-        }
-        for (int i = 0; i < additionalOptions.length; i++) {
-            setIntegerOption(OPTIONS_SIZE + i, additionalOptions[i]);
-        }
-    }
-
-    public int[] getOptions() {
-        return mOptions;
-    }
-
-    private void setBooleanOption(final int key, final boolean value) {
-        mOptions[key] = value ? 1 : 0;
-    }
-
-    private void setIntegerOption(final int key, final int value) {
-        mOptions[key] = value;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
index 49db2bd..d9858e6 100644
--- a/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/PreferencesSettingsFragment.java
@@ -19,12 +19,13 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.Preference;
 
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SubtypeSwitcher;
+import com.android.inputmethod.latin.RichInputMethodManager;
 
 /**
  * "Preferences" settings sub screen.
@@ -38,6 +39,10 @@
  * - Voice input key
  */
 public final class PreferencesSettingsFragment extends SubScreenFragment {
+
+    private static final boolean VOICE_IME_ENABLED =
+            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
+
     @Override
     public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
@@ -49,7 +54,7 @@
         // When we are called from the Settings application but we are not already running, some
         // singleton and utility classes may not have been initialized.  We have to call
         // initialization method of these classes here. See {@link LatinIME#onCreate()}.
-        SubtypeSwitcher.init(context);
+        RichInputMethodManager.init(context);
 
         final boolean showVoiceKeyOption = res.getBoolean(
                 R.bool.config_enable_show_voice_key_option);
@@ -71,11 +76,10 @@
         super.onResume();
         final Preference voiceInputKeyOption = findPreference(Settings.PREF_VOICE_INPUT_KEY);
         if (voiceInputKeyOption != null) {
-            final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance()
-                    .isShortcutImeEnabled();
-            voiceInputKeyOption.setEnabled(isShortcutImeEnabled);
-            voiceInputKeyOption.setSummary(
-                    isShortcutImeEnabled ? null : getText(R.string.voice_input_disabled_summary));
+            RichInputMethodManager.getInstance().refreshSubtypeCaches();
+            voiceInputKeyOption.setEnabled(VOICE_IME_ENABLED);
+            voiceInputKeyOption.setSummary(VOICE_IME_ENABLED
+                    ? null : getText(R.string.voice_input_disabled_summary));
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
index c173d47..9144460 100644
--- a/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
+++ b/java/src/com/android/inputmethod/latin/settings/RadioButtonPreference.java
@@ -43,9 +43,7 @@
     private final View.OnClickListener mClickListener = new View.OnClickListener() {
         @Override
         public void onClick(final View v) {
-            if (mListener != null) {
-                mListener.onRadioButtonClicked(RadioButtonPreference.this);
-            }
+            callListenerOnRadioButtonClicked();
         }
     };
 
@@ -67,6 +65,12 @@
         mListener = listener;
     }
 
+    void callListenerOnRadioButtonClicked() {
+        if (mListener != null) {
+            mListener.onRadioButtonClicked(this);
+        }
+    }
+
     @Override
     protected void onBindView(final View view) {
         super.onBindView(view);
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 0de2d88..715f7bb 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.os.Build;
@@ -29,26 +28,24 @@
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
 import com.android.inputmethod.latin.InputAttributes;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.RunInLocale;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.utils.StatsUtils;
 
 import java.util.Collections;
 import java.util.Locale;
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
+import javax.annotation.Nonnull;
+
 public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = Settings.class.getSimpleName();
     // Settings screens
-    public static final String SCREEN_PREFERENCES = "screen_preferences";
-    public static final String SCREEN_APPEARANCE = "screen_appearance";
+    public static final String SCREEN_ACCOUNTS = "screen_accounts";
     public static final String SCREEN_THEME = "screen_theme";
-    public static final String SCREEN_MULTILINGUAL = "screen_multilingual";
-    public static final String SCREEN_GESTURE = "screen_gesture";
-    public static final String SCREEN_CORRECTION = "screen_correction";
-    public static final String SCREEN_ADVANCED = "screen_advanced";
     public static final String SCREEN_DEBUG = "screen_debug";
     // In the same order as xml/prefs.xml
     public static final String PREF_AUTO_CAP = "auto_cap";
@@ -60,7 +57,10 @@
     public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key";
     public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
     public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
-    public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
+    // PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE is obsolete. Use PREF_AUTO_CORRECTION instead.
+    public static final String PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE =
+            "auto_correction_threshold";
+    public static final String PREF_AUTO_CORRECTION = "pref_key_auto_correction";
     // PREF_SHOW_SUGGESTIONS_SETTING_OBSOLETE is obsolete. Use PREF_SHOW_SUGGESTIONS instead.
     public static final String PREF_SHOW_SUGGESTIONS_SETTING_OBSOLETE = "show_suggestions_setting";
     public static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
@@ -70,19 +70,16 @@
             "pref_key_use_double_space_period";
     public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE =
             "pref_key_block_potentially_offensive";
-    // No multilingual options in Android L and above for now.
-    public static final boolean SHOW_MULTILINGUAL_SETTINGS =
-            BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
     public static final boolean ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS =
             BuildCompatUtils.EFFECTIVE_SDK_INT <= Build.VERSION_CODES.KITKAT;
-    public static final boolean HAS_UI_TO_ACCEPT_TYPED_WORD =
-            BuildCompatUtils.EFFECTIVE_SDK_INT >= BuildCompatUtils.VERSION_CODES_LXX;
+    public static final boolean SHOULD_SHOW_LXX_SUGGESTION_UI =
+            BuildCompatUtils.EFFECTIVE_SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
     public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY =
             "pref_show_language_switch_key";
     public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST =
             "pref_include_other_imes_in_language_switch_list";
-    public static final String PREF_KEYBOARD_THEME = "pref_keyboard_theme";
     public static final String PREF_CUSTOM_INPUT_STYLES = "custom_input_styles";
+    public static final String PREF_ENABLE_SPLIT_KEYBOARD = "pref_split_keyboard";
     // TODO: consolidate key preview dismiss delay with the key preview animation parameters.
     public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
             "pref_key_preview_popup_dismiss_delay";
@@ -90,20 +87,17 @@
     public static final String PREF_GESTURE_INPUT = "gesture_input";
     public static final String PREF_VIBRATION_DURATION_SETTINGS =
             "pref_vibration_duration_settings";
-    public static final String PREF_KEYPRESS_SOUND_VOLUME =
-            "pref_keypress_sound_volume";
+    public static final String PREF_KEYPRESS_SOUND_VOLUME = "pref_keypress_sound_volume";
+    public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
+    public static final String PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY =
+            "pref_enable_emoji_alt_physical_key";
     public static final String PREF_GESTURE_PREVIEW_TRAIL = "pref_gesture_preview_trail";
     public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT =
             "pref_gesture_floating_preview_text";
-    public static final String PREF_SHOW_SETUP_WIZARD_ICON = "pref_show_setup_wizard_icon";
-    public static final String PREF_PHRASE_GESTURE_ENABLED = "pref_gesture_space_aware";
 
-    public static final String PREF_INPUT_LANGUAGE = "input_language";
-    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
     public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal";
 
     public static final String PREF_ENABLE_METRICS_LOGGING = "pref_enable_metrics_logging";
-
     // This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
     // This is being used only for the backward compatibility.
     private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
@@ -149,6 +143,7 @@
         mRes = context.getResources();
         mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
         mPrefs.registerOnSharedPreferenceChangeListener(this);
+        upgradeAutocorrectionSettings(mPrefs, mRes);
     }
 
     public void onDestroy() {
@@ -166,13 +161,14 @@
                 return;
             }
             loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
+            StatsUtils.onLoadSettings(mSettingsValues);
         } finally {
             mSettingsValuesLock.unlock();
         }
     }
 
     public void loadSettings(final Context context, final Locale locale,
-            final InputAttributes inputAttributes) {
+            @Nonnull final InputAttributes inputAttributes) {
         mSettingsValuesLock.lock();
         mContext = context;
         try {
@@ -198,12 +194,8 @@
         return mSettingsValues.mIsInternal;
     }
 
-    public boolean isWordSeparator(final int code) {
-        return mSettingsValues.isWordSeparator(code);
-    }
-
-    public boolean getBlockPotentiallyOffensive() {
-        return mSettingsValues.mBlockPotentiallyOffensive;
+    public static int readScreenMetrics(final Resources res) {
+        return res.getInteger(R.integer.config_screen_metrics);
     }
 
     // Accessed from the settings interface, hence public
@@ -220,11 +212,13 @@
                 res.getBoolean(R.bool.config_default_vibration_enabled));
     }
 
-    public static boolean readAutoCorrectEnabled(final String currentAutoCorrectionSetting,
+    public static boolean readAutoCorrectEnabled(final SharedPreferences prefs,
             final Resources res) {
-        final String autoCorrectionOff = res.getString(
-                R.string.auto_correction_threshold_mode_index_off);
-        return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
+        return prefs.getBoolean(PREF_AUTO_CORRECTION, true);
+    }
+
+    public static float readPlausibilityThreshold(final Resources res) {
+        return Float.parseFloat(res.getString(R.string.plausibility_threshold));
     }
 
     public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs,
@@ -243,12 +237,6 @@
                 && prefs.getBoolean(PREF_GESTURE_INPUT, true);
     }
 
-    public static boolean readPhraseGestureEnabled(final SharedPreferences prefs,
-            final Resources res) {
-        return prefs.getBoolean(PREF_PHRASE_GESTURE_ENABLED,
-                res.getBoolean(R.bool.config_default_phrase_gesture_enabled));
-    }
-
     public static boolean readFromBuildConfigIfToShowKeyPreviewPopupOption(final Resources res) {
         return res.getBoolean(R.bool.config_enable_show_key_preview_popup_option);
     }
@@ -314,7 +302,7 @@
     public static int readKeyLongpressTimeout(final SharedPreferences prefs,
             final Resources res) {
         final int milliseconds = prefs.getInt(
-                DebugSettings.PREF_KEY_LONGPRESS_TIMEOUT, UNDEFINED_PREFERENCE_VALUE_INT);
+                PREF_KEY_LONGPRESS_TIMEOUT, UNDEFINED_PREFERENCE_VALUE_INT);
         return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
                 : readDefaultKeyLongpressTimeout(res);
     }
@@ -352,25 +340,15 @@
         return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue;
     }
 
-    public static boolean readUseFullscreenMode(final Resources res) {
-        return res.getBoolean(R.bool.config_use_fullscreen_mode);
+    public static float readKeyboardHeight(final SharedPreferences prefs,
+            final float defaultValue) {
+        final float percentage = prefs.getFloat(
+                DebugSettings.PREF_KEYBOARD_HEIGHT_SCALE, UNDEFINED_PREFERENCE_VALUE_FLOAT);
+        return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
     }
 
-    public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
-            final Context context) {
-        final boolean enableSetupWizardByConfig = context.getResources().getBoolean(
-                R.bool.config_setup_wizard_available);
-        if (!enableSetupWizardByConfig) {
-            return false;
-        }
-        if (!prefs.contains(PREF_SHOW_SETUP_WIZARD_ICON)) {
-            final ApplicationInfo appInfo = context.getApplicationInfo();
-            final boolean isApplicationInSystemImage =
-                    (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-            // Default value
-            return !isApplicationInSystemImage;
-        }
-        return prefs.getBoolean(PREF_SHOW_SETUP_WIZARD_ICON, false);
+    public static boolean readUseFullscreenMode(final Resources res) {
+        return res.getBoolean(R.bool.config_use_fullscreen_mode);
     }
 
     public static boolean readHasHardwareKeyboard(final Configuration conf) {
@@ -446,4 +424,21 @@
             final SharedPreferences prefs, final int defValue) {
         return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, defValue);
     }
+
+    private void upgradeAutocorrectionSettings(final SharedPreferences prefs, final Resources res) {
+        final String thresholdSetting =
+                prefs.getString(PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE, null);
+        if (thresholdSetting != null) {
+            SharedPreferences.Editor editor = prefs.edit();
+            editor.remove(PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE);
+            final String autoCorrectionOff =
+                    res.getString(R.string.auto_correction_threshold_mode_index_off);
+            if (thresholdSetting.equals(autoCorrectionOff)) {
+                editor.putBoolean(PREF_AUTO_CORRECTION, false);
+            } else {
+                editor.putBoolean(PREF_AUTO_CORRECTION, true);
+            }
+            editor.commit();
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
index b0c4940..9975277 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
@@ -17,6 +17,8 @@
 package com.android.inputmethod.latin.settings;
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
+import com.android.inputmethod.latin.utils.StatsUtils;
+import com.android.inputmethod.latin.utils.StatsUtilsManager;
 
 import android.app.ActionBar;
 import android.content.Intent;
@@ -25,19 +27,30 @@
 import android.view.MenuItem;
 
 public final class SettingsActivity extends PreferenceActivity {
-    public static final String EXTRA_SHOW_HOME_AS_UP = "show_home_as_up";
     private static final String DEFAULT_FRAGMENT = SettingsFragment.class.getName();
+
+    public static final String EXTRA_SHOW_HOME_AS_UP = "show_home_as_up";
+    public static final String EXTRA_ENTRY_KEY = "entry";
+    public static final String EXTRA_ENTRY_VALUE_LONG_PRESS_COMMA = "long_press_comma";
+    public static final String EXTRA_ENTRY_VALUE_APP_ICON = "app_icon";
+    public static final String EXTRA_ENTRY_VALUE_NOTICE_DIALOG = "important_notice";
+    public static final String EXTRA_ENTRY_VALUE_SYSTEM_SETTINGS = "system_settings";
+
     private boolean mShowHomeAsUp;
 
     @Override
     protected void onCreate(final Bundle savedState) {
         super.onCreate(savedState);
         final ActionBar actionBar = getActionBar();
+        final Intent intent = getIntent();
         if (actionBar != null) {
-            mShowHomeAsUp = getIntent().getBooleanExtra(EXTRA_SHOW_HOME_AS_UP, true);
+            mShowHomeAsUp = intent.getBooleanExtra(EXTRA_SHOW_HOME_AS_UP, true);
             actionBar.setDisplayHomeAsUpEnabled(mShowHomeAsUp);
             actionBar.setHomeButtonEnabled(mShowHomeAsUp);
         }
+        StatsUtils.onSettingsActivity(
+                intent.hasExtra(EXTRA_ENTRY_KEY) ? intent.getStringExtra(EXTRA_ENTRY_KEY)
+                        : EXTRA_ENTRY_VALUE_SYSTEM_SETTINGS);
     }
 
     @Override
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index 6c8ab57..f5455e3 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -27,6 +27,7 @@
 import android.view.MenuItem;
 
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.define.ProductionFlags;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 import com.android.inputmethod.latin.utils.FeedbackUtils;
 import com.android.inputmethodcommon.InputMethodSettingsFragment;
@@ -49,9 +50,9 @@
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
         preferenceScreen.setTitle(
                 ApplicationUtils.getActivityTitleResId(getActivity(), SettingsActivity.class));
-        if (!Settings.SHOW_MULTILINGUAL_SETTINGS) {
-            final Preference multilingualOptions = findPreference(Settings.SCREEN_MULTILINGUAL);
-            preferenceScreen.removePreference(multilingualOptions);
+        if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
+            final Preference accountsPreference = findPreference(Settings.SCREEN_ACCOUNTS);
+            preferenceScreen.removePreference(accountsPreference);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index d8c548d..d112e72 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.Build;
 import android.util.Log;
 import android.view.inputmethod.EditorInfo;
 
@@ -28,7 +29,6 @@
 import com.android.inputmethod.latin.InputAttributes;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.SubtypeSwitcher;
 import com.android.inputmethod.latin.utils.AsyncResultHolder;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
@@ -36,17 +36,22 @@
 import java.util.Arrays;
 import java.util.Locale;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * When you call the constructor of this class, you may want to change the current system locale by
  * using {@link com.android.inputmethod.latin.utils.RunInLocale}.
  */
-public final class SettingsValues {
+// Non-final for testing via mock library.
+public class SettingsValues {
     private static final String TAG = SettingsValues.class.getSimpleName();
     // "floatMaxValue" and "floatNegativeInfinity" are special marker strings for
     // Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings.
     private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue";
     private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity";
     private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds
+    public static final float DEFAULT_SIZE_SCALE = 1.0f; // 100%
 
     // From resources:
     public final SpacingAndPunctuations mSpacingAndPunctuations;
@@ -74,12 +79,17 @@
     public final boolean mGestureTrailEnabled;
     public final boolean mGestureFloatingPreviewTextEnabled;
     public final boolean mSlidingKeyInputPreviewEnabled;
-    public final boolean mPhraseGestureEnabled;
     public final int mKeyLongpressTimeout;
+    public final boolean mEnableEmojiAltPhysicalKey;
+    public final boolean mCloudSyncEnabled;
     public final boolean mEnableMetricsLogging;
-    public final boolean mShouldShowUiToAcceptTypedWord;
+    public final boolean mShouldShowLxxSuggestionUi;
+    // Use split layout for keyboard.
+    public final boolean mIsSplitKeyboardEnabled;
+    public final int mScreenMetrics;
 
     // From the input box
+    @Nonnull
     public final InputAttributes mInputAttributes;
 
     // Deduced settings
@@ -88,20 +98,16 @@
     public final int mKeyPreviewPopupDismissDelay;
     private final boolean mAutoCorrectEnabled;
     public final float mAutoCorrectionThreshold;
+    public final float mPlausibilityThreshold;
     public final boolean mAutoCorrectionEnabledPerUserSettings;
     private final boolean mSuggestionsEnabledPerUserSettings;
     private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
 
-    // Setting values for additional features
-    public final int[] mAdditionalFeaturesSettingValues =
-            new int[AdditionalFeaturesSettingUtils.ADDITIONAL_FEATURES_SETTINGS_SIZE];
-
-    // TextDecorator
-    public final int mTextHighlightColorForAddToDictionaryIndicator;
-
     // Debug settings
     public final boolean mIsInternal;
     public final boolean mHasCustomKeyPreviewAnimationParams;
+    public final boolean mHasKeyboardResize;
+    public final float mKeyboardHeightScale;
     public final int mKeyPreviewShowUpDuration;
     public final int mKeyPreviewDismissDuration;
     public final float mKeyPreviewShowUpStartXScale;
@@ -109,8 +115,10 @@
     public final float mKeyPreviewDismissEndXScale;
     public final float mKeyPreviewDismissEndYScale;
 
+    @Nullable public final String mAccount;
+
     public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res,
-            final InputAttributes inputAttributes) {
+            @Nonnull final InputAttributes inputAttributes) {
         mLocale = res.getConfiguration().locale;
         // Get the resources
         mDelayInMillisecondsToUpdateOldSuggestions =
@@ -118,12 +126,7 @@
         mSpacingAndPunctuations = new SpacingAndPunctuations(res);
 
         // Store the input attributes
-        if (null == inputAttributes) {
-            mInputAttributes = new InputAttributes(
-                    null, false /* isFullscreenMode */, context.getPackageName());
-        } else {
-            mInputAttributes = inputAttributes;
-        }
+        mInputAttributes = inputAttributes;
 
         // Get the settings preferences
         mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
@@ -134,10 +137,7 @@
                 DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
         mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
                 && mInputAttributes.mShouldShowVoiceInputKey
-                && SubtypeSwitcher.getInstance().isShortcutImeEnabled();
-        final String autoCorrectionThresholdRawValue = prefs.getString(
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD,
-                res.getString(R.string.auto_correction_threshold_mode_index_modest));
+                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
         mIncludesOtherImesInLanguageSwitchList = Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS
                 ? prefs.getBoolean(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false)
                 : true /* forcibly */;
@@ -148,35 +148,44 @@
         mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true)
                 && inputAttributes.mIsGeneralTextInput;
         mBlockPotentiallyOffensive = Settings.readBlockPotentiallyOffensive(prefs, res);
-        mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(autoCorrectionThresholdRawValue, res);
+        mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(prefs, res);
+        final String autoCorrectionThresholdRawValue = mAutoCorrectEnabled
+                ? res.getString(R.string.auto_correction_threshold_mode_index_modest)
+                : res.getString(R.string.auto_correction_threshold_mode_index_off);
         mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
         mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
         mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration());
         mEnableMetricsLogging = prefs.getBoolean(Settings.PREF_ENABLE_METRICS_LOGGING, true);
-        mShouldShowUiToAcceptTypedWord = Settings.HAS_UI_TO_ACCEPT_TYPED_WORD
-                && prefs.getBoolean(DebugSettings.PREF_SHOW_UI_TO_ACCEPT_TYPED_WORD, true);
+        mIsSplitKeyboardEnabled = prefs.getBoolean(Settings.PREF_ENABLE_SPLIT_KEYBOARD, false);
+        mScreenMetrics = Settings.readScreenMetrics(res);
+
+        mShouldShowLxxSuggestionUi = Settings.SHOULD_SHOW_LXX_SUGGESTION_UI
+                && prefs.getBoolean(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI, true);
         // Compute other readable settings
         mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
         mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);
         mKeypressSoundVolume = Settings.readKeypressSoundVolume(prefs, res);
         mKeyPreviewPopupDismissDelay = Settings.readKeyPreviewPopupDismissDelay(prefs, res);
+        mEnableEmojiAltPhysicalKey = prefs.getBoolean(
+                Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, true);
         mAutoCorrectionThreshold = readAutoCorrectionThreshold(res,
                 autoCorrectionThresholdRawValue);
+        mPlausibilityThreshold = Settings.readPlausibilityThreshold(res);
         mGestureInputEnabled = Settings.readGestureInputEnabled(prefs, res);
         mGestureTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true);
-        mGestureFloatingPreviewTextEnabled = prefs.getBoolean(
-                Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
-        mPhraseGestureEnabled = Settings.readPhraseGestureEnabled(prefs, res);
+        mCloudSyncEnabled = prefs.getBoolean(LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC, false);
+        mAccount = prefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME,
+                null /* default */);
+        mGestureFloatingPreviewTextEnabled = !mInputAttributes.mDisableGestureFloatingPreviewText
+                && prefs.getBoolean(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
         mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled
                 && !mInputAttributes.mInputTypeNoAutoCorrect;
         mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs);
-        AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray(
-                prefs, mAdditionalFeaturesSettingValues);
-        mTextHighlightColorForAddToDictionaryIndicator = res.getColor(
-                R.color.text_decorator_add_to_dictionary_indicator_text_highlight_color);
         mIsInternal = Settings.isInternal(prefs);
         mHasCustomKeyPreviewAnimationParams = prefs.getBoolean(
                 DebugSettings.PREF_HAS_CUSTOM_KEY_PREVIEW_ANIMATION_PARAMS, false);
+        mHasKeyboardResize = prefs.getBoolean(DebugSettings.PREF_RESIZE_KEYBOARD, false);
+        mKeyboardHeightScale = Settings.readKeyboardHeight(prefs, DEFAULT_SIZE_SCALE);
         mKeyPreviewShowUpDuration = Settings.readKeyPreviewAnimationDuration(
                 prefs, DebugSettings.PREF_KEY_PREVIEW_SHOW_UP_DURATION,
                 res.getInteger(R.integer.config_key_preview_show_up_duration));
@@ -211,6 +220,10 @@
         }
     }
 
+    public boolean isMetricsLoggingEnabled() {
+        return mEnableMetricsLogging;
+    }
+
     public boolean isApplicationSpecifiedCompletionsOn() {
         return mInputAttributes.mApplicationSpecifiedCompletionOn;
     }
@@ -224,6 +237,10 @@
         return mSuggestionsEnabledPerUserSettings;
     }
 
+    public boolean isPersonalizationEnabled() {
+        return mUsePersonalizedDicts;
+    }
+
     public boolean isWordSeparator(final int code) {
         return mSpacingAndPunctuations.isWordSeparator(code);
     }
@@ -256,9 +273,8 @@
         final RichInputMethodManager imm = RichInputMethodManager.getInstance();
         if (mIncludesOtherImesInLanguageSwitchList) {
             return imm.hasMultipleEnabledIMEsOrSubtypes(false /* include aux subtypes */);
-        } else {
-            return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
         }
+        return imm.hasMultipleEnabledSubtypesInThisIme(false /* include aux subtypes */);
     }
 
     public boolean isSameInputType(final EditorInfo editorInfo) {
@@ -388,8 +404,6 @@
         sb.append("" + mGestureFloatingPreviewTextEnabled);
         sb.append("\n   mSlidingKeyInputPreviewEnabled = ");
         sb.append("" + mSlidingKeyInputPreviewEnabled);
-        sb.append("\n   mPhraseGestureEnabled = ");
-        sb.append("" + mPhraseGestureEnabled);
         sb.append("\n   mKeyLongpressTimeout = ");
         sb.append("" + mKeyLongpressTimeout);
         sb.append("\n   mLocale = ");
@@ -415,10 +429,6 @@
         sb.append("\n   mAppWorkarounds = ");
         final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0);
         sb.append("" + (null == awu ? "null" : awu.toString()));
-        sb.append("\n   mAdditionalFeaturesSettingValues = ");
-        sb.append("" + Arrays.toString(mAdditionalFeaturesSettingValues));
-        sb.append("\n   mTextHighlightColorForAddToDictionaryIndicator = ");
-        sb.append("" + mTextHighlightColorForAddToDictionaryIndicator);
         sb.append("\n   mIsInternal = ");
         sb.append("" + mIsInternal);
         sb.append("\n   mKeyPreviewShowUpDuration = ");
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValuesForSuggestion.java b/java/src/com/android/inputmethod/latin/settings/SettingsValuesForSuggestion.java
index d80af4b..5e2e5a5 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValuesForSuggestion.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValuesForSuggestion.java
@@ -18,13 +18,8 @@
 
 public class SettingsValuesForSuggestion {
     public final boolean mBlockPotentiallyOffensive;
-    public final boolean mSpaceAwareGestureEnabled;
-    public final int[] mAdditionalFeaturesSettingValues;
 
-    public SettingsValuesForSuggestion(final boolean blockPotentiallyOffensive,
-            final boolean spaceAwareGestureEnabled, final int[] additionalFeaturesSettingValues) {
+    public SettingsValuesForSuggestion(final boolean blockPotentiallyOffensive) {
         mBlockPotentiallyOffensive = blockPotentiallyOffensive;
-        mSpaceAwareGestureEnabled = spaceAwareGestureEnabled;
-        mAdditionalFeaturesSettingValues = additionalFeaturesSettingValues;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
index 49d8110..70d97a5 100644
--- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
+++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
@@ -20,10 +20,10 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.PunctuationSuggestions;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.Arrays;
 import java.util.Locale;
@@ -36,6 +36,8 @@
     public final int[] mSortedWordSeparators;
     public final PunctuationSuggestions mSuggestPuncList;
     private final int mSentenceSeparator;
+    private final int mAbbreviationMarker;
+    private final int[] mSortedSentenceTerminators;
     public final String mSentenceSeparatorAndSpace;
     public final boolean mCurrentLanguageHasSpaces;
     public final boolean mUsesAmericanTypography;
@@ -55,7 +57,10 @@
                 res.getString(R.string.symbols_word_connectors));
         mSortedWordSeparators = StringUtils.toSortedCodePointArray(
                 res.getString(R.string.symbols_word_separators));
+        mSortedSentenceTerminators = StringUtils.toSortedCodePointArray(
+                res.getString(R.string.symbols_sentence_terminators));
         mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
+        mAbbreviationMarker = res.getInteger(R.integer.abbreviation_marker);
         mSentenceSeparatorAndSpace = new String(new int[] {
                 mSentenceSeparator, Constants.CODE_SPACE }, 0, 2);
         mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces);
@@ -77,8 +82,10 @@
         mSortedSymbolsClusteringTogether = model.mSortedSymbolsClusteringTogether;
         mSortedWordConnectors = model.mSortedWordConnectors;
         mSortedWordSeparators = overrideSortedWordSeparators;
+        mSortedSentenceTerminators = model.mSortedSentenceTerminators;
         mSuggestPuncList = model.mSuggestPuncList;
         mSentenceSeparator = model.mSentenceSeparator;
+        mAbbreviationMarker = model.mAbbreviationMarker;
         mSentenceSeparatorAndSpace = model.mSentenceSeparatorAndSpace;
         mCurrentLanguageHasSpaces = model.mCurrentLanguageHasSpaces;
         mUsesAmericanTypography = model.mUsesAmericanTypography;
@@ -109,6 +116,14 @@
         return Arrays.binarySearch(mSortedSymbolsClusteringTogether, code) >= 0;
     }
 
+    public boolean isSentenceTerminator(final int code) {
+        return Arrays.binarySearch(mSortedSentenceTerminators, code) >= 0;
+    }
+
+    public boolean isAbbreviationMarker(final int code) {
+        return code == mAbbreviationMarker;
+    }
+
     public boolean isSentenceSeparator(final int code) {
         return code == mSentenceSeparator;
     }
diff --git a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
index ca5b395..240f8f8 100644
--- a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.preference.ListPreference;
 import android.preference.Preference;
@@ -79,6 +80,16 @@
         return getPreferenceManager().getSharedPreferences();
     }
 
+    /**
+     * Gets the application name to display on the UI.
+     */
+    final String getApplicationName() {
+        final Context context = getActivity();
+        final Resources res = getResources();
+        final int applicationLabelRes = context.getApplicationInfo().labelRes;
+        return res.getString(applicationLabelRes);
+    }
+
     @Override
     public void addPreferencesFromResource(final int preferencesResId) {
         super.addPreferencesFromResource(preferencesResId);
diff --git a/java/src/com/android/inputmethod/latin/settings/TestFragmentActivity.java b/java/src/com/android/inputmethod/latin/settings/TestFragmentActivity.java
new file mode 100644
index 0000000..254bc65
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/settings/TestFragmentActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Test activity to use when testing preference fragments. <br/>
+ * Usage: <br/>
+ * Create an ActivityInstrumentationTestCase2 for this activity
+ * and call setIntent() with an intent that specifies the fragment to load in the activity.
+ * The fragment can then be obtained from this activity and used for testing/verification.
+ */
+public final class TestFragmentActivity extends Activity {
+    /**
+     * The fragment name that should be loaded when starting this activity.
+     * This must be specified when starting this activity, as this activity is only
+     * meant to test fragments from instrumentation tests.
+     */
+    public static final String EXTRA_SHOW_FRAGMENT = "show_fragment";
+
+    public Fragment mFragment;
+
+    @Override
+    protected void onCreate(final Bundle savedState) {
+        super.onCreate(savedState);
+        final Intent intent = getIntent();
+        final String fragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
+        if (fragmentName == null) {
+            throw new IllegalArgumentException("No fragment name specified for testing");
+        }
+
+        mFragment = Fragment.instantiate(this, fragmentName);
+        FragmentManager fragmentManager = getFragmentManager();
+        fragmentManager.beginTransaction().add(mFragment, fragmentName).commit();
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/ThemeSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/ThemeSettingsFragment.java
index 5a3fc36..29289ae 100644
--- a/java/src/com/android/inputmethod/latin/settings/ThemeSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/ThemeSettingsFragment.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.latin.settings;
 
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.preference.Preference;
@@ -32,12 +31,12 @@
  */
 public final class ThemeSettingsFragment extends SubScreenFragment
         implements OnRadioButtonClickedListener {
-    private String mSelectedThemeId;
+    private int mSelectedThemeId;
 
     static class KeyboardThemePreference extends RadioButtonPreference {
-        final String mThemeId;
+        final int mThemeId;
 
-        KeyboardThemePreference(final Context context, final String name, final String id) {
+        KeyboardThemePreference(final Context context, final String name, final int id) {
             super(context);
             setTitle(name);
             mThemeId = id;
@@ -45,14 +44,13 @@
     }
 
     static void updateKeyboardThemeSummary(final Preference pref) {
-        final Resources res = pref.getContext().getResources();
-        final SharedPreferences prefs = pref.getSharedPreferences();
-        final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(prefs);
-        final String keyboardThemeId = String.valueOf(keyboardTheme.mThemeId);
+        final Context context = pref.getContext();
+        final Resources res = context.getResources();
+        final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(context);
         final String[] keyboardThemeNames = res.getStringArray(R.array.keyboard_theme_names);
-        final String[] keyboardThemeIds = res.getStringArray(R.array.keyboard_theme_ids);
+        final int[] keyboardThemeIds = res.getIntArray(R.array.keyboard_theme_ids);
         for (int index = 0; index < keyboardThemeNames.length; index++) {
-            if (keyboardThemeId.equals(keyboardThemeIds[index])) {
+            if (keyboardTheme.mThemeId == keyboardThemeIds[index]) {
                 pref.setSummary(keyboardThemeNames[index]);
                 return;
             }
@@ -64,18 +62,18 @@
         super.onCreate(icicle);
         addPreferencesFromResource(R.xml.prefs_screen_theme);
         final PreferenceScreen screen = getPreferenceScreen();
+        final Context context = getActivity();
         final Resources res = getResources();
         final String[] keyboardThemeNames = res.getStringArray(R.array.keyboard_theme_names);
-        final String[] keyboardThemeIds = res.getStringArray(R.array.keyboard_theme_ids);
+        final int[] keyboardThemeIds = res.getIntArray(R.array.keyboard_theme_ids);
         for (int index = 0; index < keyboardThemeNames.length; index++) {
             final KeyboardThemePreference pref = new KeyboardThemePreference(
-                    getActivity(), keyboardThemeNames[index], keyboardThemeIds[index]);
+                    context, keyboardThemeNames[index], keyboardThemeIds[index]);
             screen.addPreference(pref);
             pref.setOnRadioButtonClickedListener(this);
         }
-        final SharedPreferences prefs = getSharedPreferences();
-        final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(prefs);
-        mSelectedThemeId = String.valueOf(keyboardTheme.mThemeId);
+        final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(context);
+        mSelectedThemeId = keyboardTheme.mThemeId;
     }
 
     @Override
@@ -106,7 +104,7 @@
             final Preference preference = screen.getPreference(index);
             if (preference instanceof KeyboardThemePreference) {
                 final KeyboardThemePreference pref = (KeyboardThemePreference)preference;
-                final boolean selected = mSelectedThemeId.equals(pref.mThemeId);
+                final boolean selected = (mSelectedThemeId == pref.mThemeId);
                 pref.setSelected(selected);
             }
         }
diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
deleted file mode 100644
index 3f0b102..0000000
--- a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
+++ /dev/null
@@ -1,85 +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.setup;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import com.android.inputmethod.latin.settings.Settings;
-
-/**
- * This class handles the {@link Intent#ACTION_MY_PACKAGE_REPLACED} broadcast intent when this IME
- * package has been replaced by a newer version of the same package. This class also handles
- * {@link Intent#ACTION_BOOT_COMPLETED} and {@link Intent#ACTION_USER_INITIALIZE} broadcast intent.
- *
- * If this IME has already been installed in the system image and a new version of this IME has
- * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is received to this class to hide the
- * setup wizard's icon.
- *
- * If this IME has already been installed in the data partition and a new version of this IME has
- * been installed, {@link Intent#ACTION_MY_PACKAGE_REPLACED} is forwarded to this class but it
- * will not hide the setup wizard's icon, and the icon will appear on the launcher.
- *
- * If this IME hasn't been installed yet and has been newly installed, no
- * {@link Intent#ACTION_MY_PACKAGE_REPLACED} will be sent and the setup wizard's icon will appear
- * on the launcher.
- *
- * When the device has been booted, {@link Intent#ACTION_BOOT_COMPLETED} is forwarded to this class
- * to check whether the setup wizard's icon should be appeared or not on the launcher
- * depending on which partition this IME is installed.
- *
- * When a multiuser account has been created, {@link Intent#ACTION_USER_INITIALIZE} is forwarded to
- * this class to check whether the setup wizard's icon should be appeared or not on the launcher
- * depending on which partition this IME is installed.
- */
-public final class LauncherIconVisibilityManager {
-    private static final String TAG = LauncherIconVisibilityManager.class.getSimpleName();
-
-    public static void updateSetupWizardIconVisibility(final Context context) {
-        final ComponentName setupWizardActivity = new ComponentName(context, SetupActivity.class);
-        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        final boolean stateHasSet;
-        if (Settings.readShowSetupWizardIcon(prefs, context)) {
-            stateHasSet = setActivityState(context, setupWizardActivity,
-                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
-            Log.i(TAG, (stateHasSet ? "Enable activity: " : "Activity has already been enabled: ")
-                    + setupWizardActivity);
-        } else {
-            stateHasSet = setActivityState(context, setupWizardActivity,
-                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
-            Log.i(TAG, (stateHasSet ? "Disable activity: " : "Activity has already been disabled: ")
-                    + setupWizardActivity);
-        }
-    }
-
-    private static boolean setActivityState(final Context context,
-            final ComponentName activityComponent, final int activityState) {
-        final PackageManager pm = context.getPackageManager();
-        final int activityComponentState = pm.getComponentEnabledSetting(activityComponent);
-        if (activityComponentState == activityState) {
-            return false;
-        }
-        pm.setComponentEnabledSetting(
-                activityComponent, activityState, PackageManager.DONT_KILL_APP);
-        return true;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
index b770ea5..7607429 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupActivity.java
@@ -17,12 +17,8 @@
 package com.android.inputmethod.latin.setup;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.provider.Settings;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
 
 public final class SetupActivity extends Activity {
     @Override
diff --git a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
index e455e53..bee22af 100644
--- a/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
+++ b/java/src/com/android/inputmethod/latin/setup/SetupWizardActivity.java
@@ -42,10 +42,14 @@
 
 import java.util.ArrayList;
 
+import javax.annotation.Nonnull;
+
 // TODO: Use Fragment to implement welcome screen and setup steps.
 public final class SetupWizardActivity extends Activity implements View.OnClickListener {
     static final String TAG = SetupWizardActivity.class.getSimpleName();
 
+    // For debugging purpose.
+    private static final boolean FORCE_TO_SHOW_WELCOME_SCREEN = false;
     private static final boolean ENABLE_WELCOME_VIDEO = true;
 
     private InputMethodManager mImm;
@@ -80,7 +84,7 @@
 
         private final InputMethodManager mImmInHandler;
 
-        public SettingsPoolingHandler(final SetupWizardActivity ownerInstance,
+        public SettingsPoolingHandler(@Nonnull final SetupWizardActivity ownerInstance,
                 final InputMethodManager imm) {
             super(ownerInstance);
             mImmInHandler = imm;
@@ -261,6 +265,8 @@
         intent.setClass(this, SettingsActivity.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        intent.putExtra(SettingsActivity.EXTRA_ENTRY_KEY,
+                SettingsActivity.EXTRA_ENTRY_VALUE_APP_ICON);
         startActivity(intent);
     }
 
@@ -304,6 +310,9 @@
 
     private int determineSetupStepNumber() {
         mHandler.cancelPollingImeSettings();
+        if (FORCE_TO_SHOW_WELCOME_SCREEN) {
+            return STEP_1;
+        }
         if (!UncachedInputMethodManagerUtils.isThisImeEnabled(this, mImm)) {
             return STEP_1;
         }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 90398de..766b385 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -16,55 +16,37 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
-import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 import android.service.textservice.SpellCheckerService;
 import android.text.InputType;
-import android.util.Log;
-import android.util.LruCache;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.textservice.SuggestionsInfo;
+import android.util.Log;
 
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
-import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.latin.ContactsBinaryDictionary;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryCollection;
 import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.DictionaryFactory;
-import com.android.inputmethod.latin.PrevWordsInfo;
+import com.android.inputmethod.latin.DictionaryFacilitatorLruCache;
+import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.ComposedData;
 import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
-import com.android.inputmethod.latin.UserBinaryDictionary;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.CollectionUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.SuggestionResults;
-import com.android.inputmethod.latin.WordComposer;
 
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
 
 /**
  * Service for spell checking, using LatinIME's dictionaries and mechanisms.
@@ -72,72 +54,36 @@
 public final class AndroidSpellCheckerService extends SpellCheckerService
         implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = AndroidSpellCheckerService.class.getSimpleName();
-    private static final boolean DBG = false;
+    private static final boolean DEBUG = false;
 
     public static final String PREF_USE_CONTACTS_KEY = "pref_spellcheck_use_contacts";
 
     private static final int SPELLCHECKER_DUMMY_KEYBOARD_WIDTH = 480;
-    private static final int SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT = 368;
+    private static final int SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT = 301;
 
     private static final String DICTIONARY_NAME_PREFIX = "spellcheck_";
-    private static final int WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS = 1000;
-    private static final int MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT = 5;
 
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
-    private final HashSet<Locale> mCachedLocales = new HashSet<>();
-
     private final int MAX_NUM_OF_THREADS_READ_DICTIONARY = 2;
     private final Semaphore mSemaphore = new Semaphore(MAX_NUM_OF_THREADS_READ_DICTIONARY,
             true /* fair */);
     // TODO: Make each spell checker session has its own session id.
     private final ConcurrentLinkedQueue<Integer> mSessionIdPool = new ConcurrentLinkedQueue<>();
 
-    private static class DictionaryFacilitatorLruCache extends
-            LruCache<Locale, DictionaryFacilitator> {
-        private final HashSet<Locale> mCachedLocales;
-        public DictionaryFacilitatorLruCache(final HashSet<Locale> cachedLocales, int maxSize) {
-            super(maxSize);
-            mCachedLocales = cachedLocales;
-        }
-
-        @Override
-        protected void entryRemoved(boolean evicted, Locale key,
-                DictionaryFacilitator oldValue, DictionaryFacilitator newValue) {
-            if (oldValue != null && oldValue != newValue) {
-                oldValue.closeDictionaries();
-            }
-            if (key != null && newValue == null) {
-                // Remove locale from the cache when the dictionary facilitator for the locale is
-                // evicted and new facilitator is not set for the locale.
-                mCachedLocales.remove(key);
-                if (size() >= maxSize()) {
-                    Log.w(TAG, "DictionaryFacilitator for " + key.toString()
-                            + " has been evicted due to cache size limit."
-                            + " size: " + size() + ", maxSize: " + maxSize());
-                }
-            }
-        }
-    }
-
-    private static final int MAX_DICTIONARY_FACILITATOR_COUNT = 3;
-    private final LruCache<Locale, DictionaryFacilitator> mDictionaryFacilitatorCache =
-            new DictionaryFacilitatorLruCache(mCachedLocales, MAX_DICTIONARY_FACILITATOR_COUNT);
+    private final DictionaryFacilitatorLruCache mDictionaryFacilitatorCache =
+            new DictionaryFacilitatorLruCache(this /* context */, DICTIONARY_NAME_PREFIX);
     private final ConcurrentHashMap<Locale, Keyboard> mKeyboardCache = new ConcurrentHashMap<>();
 
     // The threshold for a suggestion to be considered "recommended".
     private float mRecommendedThreshold;
-    // Whether to use the contacts dictionary
-    private boolean mUseContactsDictionary;
     // TODO: make a spell checker option to block offensive words or not
     private final SettingsValuesForSuggestion mSettingsValuesForSuggestion =
-            new SettingsValuesForSuggestion(true /* blockPotentiallyOffensive */,
-                    true /* spaceAwareGestureEnabled */,
-                    null /* additionalFeaturesSettingValues */);
-    private final Object mDictionaryLock = new Object();
+            new SettingsValuesForSuggestion(true /* blockPotentiallyOffensive */);
 
     public static final String SINGLE_QUOTE = "\u0027";
     public static final String APOSTROPHE = "\u2019";
+    private UserDictionaryLookup mUserDictionaryLookup;
 
     public AndroidSpellCheckerService() {
         super();
@@ -146,20 +92,45 @@
         }
     }
 
-    @Override public void onCreate() {
+    @Override
+    public void onCreate() {
         super.onCreate();
         mRecommendedThreshold =
                 Float.parseFloat(getString(R.string.spellchecker_recommended_threshold_value));
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
         prefs.registerOnSharedPreferenceChangeListener(this);
         onSharedPreferenceChanged(prefs, PREF_USE_CONTACTS_KEY);
+        // Create a UserDictionaryLookup.  It needs to be close()d and set to null in onDestroy.
+        if (mUserDictionaryLookup == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Creating mUserDictionaryLookup in onCreate");
+            }
+            mUserDictionaryLookup = new UserDictionaryLookup(this);
+        } else if (DEBUG) {
+            Log.d(TAG, "mUserDictionaryLookup already created before onCreate");
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (DEBUG) {
+            Log.d(TAG, "Closing and dereferencing mUserDictionaryLookup in onDestroy");
+        }
+        mUserDictionaryLookup.close();
+        mUserDictionaryLookup = null;
+        super.onDestroy();
     }
 
     public float getRecommendedThreshold() {
         return mRecommendedThreshold;
     }
 
-    private static String getKeyboardLayoutNameForScript(final int script) {
+    private static String getKeyboardLayoutNameForLocale(final Locale locale) {
+        // See b/19963288.
+        if (locale.getLanguage().equals("sr")) {
+            return "south_slavic";
+        }
+        final int script = ScriptUtils.getScriptFromSpellCheckerLocale(locale);
         switch (script) {
         case ScriptUtils.SCRIPT_LATIN:
             return "qwerty";
@@ -167,6 +138,8 @@
             return "east_slavic";
         case ScriptUtils.SCRIPT_GREEK:
             return "greek";
+        case ScriptUtils.SCRIPT_HEBREW:
+            return "hebrew";
         default:
             throw new RuntimeException("Wrong script supplied: " + script);
         }
@@ -175,21 +148,8 @@
     @Override
     public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
         if (!PREF_USE_CONTACTS_KEY.equals(key)) return;
-            final boolean useContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
-            if (useContactsDictionary != mUseContactsDictionary) {
-                mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY);
-                try {
-                    mUseContactsDictionary = useContactsDictionary;
-                    for (final Locale locale : mCachedLocales) {
-                        final DictionaryFacilitator dictionaryFacilitator =
-                                mDictionaryFacilitatorCache.get(locale);
-                        resetDictionariesForLocale(this /* context  */,
-                                dictionaryFacilitator, locale, mUseContactsDictionary);
-                    }
-                } finally {
-                    mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY);
-                }
-            }
+        final boolean useContactsDictionary = prefs.getBoolean(PREF_USE_CONTACTS_KEY, true);
+        mDictionaryFacilitatorCache.setUseContactsDictionary(useContactsDictionary);
     }
 
     @Override
@@ -221,24 +181,36 @@
     public boolean isValidWord(final Locale locale, final String word) {
         mSemaphore.acquireUninterruptibly();
         try {
+            if (mUserDictionaryLookup.isValidWord(word, locale)) {
+                if (DEBUG) {
+                    Log.d(TAG, "mUserDictionaryLookup.isValidWord(" + word + ")=true");
+                }
+                return true;
+            } else {
+                if (DEBUG) {
+                    Log.d(TAG, "mUserDictionaryLookup.isValidWord(" + word + ")=false");
+                }
+            }
             DictionaryFacilitator dictionaryFacilitatorForLocale =
-                    getDictionaryFacilitatorForLocaleLocked(locale);
-            return dictionaryFacilitatorForLocale.isValidWord(word, false /* igroreCase */);
+                    mDictionaryFacilitatorCache.get(locale);
+            return dictionaryFacilitatorForLocale.isValidSpellingWord(word);
         } finally {
             mSemaphore.release();
         }
     }
 
-    public SuggestionResults getSuggestionResults(final Locale locale, final WordComposer composer,
-            final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo) {
+    public SuggestionResults getSuggestionResults(final Locale locale,
+            final ComposedData composedData, final NgramContext ngramContext,
+            @Nonnull final Keyboard keyboard) {
         Integer sessionId = null;
         mSemaphore.acquireUninterruptibly();
         try {
             sessionId = mSessionIdPool.poll();
             DictionaryFacilitator dictionaryFacilitatorForLocale =
-                    getDictionaryFacilitatorForLocaleLocked(locale);
-            return dictionaryFacilitatorForLocale.getSuggestionResults(composer, prevWordsInfo,
-                    proximityInfo, mSettingsValuesForSuggestion, sessionId);
+                    mDictionaryFacilitatorCache.get(locale);
+            return dictionaryFacilitatorForLocale.getSuggestionResults(composedData, ngramContext,
+                    keyboard, mSettingsValuesForSuggestion,
+                    sessionId, SuggestedWords.INPUT_STYLE_TYPING);
         } finally {
             if (sessionId != null) {
                 mSessionIdPool.add(sessionId);
@@ -251,56 +223,18 @@
         mSemaphore.acquireUninterruptibly();
         try {
             final DictionaryFacilitator dictionaryFacilitator =
-                    getDictionaryFacilitatorForLocaleLocked(locale);
-            return dictionaryFacilitator.hasInitializedMainDictionary();
+                    mDictionaryFacilitatorCache.get(locale);
+            return dictionaryFacilitator.hasAtLeastOneInitializedMainDictionary();
         } finally {
             mSemaphore.release();
         }
     }
 
-    private DictionaryFacilitator getDictionaryFacilitatorForLocaleLocked(final Locale locale) {
-        DictionaryFacilitator dictionaryFacilitatorForLocale =
-                mDictionaryFacilitatorCache.get(locale);
-        if (dictionaryFacilitatorForLocale == null) {
-            dictionaryFacilitatorForLocale = new DictionaryFacilitator();
-            mDictionaryFacilitatorCache.put(locale, dictionaryFacilitatorForLocale);
-            mCachedLocales.add(locale);
-            resetDictionariesForLocale(this /* context */, dictionaryFacilitatorForLocale,
-                    locale, mUseContactsDictionary);
-        }
-        return dictionaryFacilitatorForLocale;
-    }
-
-    private static void resetDictionariesForLocale(final Context context,
-            final DictionaryFacilitator dictionaryFacilitator, final Locale locale,
-            final boolean useContactsDictionary) {
-        dictionaryFacilitator.resetDictionariesWithDictNamePrefix(context, locale,
-                useContactsDictionary, false /* usePersonalizedDicts */,
-                false /* forceReloadMainDictionary */, null /* listener */,
-                DICTIONARY_NAME_PREFIX);
-        for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
-            try {
-                dictionaryFacilitator.waitForLoadingMainDictionary(
-                        WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
-                return;
-            } catch (final InterruptedException e) {
-                Log.i(TAG, "Interrupted during waiting for loading main dictionary.", e);
-                if (i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT - 1) {
-                    Log.i(TAG, "Retry", e);
-                } else {
-                    Log.w(TAG, "Give up retrying. Retried "
-                            + MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT + " times.", e);
-                }
-            }
-        }
-    }
-
     @Override
     public boolean onUnbind(final Intent intent) {
         mSemaphore.acquireUninterruptibly(MAX_NUM_OF_THREADS_READ_DICTIONARY);
         try {
-            mDictionaryFacilitatorCache.evictAll();
-            mCachedLocales.clear();
+            mDictionaryFacilitatorCache.closeDictionaries();
         } finally {
             mSemaphore.release(MAX_NUM_OF_THREADS_READ_DICTIONARY);
         }
@@ -320,8 +254,7 @@
     }
 
     private Keyboard createKeyboardForLocale(final Locale locale) {
-        final int script = ScriptUtils.getScriptFromSpellCheckerLocale(locale);
-        final String keyboardLayoutName = getKeyboardLayoutNameForScript(script);
+        final String keyboardLayoutName = getKeyboardLayoutNameForLocale(locale);
         final InputMethodSubtype subtype = AdditionalSubtypeUtils.createDummyAdditionalSubtype(
                 locale.toString(), keyboardLayoutName);
         final KeyboardLayoutSet keyboardLayoutSet = createKeyboardSetForSpellChecker(subtype);
@@ -334,7 +267,7 @@
         final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(this, editorInfo);
         builder.setKeyboardGeometry(
                 SPELLCHECKER_DUMMY_KEYBOARD_WIDTH, SPELLCHECKER_DUMMY_KEYBOARD_HEIGHT);
-        builder.setSubtype(subtype);
+        builder.setSubtype(RichInputMethodSubtype.getRichInputMethodSubtype(subtype));
         builder.setIsSpellChecker(true /* isSpellChecker */);
         builder.disableTouchPositionCorrectionData();
         return builder.build();
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
index 34e0119..2c690ae 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerSession.java
@@ -16,8 +16,10 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.annotation.TargetApi;
 import android.content.res.Resources;
 import android.os.Binder;
+import android.os.Build;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.textservice.SentenceSuggestionsInfo;
@@ -25,8 +27,8 @@
 import android.view.textservice.TextInfo;
 
 import com.android.inputmethod.compat.TextInfoCompatUtils;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.utils.SpannableStringUtils;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -42,6 +44,7 @@
         mResources = service.getResources();
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(TextInfo ti,
             SentenceSuggestionsInfo ssi) {
         final CharSequence typedText = TextInfoCompatUtils.getCharSequenceOrString(ti);
@@ -62,15 +65,16 @@
             final int offset = ssi.getOffsetAt(i);
             final int length = ssi.getLengthAt(i);
             final CharSequence subText = typedText.subSequence(offset, offset + length);
-            final PrevWordsInfo prevWordsInfo =
-                    new PrevWordsInfo(new PrevWordsInfo.WordInfo(currentWord));
+            final NgramContext ngramContext =
+                    new NgramContext(new NgramContext.WordInfo(currentWord));
             currentWord = subText;
             if (!subText.toString().contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
                 continue;
             }
-            final CharSequence[] splitTexts = StringUtils.split(subText,
+            // Split preserving spans.
+            final CharSequence[] splitTexts = SpannableStringUtils.split(subText,
                     AndroidSpellCheckerService.SINGLE_QUOTE,
-                    true /* preserveTrailingEmptySegments */ );
+                    true /* preserveTrailingEmptySegments */);
             if (splitTexts == null || splitTexts.length <= 1) {
                 continue;
             }
@@ -80,7 +84,7 @@
                 if (TextUtils.isEmpty(splitText)) {
                     continue;
                 }
-                if (mSuggestionsCache.getSuggestionsFromCache(splitText.toString(), prevWordsInfo)
+                if (mSuggestionsCache.getSuggestionsFromCache(splitText.toString(), ngramContext)
                         == null) {
                     continue;
                 }
@@ -149,7 +153,7 @@
      * @param textInfos an array of the text metadata
      * @param suggestionsLimit the maximum number of suggestions to be returned
      * @return an array of {@link SentenceSuggestionsInfo} returned by
-     * {@link SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
+     * {@link android.service.textservice.SpellCheckerService.Session#onGetSuggestions(TextInfo, int)}
      */
     private SentenceSuggestionsInfo[] splitAndSuggest(TextInfo[] textInfos, int suggestionsLimit) {
         if (textInfos == null || textInfos.length == 0) {
@@ -208,10 +212,10 @@
                 } else {
                     prevWord = null;
                 }
-                final PrevWordsInfo prevWordsInfo =
-                        new PrevWordsInfo(new PrevWordsInfo.WordInfo(prevWord));
+                final NgramContext ngramContext =
+                        new NgramContext(new NgramContext.WordInfo(prevWord));
                 final TextInfo textInfo = textInfos[i];
-                retval[i] = onGetSuggestionsInternal(textInfo, prevWordsInfo, suggestionsLimit);
+                retval[i] = onGetSuggestionsInternal(textInfo, ngramContext, suggestionsLimit);
                 retval[i].setCookieAndSequence(textInfo.getCookie(), textInfo.getSequence());
             }
             return retval;
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
index d668672..5aa7783 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java
@@ -29,19 +29,19 @@
 
 import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
 import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.PrevWordsInfo;
+import com.android.inputmethod.latin.NgramContext;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
 import com.android.inputmethod.latin.utils.ScriptUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.utils.StatsUtils;
 import com.android.inputmethod.latin.utils.SuggestionResults;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 public abstract class AndroidWordLevelSpellCheckerSession extends Session {
@@ -73,27 +73,25 @@
         private final LruCache<String, SuggestionsParams> mUnigramSuggestionsInfoCache =
                 new LruCache<>(MAX_CACHE_SIZE);
 
-        // TODO: Support n-gram input
-        private static String generateKey(final String query, final PrevWordsInfo prevWordsInfo) {
-            if (TextUtils.isEmpty(query) || !prevWordsInfo.isValid()) {
+        private static String generateKey(final String query, final NgramContext ngramContext) {
+            if (TextUtils.isEmpty(query) || !ngramContext.isValid()) {
                 return query;
             }
-            return query + CHAR_DELIMITER + prevWordsInfo;
+            return query + CHAR_DELIMITER + ngramContext;
         }
 
         public SuggestionsParams getSuggestionsFromCache(String query,
-                final PrevWordsInfo prevWordsInfo) {
-            return mUnigramSuggestionsInfoCache.get(generateKey(query, prevWordsInfo));
+                final NgramContext ngramContext) {
+            return mUnigramSuggestionsInfoCache.get(generateKey(query, ngramContext));
         }
 
-        public void putSuggestionsToCache(
-                final String query, final PrevWordsInfo prevWordsInfo,
+        public void putSuggestionsToCache(final String query, final NgramContext ngramContext,
                 final String[] suggestions, final int flags) {
             if (suggestions == null || TextUtils.isEmpty(query)) {
                 return;
             }
             mUnigramSuggestionsInfoCache.put(
-                    generateKey(query, prevWordsInfo), new SuggestionsParams(suggestions, flags));
+                    generateKey(query, ngramContext), new SuggestionsParams(suggestions, flags));
         }
 
         public void clearCache() {
@@ -117,7 +115,8 @@
     @Override
     public void onCreate() {
         final String localeString = getLocale();
-        mLocale = LocaleUtils.constructLocaleFromString(localeString);
+        mLocale = (null == localeString) ? null
+                : LocaleUtils.constructLocaleFromString(localeString);
         mScript = ScriptUtils.getScriptFromSpellCheckerLocale(mLocale);
     }
 
@@ -223,12 +222,11 @@
     }
 
     protected SuggestionsInfo onGetSuggestionsInternal(
-            final TextInfo textInfo, final PrevWordsInfo prevWordsInfo,
-            final int suggestionsLimit) {
+            final TextInfo textInfo, final NgramContext ngramContext, final int suggestionsLimit) {
         try {
             final String inText = textInfo.getText();
             final SuggestionsParams cachedSuggestionsParams =
-                    mSuggestionsCache.getSuggestionsFromCache(inText, prevWordsInfo);
+                    mSuggestionsCache.getSuggestionsFromCache(inText, ngramContext);
             if (cachedSuggestionsParams != null) {
                 if (DBG) {
                     Log.d(TAG, "Cache hit: " + inText + ", " + cachedSuggestionsParams.mFlags);
@@ -262,31 +260,28 @@
             final String text = inText.replaceAll(
                     AndroidSpellCheckerService.APOSTROPHE, AndroidSpellCheckerService.SINGLE_QUOTE);
             final int capitalizeType = StringUtils.getCapitalizationType(text);
-            boolean isInDict = true;
             if (!mService.hasMainDictionaryForLocale(mLocale)) {
                 return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
                         false /* reportAsTypo */);
             }
             final Keyboard keyboard = mService.getKeyboardForLocale(mLocale);
+            if (null == keyboard) {
+                Log.d(TAG, "No keyboard for locale: " + mLocale);
+                // If there is no keyboard for this locale, don't do any spell-checking.
+                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+                        false /* reportAsTypo */);
+            }
             final WordComposer composer = new WordComposer();
             final int[] codePoints = StringUtils.toCodePointArray(text);
             final int[] coordinates;
-            final ProximityInfo proximityInfo;
-            if (null == keyboard) {
-                coordinates = CoordinateUtils.newCoordinateArray(codePoints.length,
-                        Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
-                proximityInfo = null;
-            } else {
-                coordinates = keyboard.getCoordinates(codePoints);
-                proximityInfo = keyboard.getProximityInfo();
-            }
+            coordinates = keyboard.getCoordinates(codePoints);
             composer.setComposingWord(codePoints, coordinates);
             // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
             final SuggestionResults suggestionResults = mService.getSuggestionResults(
-                    mLocale, composer, prevWordsInfo, proximityInfo);
+                    mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard);
             final Result result = getResult(capitalizeType, mLocale, suggestionsLimit,
                     mService.getRecommendedThreshold(), text, suggestionResults);
-            isInDict = isInDictForAnyCapitalization(text, capitalizeType);
+            final boolean isInDict = isInDictForAnyCapitalization(text, capitalizeType);
             if (DBG) {
                 Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
                         + suggestionsLimit);
@@ -299,6 +294,15 @@
                     }
                 }
             }
+            // Handle word not in dictionary.
+            // This is called only once per unique word, so entering multiple
+            // instances of the same word does not result in more than one call
+            // to this method.
+            // Also, upon changing the orientation of the device, this is called
+            // again for every unique invalid word in the text box.
+            if (!isInDict) {
+                StatsUtils.onInvalidWordIdentification(text);
+            }
 
             final int flags =
                     (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
@@ -308,26 +312,24 @@
                                     .getValueOf_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS()
                             : 0);
             final SuggestionsInfo retval = new SuggestionsInfo(flags, result.mSuggestions);
-            mSuggestionsCache.putSuggestionsToCache(text, prevWordsInfo, result.mSuggestions,
+            mSuggestionsCache.putSuggestionsToCache(text, ngramContext, result.mSuggestions,
                     flags);
             return retval;
         } catch (RuntimeException e) {
             // Don't kill the keyboard if there is a bug in the spell checker
             if (DBG) {
                 throw e;
-            } else {
-                Log.e(TAG, "Exception while spellcheking", e);
-                return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
-                        false /* reportAsTypo */);
             }
+            Log.e(TAG, "Exception while spellchecking", e);
+            return AndroidSpellCheckerService.getNotInDictEmptySuggestions(
+                    false /* reportAsTypo */);
         }
     }
 
     private static final class Result {
         public final String[] mSuggestions;
         public final boolean mHasRecommendedSuggestions;
-        public Result(final String[] gatheredSuggestions,
-                final boolean hasRecommendedSuggestions) {
+        public Result(final String[] gatheredSuggestions, final boolean hasRecommendedSuggestions) {
             mSuggestions = gatheredSuggestions;
             mHasRecommendedSuggestions = hasRecommendedSuggestions;
         }
@@ -361,14 +363,15 @@
         StringUtils.removeDupes(suggestions);
         // This returns a String[], while toArray() returns an Object[] which cannot be cast
         // into a String[].
+        final List<String> gatheredSuggestionsList =
+                suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit));
         final String[] gatheredSuggestions =
-                suggestions.subList(0, Math.min(suggestions.size(), suggestionsLimit))
-                        .toArray(EMPTY_STRING_ARRAY);
+                gatheredSuggestionsList.toArray(new String[gatheredSuggestionsList.size()]);
 
         final int bestScore = suggestionResults.first().mScore;
         final String bestSuggestion = suggestions.get(0);
         final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
-                originalText, bestSuggestion.toString(), bestScore);
+                originalText, bestSuggestion, bestScore);
         final boolean hasRecommendedSuggestions = (normalizedScore > recommendedThreshold);
         if (DBG) {
             Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
@@ -387,8 +390,7 @@
      * That's what the following method does.
      */
     @Override
-    public SuggestionsInfo onGetSuggestions(final TextInfo textInfo,
-            final int suggestionsLimit) {
+    public SuggestionsInfo onGetSuggestions(final TextInfo textInfo, final int suggestionsLimit) {
         long ident = Binder.clearCallingIdentity();
         try {
             return onGetSuggestionsInternal(textInfo, suggestionsLimit);
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
index 51c4b1e..10c458c 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SentenceLevelAdapter.java
@@ -16,13 +16,15 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.annotation.TargetApi;
 import android.content.res.Resources;
+import android.os.Build;
 import android.view.textservice.SentenceSuggestionsInfo;
 import android.view.textservice.SuggestionsInfo;
 import android.view.textservice.TextInfo;
 
 import com.android.inputmethod.compat.TextInfoCompatUtils;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.RunInLocale;
 
@@ -76,19 +78,19 @@
     private static class WordIterator {
         private final SpacingAndPunctuations mSpacingAndPunctuations;
         public WordIterator(final Resources res, final Locale locale) {
-            final RunInLocale<SpacingAndPunctuations> job
-                    = new RunInLocale<SpacingAndPunctuations>() {
+            final RunInLocale<SpacingAndPunctuations> job =
+                    new RunInLocale<SpacingAndPunctuations>() {
                 @Override
-                protected SpacingAndPunctuations job(final Resources res) {
-                    return new SpacingAndPunctuations(res);
+                protected SpacingAndPunctuations job(final Resources r) {
+                    return new SpacingAndPunctuations(r);
                 }
             };
             mSpacingAndPunctuations = job.runInLocale(res, locale);
         }
 
-        public int getEndOfWord(final CharSequence sequence, int index) {
+        public int getEndOfWord(final CharSequence sequence, final int fromIndex) {
             final int length = sequence.length();
-            index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
+            int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
             while (index < length) {
                 final int codePoint = Character.codePointAt(sequence, index);
                 if (mSpacingAndPunctuations.isWordSeparator(codePoint)) {
@@ -111,12 +113,12 @@
             return index;
         }
 
-        public int getBeginningOfNextWord(final CharSequence sequence, int index) {
+        public int getBeginningOfNextWord(final CharSequence sequence, final int fromIndex) {
             final int length = sequence.length();
-            if (index >= length) {
+            if (fromIndex >= length) {
                 return -1;
             }
-            index = index < 0 ? 0 : Character.offsetByCodePoints(sequence, index, 1);
+            int index = fromIndex < 0 ? 0 : Character.offsetByCodePoints(sequence, fromIndex, 1);
             while (index < length) {
                 final int codePoint = Character.codePointAt(sequence, index);
                 if (!mSpacingAndPunctuations.isWordSeparator(codePoint)) {
@@ -140,14 +142,13 @@
         final int cookie = originalTextInfo.getCookie();
         final int start = -1;
         final int end = originalText.length();
-        final ArrayList<SentenceWordItem> wordItems = new ArrayList<SentenceWordItem>();
+        final ArrayList<SentenceWordItem> wordItems = new ArrayList<>();
         int wordStart = wordIterator.getBeginningOfNextWord(originalText, start);
         int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
         while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
             if (wordEnd >= start && wordEnd > wordStart) {
-                CharSequence subSequence = originalText.subSequence(wordStart, wordEnd).toString();
-                final TextInfo ti = TextInfoCompatUtils.newInstance(subSequence, 0,
-                        subSequence.length(), cookie, subSequence.hashCode());
+                final TextInfo ti = TextInfoCompatUtils.newInstance(originalText, wordStart,
+                        wordEnd, cookie, originalText.subSequence(wordStart, wordEnd).hashCode());
                 wordItems.add(new SentenceWordItem(ti, wordStart, wordEnd));
             }
             wordStart = wordIterator.getBeginningOfNextWord(originalText, wordEnd);
@@ -159,6 +160,7 @@
         return new SentenceTextInfoParams(originalTextInfo, wordItems);
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     public static SentenceSuggestionsInfo reconstructSuggestions(
             SentenceTextInfoParams originalTextInfoParams, SuggestionsInfo[] results) {
         if (results == null || results.length == 0) {
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
index df9a761..294666b 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
@@ -18,7 +18,9 @@
 
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
+import android.annotation.TargetApi;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceActivity;
 
@@ -41,8 +43,8 @@
         return modIntent;
     }
 
-    // TODO: Uncomment the override annotation once we start using SDK version 19.
-    // @Override
+    @TargetApi(Build.VERSION_CODES.KITKAT)
+    @Override
     public boolean isValidFragment(String fragmentName) {
         return FragmentUtils.isValidFragment(fragmentName);
     }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java b/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java
new file mode 100644
index 0000000..f2491f4
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookup.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2015 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.spellcheck;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.UserDictionary;
+import android.util.Log;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.utils.ExecutorUtils;
+
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * UserDictionaryLookup provides the ability to lookup into the system-wide "Personal dictionary".
+ *
+ * Note, that the initial dictionary loading happens asynchronously so it is possible (hopefully
+ * rarely) that isValidWord is called before the initial load has started.
+ *
+ * The caller should explicitly call close() when the object is no longer needed, in order to
+ * release any resources and references to this object.  A service should create this object in
+ * onCreate and close() it in onDestroy.
+ */
+public class UserDictionaryLookup implements Closeable {
+    private static final String TAG = UserDictionaryLookup.class.getSimpleName();
+
+    /**
+     * This guards the execution of any Log.d() logging, so that if false, they are not even
+     */
+    private static final boolean DEBUG = false;
+
+    /**
+     * To avoid loading too many dictionary entries in memory, we cap them at this number.  If
+     * that number is exceeded, the lowest-frequency items will be dropped.  Note, there is no
+     * explicit cap on the number of locales in every entry.
+     */
+    private static final int MAX_NUM_ENTRIES = 1000;
+
+    /**
+     * The delay (in milliseconds) to impose on reloads.  Previously scheduled reloads will be
+     * cancelled if a new reload is scheduled before the delay expires.  Thus, only the last
+     * reload in the series of frequent reloads will execute.
+     *
+     * Note, this value should be low enough to allow the "Add to dictionary" feature in the
+     * TextView correction (red underline) drop-down menu to work properly in the following case:
+     *
+     *   1. User types OOV (out-of-vocabulary) word.
+     *   2. The OOV is red-underlined.
+     *   3. User selects "Add to dictionary".  The red underline disappears while the OOV is
+     *      in a composing span.
+     *   4. The user taps space.  The red underline should NOT reappear.  If this value is very
+     *      high and the user performs the space tap fast enough, the red underline may reappear.
+     */
+    @UsedForTesting
+    static final int RELOAD_DELAY_MS = 200;
+
+    private final ContentResolver mResolver;
+
+    /**
+     * Runnable that calls loadUserDictionary().
+     */
+    private class UserDictionaryLoader implements Runnable {
+        @Override
+        public void run() {
+            if (DEBUG) {
+                Log.d(TAG, "Executing (re)load");
+            }
+            loadUserDictionary();
+        }
+    }
+    private final UserDictionaryLoader mLoader = new UserDictionaryLoader();
+
+    /**
+     *  Content observer for UserDictionary changes.  It has the following properties:
+     *    1. It spawns off a UserDictionary reload in another thread, after some delay.
+     *    2. It cancels previously scheduled reloads, and only executes the latest.
+     *    3. It may be called multiple times quickly in succession (and is in fact called so
+     *       when UserDictionary is edited through its settings UI, when sometimes multiple
+     *       notifications are sent for the edited entry, but also for the entire UserDictionary).
+     */
+    private class UserDictionaryContentObserver extends ContentObserver {
+        public UserDictionaryContentObserver() {
+            super(null);
+        }
+
+        @Override
+        public boolean deliverSelfNotifications() {
+            return true;
+        }
+
+        // Support pre-API16 platforms.
+        @Override
+        public void onChange(boolean selfChange) {
+            onChange(selfChange, null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            if (DEBUG) {
+                Log.d(TAG, "Received content observer onChange notification for URI: " + uri);
+            }
+            // Cancel (but don't interrupt) any pending reloads (except the initial load).
+            if (mReloadFuture != null && !mReloadFuture.isCancelled() &&
+                    !mReloadFuture.isDone()) {
+                // Note, that if already cancelled or done, this will do nothing.
+                boolean isCancelled = mReloadFuture.cancel(false);
+                if (DEBUG) {
+                    if (isCancelled) {
+                        Log.d(TAG, "Successfully canceled previous reload request");
+                    } else {
+                        Log.d(TAG, "Unable to cancel previous reload request");
+                    }
+                }
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "Scheduling reload in " + RELOAD_DELAY_MS + " ms");
+            }
+
+            // Schedule a new reload after RELOAD_DELAY_MS.
+            mReloadFuture = ExecutorUtils.getBackgroundExecutor(ExecutorUtils.SPELLING)
+                    .schedule(mLoader, RELOAD_DELAY_MS, TimeUnit.MILLISECONDS);
+        }
+    }
+    private final ContentObserver mObserver = new UserDictionaryContentObserver();
+
+    /**
+     * Indicates that a load is in progress, so no need for another.
+     */
+    private AtomicBoolean mIsLoading = new AtomicBoolean(false);
+
+    /**
+     * Indicates that this lookup object has been close()d.
+     */
+    private AtomicBoolean mIsClosed = new AtomicBoolean(false);
+
+    /**
+     * We store a map from a dictionary word to the set of locales it belongs
+     * in. We then iterate over the set of locales to find a match using
+     * LocaleUtils.
+     */
+    private volatile HashMap<String, ArrayList<Locale>> mDictWords;
+
+    /**
+     *  The last-scheduled reload future.  Saved in order to cancel a pending reload if a new one
+     * is coming.
+     */
+    private volatile ScheduledFuture<?> mReloadFuture;
+
+    /**
+     * @param context the context from which to obtain content resolver
+     */
+    public UserDictionaryLookup(Context context) {
+        if (DEBUG) {
+            Log.d(TAG, "UserDictionaryLookup constructor with context: " + context);
+        }
+
+        // Obtain a content resolver.
+        mResolver = context.getContentResolver();
+
+        // Schedule the initial load to run immediately.  It's possible that the first call to
+        // isValidWord occurs before the dictionary has actually loaded, so it should not
+        // assume that the dictionary has been loaded.
+        ExecutorUtils.getBackgroundExecutor(ExecutorUtils.SPELLING).execute(mLoader);
+
+        // Register the observer to be notified on changes to the UserDictionary and all individual
+        // items.
+        //
+        // If the user is interacting with the UserDictionary settings UI, or with the
+        // "Add to dictionary" drop-down option, duplicate notifications will be sent for the same
+        // edit: if a new entry is added, there is a notification for the entry itself, and
+        // separately for the entire dictionary. However, when used programmatically,
+        // only notifications for the specific edits are sent. Thus, the observer is registered to
+        // receive every possible notification, and instead has throttling logic to avoid doing too
+        // many reloads.
+        mResolver.registerContentObserver(
+                UserDictionary.Words.CONTENT_URI, true /* notifyForDescendents */, mObserver);
+    }
+
+    /**
+     * To be called by the garbage collector in the off chance that the service did not clean up
+     * properly.  Do not rely on this getting called, and make sure close() is called explicitly.
+     */
+    @Override
+    public void finalize() throws Throwable {
+        try {
+            if (DEBUG) {
+                Log.d(TAG, "Finalize called, calling close()");
+            }
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Cleans up UserDictionaryLookup: shuts down any extra threads and unregisters the observer.
+     *
+     * It is safe, but not advised to call this multiple times, and isValidWord would continue to
+     * work, but no data will be reloaded any longer.
+     */
+    @Override
+    public void close() {
+        if (DEBUG) {
+            Log.d(TAG, "Close called (no pun intended), cleaning up executor and observer");
+        }
+        if (mIsClosed.compareAndSet(false, true)) {
+            // Unregister the content observer.
+            mResolver.unregisterContentObserver(mObserver);
+        }
+    }
+
+    /**
+     * Returns true if the initial load has been performed.
+     *
+     * @return true if the initial load is successful
+     */
+    @UsedForTesting
+    boolean isLoaded() {
+        return mDictWords != null;
+    }
+
+    /**
+     * Determines if the given word is a valid word in the given locale based on the UserDictionary.
+     * It tries hard to find a match: for example, casing is ignored and if the word is present in a
+     * more general locale (e.g. en or all locales), and isValidWord is asking for a more specific
+     * locale (e.g. en_US), it will be considered a match.
+     *
+     * @param word the word to match
+     * @param locale the locale in which to match the word
+     * @return true iff the word has been matched for this locale in the UserDictionary.
+     */
+    public boolean isValidWord(
+            final String word, final Locale locale) {
+        if (!isLoaded()) {
+            // This is a corner case in the event the initial load of UserDictionary has not
+            // been loaded. In that case, we assume the word is not a valid word in
+            // UserDictionary.
+            if (DEBUG) {
+                Log.d(TAG, "isValidWord invoked, but initial load not complete");
+            }
+            return false;
+        }
+
+        // Atomically obtain the current copy of mDictWords;
+        final HashMap<String, ArrayList<Locale>> dictWords = mDictWords;
+
+        if (DEBUG) {
+            Log.d(TAG, "isValidWord invoked for word [" + word +
+                    "] in locale " + locale);
+        }
+        // Lowercase the word using the given locale. Note, that dictionary
+        // words are lowercased using their locale, and theoretically the
+        // lowercasing between two matching locales may differ. For simplicity
+        // we ignore that possibility.
+        final String lowercased = word.toLowerCase(locale);
+        final ArrayList<Locale> dictLocales = dictWords.get(lowercased);
+        if (null == dictLocales) {
+            if (DEBUG) {
+                Log.d(TAG, "isValidWord=false, since there is no entry for " +
+                        "lowercased word [" + lowercased + "]");
+            }
+            return false;
+        } else {
+            if (DEBUG) {
+                Log.d(TAG, "isValidWord found an entry for lowercased word [" + lowercased +
+                        "]; examining locales");
+            }
+            // Iterate over the locales this word is in.
+            for (final Locale dictLocale : dictLocales) {
+                final int matchLevel = LocaleUtils.getMatchLevel(dictLocale.toString(),
+                        locale.toString());
+                if (DEBUG) {
+                    Log.d(TAG, "matchLevel for dictLocale=" + dictLocale + ", locale=" +
+                            locale + " is " + matchLevel);
+                }
+                if (LocaleUtils.isMatch(matchLevel)) {
+                    if (DEBUG) {
+                        Log.d(TAG, "isValidWord=true, since matchLevel " + matchLevel +
+                                " is a match");
+                    }
+                    return true;
+                }
+                if (DEBUG) {
+                    Log.d(TAG, "matchLevel " + matchLevel + " is not a match");
+                }
+            }
+            if (DEBUG) {
+                Log.d(TAG, "isValidWord=false, since none of the locales matched");
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Loads the UserDictionary in the current thread.
+     *
+     * Only one reload can happen at a time. If already running, will exit quickly.
+     */
+    private void loadUserDictionary() {
+        // Bail out if already in the process of loading.
+        if (!mIsLoading.compareAndSet(false, true)) {
+            if (DEBUG) {
+                Log.d(TAG, "Already in the process of loading UserDictionary, skipping");
+            }
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "Loading UserDictionary");
+        }
+        HashMap<String, ArrayList<Locale>> dictWords = new HashMap<>();
+        // Load the UserDictionary.  Request that items be returned in the default sort order
+        // for UserDictionary, which is by frequency.
+        Cursor cursor = mResolver.query(UserDictionary.Words.CONTENT_URI,
+                null, null, null, UserDictionary.Words.DEFAULT_SORT_ORDER);
+        if (null == cursor || cursor.getCount() < 1) {
+            if (DEBUG) {
+                Log.d(TAG, "No entries found in UserDictionary");
+            }
+        } else {
+            // Iterate over the entries in the UserDictionary.  Note, that iteration is in
+            // descending frequency by default.
+            while (dictWords.size() < MAX_NUM_ENTRIES && cursor.moveToNext()) {
+                // If there is no column for locale, skip this entry. An empty
+                // locale on the other hand will not be skipped.
+                final int dictLocaleIndex = cursor.getColumnIndex(
+                        UserDictionary.Words.LOCALE);
+                if (dictLocaleIndex < 0) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Encountered UserDictionary entry " +
+                                "without LOCALE, skipping");
+                    }
+                    continue;
+                }
+                // If there is no column for word, skip this entry.
+                final int dictWordIndex = cursor.getColumnIndex(
+                        UserDictionary.Words.WORD);
+                if (dictWordIndex < 0) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Encountered UserDictionary entry without " +
+                                "WORD, skipping");
+                    }
+                    continue;
+                }
+                // If the word is null, skip this entry.
+                final String rawDictWord = cursor.getString(dictWordIndex);
+                if (null == rawDictWord) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Encountered null word");
+                    }
+                    continue;
+                }
+                // If the locale is null, that's interpreted to mean all locales. Note, the special
+                // zz locale for an Alphabet (QWERTY) layout will not match any actual language.
+                String localeString = cursor.getString(dictLocaleIndex);
+                if (null == localeString) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Encountered null locale for word [" +
+                                rawDictWord + "], assuming all locales");
+                    }
+                    // For purposes of LocaleUtils, an empty locale matches
+                    // everything.
+                    localeString = "";
+                }
+                final Locale dictLocale = LocaleUtils.constructLocaleFromString(
+                        localeString);
+                // Lowercase the word before storing it.
+                final String dictWord = rawDictWord.toLowerCase(dictLocale);
+                if (DEBUG) {
+                    Log.d(TAG, "Incorporating UserDictionary word [" + dictWord +
+                            "] for locale " + dictLocale);
+                }
+                // Check if there is an existing entry for this word.
+                ArrayList<Locale> dictLocales = dictWords.get(dictWord);
+                if (null == dictLocales) {
+                    // If there is no entry for this word, create one.
+                    if (DEBUG) {
+                        Log.d(TAG, "Word [" + dictWord +
+                                "] not seen for other locales, creating new entry");
+                    }
+                    dictLocales = new ArrayList<>();
+                    dictWords.put(dictWord, dictLocales);
+                }
+                // Append the locale to the list of locales this word is in.
+                dictLocales.add(dictLocale);
+            }
+        }
+
+        // Atomically replace the copy of mDictWords.
+        mDictWords = dictWords;
+
+        // Allow other calls to loadUserDictionary to execute now.
+        mIsLoading.set(false);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
index 9d186d4..37ab266 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java
@@ -26,9 +26,9 @@
 import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.KeyboardParams;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.TypefaceUtils;
 
 public final class MoreSuggestions extends Keyboard {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
index f7b6f91..907e3fa 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java
@@ -40,6 +40,8 @@
         public abstract void onSuggestionSelected(final SuggestedWordInfo info);
     }
 
+    private boolean mIsInModalMode;
+
     public MoreSuggestionsView(final Context context, final AttributeSet attrs) {
         this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
     }
@@ -53,6 +55,7 @@
     @Override
     public void setKeyboard(final Keyboard keyboard) {
         super.setKeyboard(keyboard);
+        mIsInModalMode = false;
         // With accessibility mode off, {@link #mAccessibilityDelegate} is set to null at the
         // above {@link MoreKeysKeyboardView#setKeyboard(Keyboard)} call.
         // With accessibility mode on, {@link #mAccessibilityDelegate} is set to a
@@ -74,12 +77,17 @@
         updateKeyDrawParams(keyHeight);
     }
 
-    public void adjustVerticalCorrectionForModalMode() {
+    public void setModalMode() {
+        mIsInModalMode = true;
         // Set vertical correction to zero (Reset more keys keyboard sliding allowance
         // {@link R#dimen.config_more_keys_keyboard_slide_allowance}).
         mKeyDetector.setKeyboard(getKeyboard(), -getPaddingLeft(), -getPaddingTop());
     }
 
+    public boolean isInModalMode() {
+        return mIsInModalMode;
+    }
+
     @Override
     protected void onKeyInput(final Key key, final int x, final int y) {
         if (!(key instanceof MoreSuggestionKey)) {
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 1e8df89..d8926ff 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -28,7 +28,6 @@
 import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.support.v4.view.ViewCompat;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
@@ -50,16 +49,16 @@
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
-import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 import com.android.inputmethod.latin.utils.ViewLayoutUtils;
 
 import java.util.ArrayList;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 final class SuggestionStripLayoutHelper {
     private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
     private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f;
@@ -94,8 +93,6 @@
     private final int mTypedWordPositionWhenAutocorrect;
     private final Drawable mMoreSuggestionsHint;
     private static final String MORE_SUGGESTIONS_HINT = "\u2026";
-    private static final String LEFTWARDS_ARROW = "\u2190";
-    private static final String RIGHTWARDS_ARROW = "\u2192";
 
     private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
     private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
@@ -213,15 +210,14 @@
             return word;
         }
 
-        final int len = word.length();
         final Spannable spannedWord = new SpannableString(word);
         final int options = mSuggestionStripOptions;
         if ((isAutoCorrection && (options & AUTO_CORRECT_BOLD) != 0)
                 || (isTypedWordValid && (options & VALID_TYPED_WORD_BOLD) != 0)) {
-            spannedWord.setSpan(BOLD_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+            addStyleSpan(spannedWord, BOLD_SPAN);
         }
         if (isAutoCorrection && (options & AUTO_CORRECT_UNDERLINE) != 0) {
-            spannedWord.setSpan(UNDERLINE_SPAN, 0, len, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+            addStyleSpan(spannedWord, UNDERLINE_SPAN);
         }
         return spannedWord;
     }
@@ -238,9 +234,9 @@
         final SettingsValues settingsValues = Settings.getInstance().getCurrent();
         final boolean shouldOmitTypedWord = shouldOmitTypedWord(suggestedWords.mInputStyle,
                 settingsValues.mGestureFloatingPreviewTextEnabled,
-                settingsValues.mShouldShowUiToAcceptTypedWord);
+                settingsValues.mShouldShowLxxSuggestionUi);
         return getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords.mWillAutoCorrect,
-                settingsValues.mShouldShowUiToAcceptTypedWord && shouldOmitTypedWord,
+                settingsValues.mShouldShowLxxSuggestionUi && shouldOmitTypedWord,
                 mCenterPositionInStrip, mTypedWordPositionWhenAutocorrect);
     }
 
@@ -319,18 +315,6 @@
         } else {
             color = mColorSuggested;
         }
-        if (DebugFlags.DEBUG_ENABLED && suggestedWords.size() > 1) {
-            // If we auto-correct, then the autocorrection is in slot 0 and the typed word
-            // is in slot 1.
-            if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION
-                    && suggestedWords.mWillAutoCorrect
-                    && AutoCorrectionUtils.shouldBlockAutoCorrectionBySafetyNet(
-                            suggestedWords.getLabel(SuggestedWords.INDEX_OF_AUTO_CORRECTION),
-                            suggestedWords.getLabel(SuggestedWords.INDEX_OF_TYPED_WORD))) {
-                return 0xFFFF0000;
-            }
-        }
-
         if (suggestedWords.mIsObsoleteSuggestions && !isTypedWord) {
             return applyAlpha(color, mAlphaObsoleted);
         }
@@ -358,25 +342,30 @@
      * @param placerView the view where the debug info will be placed.
      * @return the start index of more suggestions.
      */
-    public int layoutAndReturnStartIndexOfMoreSuggestions(final SuggestedWords suggestedWords,
-            final ViewGroup stripView, final ViewGroup placerView) {
+    public int layoutAndReturnStartIndexOfMoreSuggestions(
+            final Context context,
+            final SuggestedWords suggestedWords,
+            final ViewGroup stripView,
+            final ViewGroup placerView) {
         if (suggestedWords.isPunctuationSuggestions()) {
             return layoutPunctuationsAndReturnStartIndexOfMoreSuggestions(
                     (PunctuationSuggestions)suggestedWords, stripView);
         }
 
+        final int wordCountToShow = suggestedWords.getWordCountToShow(
+                Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi);
         final int startIndexOfMoreSuggestions = setupWordViewsAndReturnStartIndexOfMoreSuggestions(
                 suggestedWords, mSuggestionsCountInStrip);
         final TextView centerWordView = mWordViews.get(mCenterPositionInStrip);
         final int stripWidth = stripView.getWidth();
         final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, stripWidth);
-        if (suggestedWords.size() == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
+        if (wordCountToShow == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
                 centerWordView.getPaint()) < MIN_TEXT_XSCALE) {
             // Layout only the most relevant suggested word at the center of the suggestion strip
             // by consolidating all slots in the strip.
             final int countInStrip = 1;
-            mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
-            layoutWord(mCenterPositionInStrip, stripWidth - mPadding);
+            mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
+            layoutWord(context, mCenterPositionInStrip, stripWidth - mPadding);
             stripView.addView(centerWordView);
             setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT);
             if (SuggestionStripView.DBG) {
@@ -387,7 +376,8 @@
         }
 
         final int countInStrip = mSuggestionsCountInStrip;
-        mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip);
+        mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
+        @SuppressWarnings("unused")
         int x = 0;
         for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
             if (positionInStrip != 0) {
@@ -398,7 +388,7 @@
             }
 
             final int width = getSuggestionWidth(positionInStrip, stripWidth);
-            final TextView wordView = layoutWord(positionInStrip, width);
+            final TextView wordView = layoutWord(context, positionInStrip, width);
             stripView.addView(wordView);
             setLayoutWeight(wordView, getSuggestionWeight(positionInStrip),
                     ViewGroup.LayoutParams.MATCH_PARENT);
@@ -427,7 +417,7 @@
      * @param width the maximum width for layout in pixels.
      * @return the {@link TextView} containing the suggested word appropriately formatted.
      */
-    private TextView layoutWord(final int positionInStrip, final int width) {
+    private TextView layoutWord(final Context context, final int positionInStrip, final int width) {
         final TextView wordView = mWordViews.get(positionInStrip);
         final CharSequence word = wordView.getText();
         if (positionInStrip == mCenterPositionInStrip && mMoreSuggestionsAvailable) {
@@ -441,11 +431,15 @@
         }
         // {@link StyleSpan} in a content description may cause an issue of TTS/TalkBack.
         // Use a simple {@link String} to avoid the issue.
-        wordView.setContentDescription(TextUtils.isEmpty(word) ? null : word.toString());
-        final CharSequence text = getEllipsizedText(word, width, wordView.getPaint());
-        final float scaleX = getTextScaleX(word, width, wordView.getPaint());
+        wordView.setContentDescription(
+                TextUtils.isEmpty(word)
+                    ? context.getResources().getString(R.string.spoken_empty_suggestion)
+                    : word.toString());
+        final CharSequence text = getEllipsizedTextWithSettingScaleX(
+                word, width, wordView.getPaint());
+        final float scaleX = wordView.getTextScaleX();
         wordView.setText(text); // TextView.setText() resets text scale x to 1.0.
-        wordView.setTextScaleX(Math.max(scaleX, MIN_TEXT_XSCALE));
+        wordView.setTextScaleX(scaleX);
         // A <code>wordView</code> should be disabled when <code>word</code> is empty in order to
         // make it unclickable.
         // With accessibility touch exploration on, <code>wordView</code> should be enabled even
@@ -548,55 +542,6 @@
         return countInStrip;
     }
 
-    public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip) {
-        final boolean shouldShowUiToAcceptTypedWord = Settings.getInstance().getCurrent()
-                .mShouldShowUiToAcceptTypedWord;
-        final int stripWidth = addToDictionaryStrip.getWidth();
-        final int width = shouldShowUiToAcceptTypedWord ? stripWidth
-                : stripWidth - mDividerWidth - mPadding * 2;
-
-        final TextView wordView = (TextView)addToDictionaryStrip.findViewById(R.id.word_to_save);
-        wordView.setTextColor(mColorTypedWord);
-        final int wordWidth = (int)(width * mCenterSuggestionWeight);
-        final CharSequence wordToSave = getEllipsizedText(word, wordWidth, wordView.getPaint());
-        final float wordScaleX = wordView.getTextScaleX();
-        wordView.setText(wordToSave);
-        wordView.setTextScaleX(wordScaleX);
-        setLayoutWeight(wordView, mCenterSuggestionWeight, ViewGroup.LayoutParams.MATCH_PARENT);
-        final int wordVisibility = shouldShowUiToAcceptTypedWord ? View.GONE : View.VISIBLE;
-        wordView.setVisibility(wordVisibility);
-        addToDictionaryStrip.findViewById(R.id.word_to_save_divider).setVisibility(wordVisibility);
-
-        final Resources res = addToDictionaryStrip.getResources();
-        final CharSequence hintText;
-        final int hintWidth;
-        final float hintWeight;
-        final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
-                R.id.hint_add_to_dictionary);
-        if (shouldShowUiToAcceptTypedWord) {
-            hintText = res.getText(R.string.hint_add_to_dictionary_without_word);
-            hintWidth = width;
-            hintWeight = 1.0f;
-            hintView.setGravity(Gravity.CENTER);
-        } else {
-            final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
-                    == ViewCompat.LAYOUT_DIRECTION_RTL);
-            final String arrow = isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW;
-            final boolean isRtlSystem = SubtypeLocaleUtils.isRtlLanguage(
-                    res.getConfiguration().locale);
-            final CharSequence hint = res.getText(R.string.hint_add_to_dictionary);
-            hintText = (isRtlLanguage == isRtlSystem) ? (arrow + hint) : (hint + arrow);
-            hintWidth = width - wordWidth;
-            hintWeight = 1.0f - mCenterSuggestionWeight;
-            hintView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
-        }
-        hintView.setTextColor(mColorAutoCorrect);
-        final float hintScaleX = getTextScaleX(hintText, hintWidth, hintView.getPaint());
-        hintView.setText(hintText);
-        hintView.setTextScaleX(hintScaleX);
-        setLayoutWeight(hintView, hintWeight, ViewGroup.LayoutParams.MATCH_PARENT);
-    }
-
     public void layoutImportantNotice(final View importantNoticeStrip,
             final String importantNoticeTitle) {
         final TextView titleView = (TextView)importantNoticeStrip.findViewById(
@@ -604,8 +549,7 @@
         final int width = titleView.getWidth() - titleView.getPaddingLeft()
                 - titleView.getPaddingRight();
         titleView.setTextColor(mColorAutoCorrect);
-        titleView.setText(importantNoticeTitle);
-        titleView.setTextScaleX(1.0f); // Reset textScaleX.
+        titleView.setText(importantNoticeTitle); // TextView.setText() resets text scale x to 1.0.
         final float titleScaleX = getTextScaleX(importantNoticeTitle, width, titleView.getPaint());
         titleView.setTextScaleX(titleScaleX);
     }
@@ -620,18 +564,19 @@
         }
     }
 
-    private static float getTextScaleX(final CharSequence text, final int maxWidth,
+    private static float getTextScaleX(@Nullable final CharSequence text, final int maxWidth,
             final TextPaint paint) {
         paint.setTextScaleX(1.0f);
         final int width = getTextWidth(text, paint);
         if (width <= maxWidth || maxWidth <= 0) {
             return 1.0f;
         }
-        return maxWidth / (float)width;
+        return maxWidth / (float) width;
     }
 
-    private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth,
-            final TextPaint paint) {
+    @Nullable
+    private static CharSequence getEllipsizedTextWithSettingScaleX(
+            @Nullable final CharSequence text, final int maxWidth, @Nonnull final TextPaint paint) {
         if (text == null) {
             return null;
         }
@@ -641,62 +586,63 @@
             return text;
         }
 
-        // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
-        // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
-        final float upscaledWidth = maxWidth / MIN_TEXT_XSCALE;
-        CharSequence ellipsized = TextUtils.ellipsize(
-                text, paint, upscaledWidth, TextUtils.TruncateAt.MIDDLE);
-        // For an unknown reason, ellipsized seems to return a text that does indeed fit inside the
-        // passed width according to paint.measureText, but not according to paint.getTextWidths.
-        // But when rendered, the text seems to actually take up as many pixels as returned by
-        // paint.getTextWidths, hence problem.
-        // To save this case, we compare the measured size of the new text, and if it's too much,
-        // try it again removing the difference. This may still give a text too long by one or
-        // two pixels so we take an additional 2 pixels cushion and call it a day.
-        // TODO: figure out why getTextWidths and measureText don't agree with each other, and
-        // remove the following code.
-        final float ellipsizedTextWidth = getTextWidth(ellipsized, paint);
-        if (upscaledWidth <= ellipsizedTextWidth) {
-            ellipsized = TextUtils.ellipsize(
-                    text, paint, upscaledWidth - (ellipsizedTextWidth - upscaledWidth) - 2,
-                    TextUtils.TruncateAt.MIDDLE);
-        }
+        // <code>text</code> must be ellipsized with minimum text scale x.
         paint.setTextScaleX(MIN_TEXT_XSCALE);
-        return ellipsized;
+        final boolean hasBoldStyle = hasStyleSpan(text, BOLD_SPAN);
+        final boolean hasUnderlineStyle = hasStyleSpan(text, UNDERLINE_SPAN);
+        // TextUtils.ellipsize erases any span object existed after ellipsized point.
+        // We have to restore these spans afterward.
+        final CharSequence ellipsizedText = TextUtils.ellipsize(
+                text, paint, maxWidth, TextUtils.TruncateAt.MIDDLE);
+        if (!hasBoldStyle && !hasUnderlineStyle) {
+            return ellipsizedText;
+        }
+        final Spannable spannableText = (ellipsizedText instanceof Spannable)
+                ? (Spannable)ellipsizedText : new SpannableString(ellipsizedText);
+        if (hasBoldStyle) {
+            addStyleSpan(spannableText, BOLD_SPAN);
+        }
+        if (hasUnderlineStyle) {
+            addStyleSpan(spannableText, UNDERLINE_SPAN);
+        }
+        return spannableText;
     }
 
-    private static int getTextWidth(final CharSequence text, final TextPaint paint) {
+    private static boolean hasStyleSpan(@Nullable final CharSequence text,
+            final CharacterStyle style) {
+        if (text instanceof Spanned) {
+            return ((Spanned)text).getSpanStart(style) >= 0;
+        }
+        return false;
+    }
+
+    private static void addStyleSpan(@Nonnull final Spannable text, final CharacterStyle style) {
+        text.removeSpan(style);
+        text.setSpan(style, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+    }
+
+    private static int getTextWidth(@Nullable final CharSequence text, final TextPaint paint) {
         if (TextUtils.isEmpty(text)) {
             return 0;
         }
+        final int length = text.length();
+        final float[] widths = new float[length];
+        final int count;
         final Typeface savedTypeface = paint.getTypeface();
-        paint.setTypeface(getTextTypeface(text));
-        final int len = text.length();
-        final float[] widths = new float[len];
-        final int count = paint.getTextWidths(text, 0, len, widths);
+        try {
+            paint.setTypeface(getTextTypeface(text));
+            count = paint.getTextWidths(text, 0, length, widths);
+        } finally {
+            paint.setTypeface(savedTypeface);
+        }
         int width = 0;
         for (int i = 0; i < count; i++) {
             width += Math.round(widths[i] + 0.5f);
         }
-        paint.setTypeface(savedTypeface);
         return width;
     }
 
-    private static Typeface getTextTypeface(final CharSequence text) {
-        if (!(text instanceof SpannableString)) {
-            return Typeface.DEFAULT;
-        }
-
-        final SpannableString ss = (SpannableString)text;
-        final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
-        if (styles.length == 0) {
-            return Typeface.DEFAULT;
-        }
-
-        if (styles[0].getStyle() == Typeface.BOLD) {
-            return Typeface.DEFAULT_BOLD;
-        }
-        // TODO: BOLD_ITALIC, ITALIC case?
-        return Typeface.DEFAULT;
+    private static Typeface getTextTypeface(@Nullable final CharSequence text) {
+        return hasStyleSpan(text, BOLD_SPAN) ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT;
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 0fd5e13..7dd0f03 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -43,10 +43,10 @@
 import com.android.inputmethod.keyboard.MainKeyboardView;
 import com.android.inputmethod.keyboard.MoreKeysPanel;
 import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsValues;
@@ -58,7 +58,6 @@
 public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
         OnLongClickListener {
     public interface Listener {
-        public void addWordToUserDictionary(String word);
         public void showImportantNoticeContents();
         public void pickSuggestionManually(SuggestedWordInfo word);
         public void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
@@ -69,7 +68,6 @@
 
     private final ViewGroup mSuggestionsStrip;
     private final ImageButton mVoiceKey;
-    private final ViewGroup mAddToDictionaryStrip;
     private final View mImportantNoticeStrip;
     MainKeyboardView mMainKeyboardView;
 
@@ -82,7 +80,7 @@
     private final ArrayList<View> mDividerViews = new ArrayList<>();
 
     Listener mListener;
-    private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
+    private SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance();
     private int mStartIndexOfMoreSuggestions;
 
     private final SuggestionStripLayoutHelper mLayoutHelper;
@@ -91,15 +89,12 @@
     private static class StripVisibilityGroup {
         private final View mSuggestionStripView;
         private final View mSuggestionsStrip;
-        private final View mAddToDictionaryStrip;
         private final View mImportantNoticeStrip;
 
         public StripVisibilityGroup(final View suggestionStripView,
-                final ViewGroup suggestionsStrip, final ViewGroup addToDictionaryStrip,
-                final View importantNoticeStrip) {
+                final ViewGroup suggestionsStrip, final View importantNoticeStrip) {
             mSuggestionStripView = suggestionStripView;
             mSuggestionsStrip = suggestionsStrip;
-            mAddToDictionaryStrip = addToDictionaryStrip;
             mImportantNoticeStrip = importantNoticeStrip;
             showSuggestionsStrip();
         }
@@ -109,30 +104,21 @@
                     : ViewCompat.LAYOUT_DIRECTION_LTR;
             ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
             ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
-            ViewCompat.setLayoutDirection(mAddToDictionaryStrip, layoutDirection);
             ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
         }
 
         public void showSuggestionsStrip() {
             mSuggestionsStrip.setVisibility(VISIBLE);
-            mAddToDictionaryStrip.setVisibility(INVISIBLE);
-            mImportantNoticeStrip.setVisibility(INVISIBLE);
-        }
-
-        public void showAddToDictionaryStrip() {
-            mSuggestionsStrip.setVisibility(INVISIBLE);
-            mAddToDictionaryStrip.setVisibility(VISIBLE);
             mImportantNoticeStrip.setVisibility(INVISIBLE);
         }
 
         public void showImportantNoticeStrip() {
             mSuggestionsStrip.setVisibility(INVISIBLE);
-            mAddToDictionaryStrip.setVisibility(INVISIBLE);
             mImportantNoticeStrip.setVisibility(VISIBLE);
         }
 
-        public boolean isShowingAddToDictionaryStrip() {
-            return mAddToDictionaryStrip.getVisibility() == VISIBLE;
+        public boolean isShowingImportantNoticeStrip() {
+            return mImportantNoticeStrip.getVisibility() == VISIBLE;
         }
     }
 
@@ -154,13 +140,13 @@
 
         mSuggestionsStrip = (ViewGroup)findViewById(R.id.suggestions_strip);
         mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
-        mAddToDictionaryStrip = (ViewGroup)findViewById(R.id.add_to_dictionary_strip);
         mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
         mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip,
-                mAddToDictionaryStrip, mImportantNoticeStrip);
+                mImportantNoticeStrip);
 
         for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
             final TextView word = new TextView(context, null, R.attr.suggestionWordStyle);
+            word.setContentDescription(getResources().getString(R.string.spoken_empty_suggestion));
             word.setOnClickListener(this);
             word.setOnLongClickListener(this);
             mWordViews.add(word);
@@ -215,7 +201,7 @@
         mStripVisibilityGroup.setLayoutDirection(isRtlLanguage);
         mSuggestedWords = suggestedWords;
         mStartIndexOfMoreSuggestions = mLayoutHelper.layoutAndReturnStartIndexOfMoreSuggestions(
-                mSuggestedWords, mSuggestionsStrip, this);
+                getContext(), mSuggestedWords, mSuggestionsStrip, this);
         mStripVisibilityGroup.showSuggestionsStrip();
     }
 
@@ -223,32 +209,12 @@
         mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
     }
 
-    public boolean isShowingAddToDictionaryHint() {
-        return mStripVisibilityGroup.isShowingAddToDictionaryStrip();
-    }
-
-    public void showAddToDictionaryHint(final String word) {
-        mLayoutHelper.layoutAddToDictionaryHint(word, mAddToDictionaryStrip);
-        // {@link TextView#setTag()} is used to hold the word to be added to dictionary. The word
-        // will be extracted at {@link #onClick(View)}.
-        mAddToDictionaryStrip.setTag(word);
-        mAddToDictionaryStrip.setOnClickListener(this);
-        mStripVisibilityGroup.showAddToDictionaryStrip();
-    }
-
-    public boolean dismissAddToDictionaryHint() {
-        if (isShowingAddToDictionaryHint()) {
-            clear();
-            return true;
-        }
-        return false;
-    }
-
     // This method checks if we should show the important notice (checks on permanent storage if
     // it has been shown once already or not, and if in the setup wizard). If applicable, it shows
     // the notice. In all cases, it returns true if it was shown, false otherwise.
     public boolean maybeShowImportantNoticeTitle() {
-        if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext())) {
+        final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
+        if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext(), currentSettingsValues)) {
             return false;
         }
         if (getWidth() <= 0) {
@@ -340,12 +306,6 @@
         if (mSuggestedWords.size() <= mStartIndexOfMoreSuggestions) {
             return false;
         }
-        // Dismiss another {@link MoreKeysPanel} that may be being showed, for example
-        // {@link MoreKeysKeyboardView}.
-        mMainKeyboardView.onDismissMoreKeysPanel();
-        // Dismiss all key previews and sliding key input preview that may be being showed.
-        mMainKeyboardView.dismissAllKeyPreviews();
-        mMainKeyboardView.dismissSlidingKeyInputPreview();
         final int stripWidth = getWidth();
         final View container = mMoreSuggestionsContainer;
         final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight();
@@ -393,11 +353,18 @@
 
     @Override
     public boolean onInterceptTouchEvent(final MotionEvent me) {
+        if (mStripVisibilityGroup.isShowingImportantNoticeStrip()) {
+            return false;
+        }
+        // Detecting sliding up finger to show {@link MoreSuggestionsView}.
         if (!mMoreSuggestionsView.isShowingInParent()) {
             mLastX = (int)me.getX();
             mLastY = (int)me.getY();
             return mMoreSuggestionsSlidingDetector.onTouchEvent(me);
         }
+        if (mMoreSuggestionsView.isInModalMode()) {
+            return false;
+        }
 
         final int action = me.getAction();
         final int index = me.getActionIndex();
@@ -416,7 +383,7 @@
 
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
             // Decided to be in the modal input mode.
-            mMoreSuggestionsView.adjustVerticalCorrectionForModalMode();
+            mMoreSuggestionsView.setModalMode();
         }
         return false;
     }
@@ -429,6 +396,11 @@
 
     @Override
     public boolean onTouchEvent(final MotionEvent me) {
+        if (!mMoreSuggestionsView.isShowingInParent()) {
+            // Ignore any touch event while more suggestions panel hasn't been shown.
+            // Detecting sliding up is done at {@link #onInterceptTouchEvent}.
+            return true;
+        }
         // In the sliding input mode. {@link MotionEvent} should be forwarded to
         // {@link MoreSuggestionsView}.
         final int index = me.getActionIndex();
@@ -484,15 +456,8 @@
                     false /* isKeyRepeat */);
             return;
         }
-        final Object tag = view.getTag();
-        // {@link String} tag is set at {@link #showAddToDictionaryHint(String,CharSequence)}.
-        if (tag instanceof String) {
-            final String wordToSave = (String)tag;
-            mListener.addWordToUserDictionary(wordToSave);
-            clear();
-            return;
-        }
 
+        final Object tag = view.getTag();
         // {@link Integer} tag is set at
         // {@link SuggestionStripLayoutHelper#setupWordViewsTextAndColor(SuggestedWords,int)} and
         // {@link SuggestionStripLayoutHelper#layoutPunctuationSuggestions(SuggestedWords,ViewGroup}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java
index 5270845..68f417e 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripViewAccessor.java
@@ -22,9 +22,6 @@
  * An object that gives basic control of a suggestion strip and some info on it.
  */
 public interface SuggestionStripViewAccessor {
-    public void showAddToDictionaryHint(final String word);
-    public boolean isShowingAddToDictionaryHint();
-    public void dismissAddToDictionaryHint();
     public void setNeutralSuggestionStrip();
     public void showSuggestionStrip(final SuggestedWords suggestedWords);
 }
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
index eda8194..cb615f3 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
@@ -26,14 +26,15 @@
 import android.view.View;
 import android.widget.EditText;
 
-import com.android.inputmethod.compat.UserDictionaryCompatUtils;
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
 
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.TreeSet;
 
+import javax.annotation.Nullable;
+
 // Caveat: This class is basically taken from
 // packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
 // in order to deal with some devices that have issues with the user dictionary handling
@@ -45,10 +46,7 @@
 public class UserDictionaryAddWordContents {
     public static final String EXTRA_MODE = "mode";
     public static final String EXTRA_WORD = "word";
-    public static final String EXTRA_SHORTCUT = "shortcut";
     public static final String EXTRA_LOCALE = "locale";
-    public static final String EXTRA_ORIGINAL_WORD = "originalWord";
-    public static final String EXTRA_ORIGINAL_SHORTCUT = "originalShortcut";
 
     public static final int MODE_EDIT = 0;
     public static final int MODE_INSERT = 1;
@@ -61,20 +59,12 @@
 
     private final int mMode; // Either MODE_EDIT or MODE_INSERT
     private final EditText mWordEditText;
-    private final EditText mShortcutEditText;
     private String mLocale;
     private final String mOldWord;
-    private final String mOldShortcut;
     private String mSavedWord;
-    private String mSavedShortcut;
 
     /* package */ UserDictionaryAddWordContents(final View view, final Bundle args) {
         mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
-        mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            mShortcutEditText.setVisibility(View.GONE);
-            view.findViewById(R.id.user_dictionary_add_shortcut_label).setVisibility(View.GONE);
-        }
         final String word = args.getString(EXTRA_WORD);
         if (null != word) {
             mWordEditText.setText(word);
@@ -82,17 +72,6 @@
             // it's too long to be edited.
             mWordEditText.setSelection(mWordEditText.getText().length());
         }
-        final String shortcut;
-        if (UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            shortcut = args.getString(EXTRA_SHORTCUT);
-            if (null != shortcut && null != mShortcutEditText) {
-                mShortcutEditText.setText(shortcut);
-            }
-            mOldShortcut = args.getString(EXTRA_SHORTCUT);
-        } else {
-            shortcut = null;
-            mOldShortcut = null;
-        }
         mMode = args.getInt(EXTRA_MODE); // default return value for #getInt() is 0 = MODE_EDIT
         mOldWord = args.getString(EXTRA_WORD);
         updateLocale(args.getString(EXTRA_LOCALE));
@@ -101,10 +80,8 @@
     /* package */ UserDictionaryAddWordContents(final View view,
             final UserDictionaryAddWordContents oldInstanceToBeEdited) {
         mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
-        mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
         mMode = MODE_EDIT;
         mOldWord = oldInstanceToBeEdited.mSavedWord;
-        mOldShortcut = oldInstanceToBeEdited.mSavedShortcut;
         updateLocale(mLocale);
     }
 
@@ -116,13 +93,6 @@
 
     /* package */ void saveStateIntoBundle(final Bundle outState) {
         outState.putString(EXTRA_WORD, mWordEditText.getText().toString());
-        outState.putString(EXTRA_ORIGINAL_WORD, mOldWord);
-        if (null != mShortcutEditText) {
-            outState.putString(EXTRA_SHORTCUT, mShortcutEditText.getText().toString());
-        }
-        if (null != mOldShortcut) {
-            outState.putString(EXTRA_ORIGINAL_SHORTCUT, mOldShortcut);
-        }
         outState.putString(EXTRA_LOCALE, mLocale);
     }
 
@@ -130,7 +100,7 @@
         if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
             // Mode edit: remove the old entry.
             final ContentResolver resolver = context.getContentResolver();
-            UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
+            UserDictionarySettings.deleteWord(mOldWord, resolver);
         }
         // If we are in add mode, nothing was added, so we don't need to do anything.
     }
@@ -141,50 +111,31 @@
         final ContentResolver resolver = context.getContentResolver();
         if (MODE_EDIT == mMode && !TextUtils.isEmpty(mOldWord)) {
             // Mode edit: remove the old entry.
-            UserDictionarySettings.deleteWord(mOldWord, mOldShortcut, resolver);
+            UserDictionarySettings.deleteWord(mOldWord, resolver);
         }
         final String newWord = mWordEditText.getText().toString();
-        final String newShortcut;
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
-            newShortcut = null;
-        } else if (null == mShortcutEditText) {
-            newShortcut = null;
-        } else {
-            final String tmpShortcut = mShortcutEditText.getText().toString();
-            if (TextUtils.isEmpty(tmpShortcut)) {
-                newShortcut = null;
-            } else {
-                newShortcut = tmpShortcut;
-            }
-        }
         if (TextUtils.isEmpty(newWord)) {
             // If the word is somehow empty, don't insert it.
             return CODE_CANCEL;
         }
         mSavedWord = newWord;
-        mSavedShortcut = newShortcut;
-        // If there is no shortcut, and the word already exists in the database, then we
-        // should not insert, because either A. the word exists with no shortcut, in which
-        // case the exact same thing we want to insert is already there, or B. the word
-        // exists with at least one shortcut, in which case it has priority on our word.
-        if (TextUtils.isEmpty(newShortcut) && hasWord(newWord, context)) {
+        // If the word already exists in the database, then we should not insert.
+        if (hasWord(newWord, context)) {
             return CODE_ALREADY_PRESENT;
         }
 
-        // Disallow duplicates. If the same word with no shortcut is defined, remove it; if
-        // the same word with the same shortcut is defined, remove it; but we don't mind if
-        // there is the same word with a different, non-empty shortcut.
-        UserDictionarySettings.deleteWord(newWord, null, resolver);
-        if (!TextUtils.isEmpty(newShortcut)) {
-            // If newShortcut is empty we just deleted this, no need to do it again
-            UserDictionarySettings.deleteWord(newWord, newShortcut, resolver);
-        }
+        // Disallow duplicates. If the same word is defined, remove it.
+        UserDictionarySettings.deleteWord(newWord, resolver);
 
         // In this class we use the empty string to represent 'all locales' and mLocale cannot
         // be null. However the addWord method takes null to mean 'all locales'.
-        UserDictionaryCompatUtils.addWord(context, newWord.toString(),
-                FREQUENCY_FOR_USER_DICTIONARY_ADDS, newShortcut, TextUtils.isEmpty(mLocale) ?
-                        null : LocaleUtils.constructLocaleFromString(mLocale));
+        final Locale locale = TextUtils.isEmpty(mLocale) ?
+                null : LocaleUtils.constructLocaleFromString(mLocale);
+        final Locale currentLocale = context.getResources().getConfiguration().locale;
+        final boolean useCurrentLocale = currentLocale.equals(locale);
+        UserDictionary.Words.addWord(context, newWord.toString(),
+                FREQUENCY_FOR_USER_DICTIONARY_ADDS, null /* shortcut */,
+                useCurrentLocale ? Locale.getDefault() : null);
 
         return CODE_WORD_ADDED;
     }
@@ -218,8 +169,8 @@
     public static class LocaleRenderer {
         private final String mLocaleString;
         private final String mDescription;
-        // LocaleString may NOT be null.
-        public LocaleRenderer(final Context context, final String localeString) {
+
+        public LocaleRenderer(final Context context, @Nullable final String localeString) {
             mLocaleString = localeString;
             if (null == localeString) {
                 mDescription = context.getString(R.string.user_dict_settings_more_languages);
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java
deleted file mode 100644
index 1634430..0000000
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java
+++ /dev/null
@@ -1,178 +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.userdictionary;
-
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.LocaleRenderer;
-import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker.LocationChangedListener;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-// Caveat: This class is basically taken from
-// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
-// in order to deal with some devices that have issues with the user dictionary handling
-
-/**
- * Fragment to add a word/shortcut to the user dictionary.
- *
- * As opposed to the UserDictionaryActivity, this is only invoked within Settings
- * from the UserDictionarySettings.
- */
-public class UserDictionaryAddWordFragment extends Fragment
-        implements AdapterView.OnItemSelectedListener, LocationChangedListener {
-
-    private static final int OPTIONS_MENU_ADD = Menu.FIRST;
-    private static final int OPTIONS_MENU_DELETE = Menu.FIRST + 1;
-
-    private UserDictionaryAddWordContents mContents;
-    private View mRootView;
-    private boolean mIsDeleting = false;
-
-    @Override
-    public void onActivityCreated(final Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        setHasOptionsMenu(true);
-        getActivity().getActionBar().setTitle(R.string.edit_personal_dictionary);
-        // Keep the instance so that we remember mContents when configuration changes (eg rotation)
-        setRetainInstance(true);
-    }
-
-    @Override
-    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
-            final Bundle savedState) {
-        mRootView = inflater.inflate(R.layout.user_dictionary_add_word_fullscreen, null);
-        mIsDeleting = false;
-        // If we have a non-null mContents object, it's the old value before a configuration
-        // change (eg rotation) so we need to use its values. Otherwise, read from the arguments.
-        if (null == mContents) {
-            mContents = new UserDictionaryAddWordContents(mRootView, getArguments());
-        } else {
-            // We create a new mContents object to account for the new situation : a word has
-            // been added to the user dictionary when we started rotating, and we are now editing
-            // it. That means in particular if the word undergoes any change, the old version should
-            // be updated, so the mContents object needs to switch to EDIT mode if it was in
-            // INSERT mode.
-            mContents = new UserDictionaryAddWordContents(mRootView,
-                    mContents /* oldInstanceToBeEdited */);
-        }
-        getActivity().getActionBar().setSubtitle(UserDictionarySettingsUtils.getLocaleDisplayName(
-                getActivity(), mContents.getCurrentUserDictionaryLocale()));
-        return mRootView;
-    }
-
-    @Override
-    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
-        final MenuItem actionItemAdd = menu.add(0, OPTIONS_MENU_ADD, 0,
-                R.string.user_dict_settings_add_menu_title).setIcon(R.drawable.ic_menu_add);
-        actionItemAdd.setShowAsAction(
-                MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-        final MenuItem actionItemDelete = menu.add(0, OPTIONS_MENU_DELETE, 0,
-                R.string.user_dict_settings_delete).setIcon(android.R.drawable.ic_menu_delete);
-        actionItemDelete.setShowAsAction(
-                MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-    }
-
-    /**
-     * Callback for the framework when a menu option is pressed.
-     *
-     * @param item the item that was pressed
-     * @return false to allow normal menu processing to proceed, true to consume it here
-     */
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == OPTIONS_MENU_ADD) {
-            // added the entry in "onPause"
-            getActivity().onBackPressed();
-            return true;
-        }
-        if (item.getItemId() == OPTIONS_MENU_DELETE) {
-            mContents.delete(getActivity());
-            mIsDeleting = true;
-            getActivity().onBackPressed();
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        // We are being shown: display the word
-        updateSpinner();
-    }
-
-    private void updateSpinner() {
-        final ArrayList<LocaleRenderer> localesList = mContents.getLocalesList(getActivity());
-
-        final Spinner localeSpinner =
-                (Spinner)mRootView.findViewById(R.id.user_dictionary_add_locale);
-        final ArrayAdapter<LocaleRenderer> adapter = new ArrayAdapter<>(
-                getActivity(), android.R.layout.simple_spinner_item, localesList);
-        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        localeSpinner.setAdapter(adapter);
-        localeSpinner.setOnItemSelectedListener(this);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        // We are being hidden: commit changes to the user dictionary, unless we were deleting it
-        if (!mIsDeleting) {
-            mContents.apply(getActivity(), null);
-        }
-    }
-
-    @Override
-    public void onItemSelected(final AdapterView<?> parent, final View view, final int pos,
-            final long id) {
-        final LocaleRenderer locale = (LocaleRenderer)parent.getItemAtPosition(pos);
-        if (locale.isMoreLanguages()) {
-            PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
-            preferenceActivity.startPreferenceFragment(new UserDictionaryLocalePicker(), true);
-        } else {
-            mContents.updateLocale(locale.getLocaleString());
-        }
-    }
-
-    @Override
-    public void onNothingSelected(final AdapterView<?> parent) {
-        // I'm not sure we can come here, but if we do, that's the right thing to do.
-        final Bundle args = getArguments();
-        mContents.updateLocale(args.getString(UserDictionaryAddWordContents.EXTRA_LOCALE));
-    }
-
-    // Called by the locale picker
-    @Override
-    public void onLocaleSelected(final Locale locale) {
-        mContents.updateLocale(locale.toString());
-        getActivity().onBackPressed();
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
index 624783a..57347ce 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
+import android.os.Build;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
@@ -31,12 +32,14 @@
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
 
 import java.util.List;
 import java.util.Locale;
 import java.util.TreeSet;
 
+import javax.annotation.Nullable;
+
 // Caveat: This class is basically taken from
 // packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java
 // in order to deal with some devices that have issues with the user dictionary handling
@@ -47,12 +50,12 @@
             "android.settings.USER_DICTIONARY_SETTINGS";
 
     @Override
-    public void onCreate(Bundle icicle) {
+    public void onCreate(final Bundle icicle) {
         super.onCreate(icicle);
         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
     }
 
-    public static TreeSet<String> getUserDictionaryLocalesSet(Activity activity) {
+    public static TreeSet<String> getUserDictionaryLocalesSet(final Activity activity) {
         final Cursor cursor = activity.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
                 new String[] { UserDictionary.Words.LOCALE },
                 null, null, null);
@@ -72,7 +75,7 @@
         } finally {
             cursor.close();
         }
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
             // For ICS, we need to show "For all languages" in case that the keyboard locale
             // is different from the system locale
             localeSet.add("");
@@ -108,7 +111,7 @@
      * Creates the entries that allow the user to go into the user dictionary for each locale.
      * @param userDictGroup The group to put the settings in.
      */
-    protected void createUserDictSettings(PreferenceGroup userDictGroup) {
+    protected void createUserDictSettings(final PreferenceGroup userDictGroup) {
         final Activity activity = getActivity();
         userDictGroup.removeAll();
         final TreeSet<String> localeSet =
@@ -121,31 +124,33 @@
         }
 
         if (localeSet.isEmpty()) {
-            userDictGroup.addPreference(createUserDictionaryPreference(null, activity));
+            userDictGroup.addPreference(createUserDictionaryPreference(null));
         } else {
             for (String locale : localeSet) {
-                userDictGroup.addPreference(createUserDictionaryPreference(locale, activity));
+                userDictGroup.addPreference(createUserDictionaryPreference(locale));
             }
         }
     }
 
     /**
      * Create a single User Dictionary Preference object, with its parameters set.
-     * @param locale The locale for which this user dictionary is for.
+     * @param localeString The locale for which this user dictionary is for.
      * @return The corresponding preference.
      */
-    protected Preference createUserDictionaryPreference(String locale, Activity activity) {
+    protected Preference createUserDictionaryPreference(@Nullable final String localeString) {
         final Preference newPref = new Preference(getActivity());
         final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
-        if (null == locale) {
+        if (null == localeString) {
             newPref.setTitle(Locale.getDefault().getDisplayName());
         } else {
-            if ("".equals(locale))
+            if (localeString.isEmpty()) {
                 newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
-            else
-                newPref.setTitle(LocaleUtils.constructLocaleFromString(locale).getDisplayName());
-            intent.putExtra("locale", locale);
-            newPref.getExtras().putString("locale", locale);
+            } else {
+                newPref.setTitle(
+                        LocaleUtils.constructLocaleFromString(localeString).getDisplayName());
+            }
+            intent.putExtra("locale", localeString);
+            newPref.getExtras().putString("locale", localeString);
         }
         newPref.setIntent(intent);
         newPref.setFragment(UserDictionarySettings.class.getName());
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
index cf2014a..bd35723 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
@@ -16,6 +16,12 @@
 
 package com.android.inputmethod.latin.userdictionary;
 
+import static com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.EXTRA_LOCALE;
+import static com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.EXTRA_MODE;
+import static com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.EXTRA_WORD;
+import static com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.MODE_EDIT;
+import static com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordContents.MODE_INSERT;
+
 import com.android.inputmethod.latin.R;
 
 import android.app.ListFragment;
@@ -25,7 +31,7 @@
 import android.database.Cursor;
 import android.os.Build;
 import android.os.Bundle;
-import android.provider.UserDictionary;
+import android.provider.UserDictionary.Words;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -48,62 +54,8 @@
 
 public class UserDictionarySettings extends ListFragment {
 
-    public static final boolean IS_SHORTCUT_API_SUPPORTED =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-
-    private static final String[] QUERY_PROJECTION_SHORTCUT_UNSUPPORTED =
-            { UserDictionary.Words._ID, UserDictionary.Words.WORD};
-    private static final String[] QUERY_PROJECTION_SHORTCUT_SUPPORTED =
-            { UserDictionary.Words._ID, UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT};
-    private static final String[] QUERY_PROJECTION =
-            IS_SHORTCUT_API_SUPPORTED ?
-                    QUERY_PROJECTION_SHORTCUT_SUPPORTED : QUERY_PROJECTION_SHORTCUT_UNSUPPORTED;
-
-    // The index of the shortcut in the above array.
-    private static final int INDEX_SHORTCUT = 2;
-
-    private static final String[] ADAPTER_FROM_SHORTCUT_UNSUPPORTED = {
-        UserDictionary.Words.WORD,
-    };
-
-    private static final String[] ADAPTER_FROM_SHORTCUT_SUPPORTED = {
-        UserDictionary.Words.WORD, UserDictionary.Words.SHORTCUT
-    };
-
-    private static final String[] ADAPTER_FROM = IS_SHORTCUT_API_SUPPORTED ?
-            ADAPTER_FROM_SHORTCUT_SUPPORTED : ADAPTER_FROM_SHORTCUT_UNSUPPORTED;
-
-    private static final int[] ADAPTER_TO_SHORTCUT_UNSUPPORTED = {
-        android.R.id.text1,
-    };
-
-    private static final int[] ADAPTER_TO_SHORTCUT_SUPPORTED = {
-        android.R.id.text1, android.R.id.text2
-    };
-
-    private static final int[] ADAPTER_TO = IS_SHORTCUT_API_SUPPORTED ?
-            ADAPTER_TO_SHORTCUT_SUPPORTED : ADAPTER_TO_SHORTCUT_UNSUPPORTED;
-
-    // Either the locale is empty (means the word is applicable to all locales)
-    // or the word equals our current locale
-    private static final String QUERY_SELECTION =
-            UserDictionary.Words.LOCALE + "=?";
-    private static final String QUERY_SELECTION_ALL_LOCALES =
-            UserDictionary.Words.LOCALE + " is null";
-
-    private static final String DELETE_SELECTION_WITH_SHORTCUT = UserDictionary.Words.WORD
-            + "=? AND " + UserDictionary.Words.SHORTCUT + "=?";
-    private static final String DELETE_SELECTION_WITHOUT_SHORTCUT = UserDictionary.Words.WORD
-            + "=? AND " + UserDictionary.Words.SHORTCUT + " is null OR "
-            + UserDictionary.Words.SHORTCUT + "=''";
-    private static final String DELETE_SELECTION_SHORTCUT_UNSUPPORTED =
-            UserDictionary.Words.WORD + "=?";
-
-    private static final int OPTIONS_MENU_ADD = Menu.FIRST;
-
     private Cursor mCursor;
-
-    protected String mLocale;
+    private String mLocale;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -172,55 +124,60 @@
         // TODO: it should be easy to make this more readable by making the special values
         // human-readable, like "all_locales" and "current_locales" strings, provided they
         // can be guaranteed not to match locales that may exist.
-        if ("".equals(locale)) {
+        if (TextUtils.isEmpty(locale)) {
             // Case-insensitive sort
-            return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
-                    QUERY_SELECTION_ALL_LOCALES, null,
-                    "UPPER(" + UserDictionary.Words.WORD + ")");
-        } else {
-            final String queryLocale = null != locale ? locale : Locale.getDefault().toString();
-            return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
-                    QUERY_SELECTION, new String[] { queryLocale },
-                    "UPPER(" + UserDictionary.Words.WORD + ")");
+            return getActivity().managedQuery(
+                    Words.CONTENT_URI,
+                    new String[] { Words._ID, Words.WORD },
+                    Words.LOCALE + " is null",
+                    null,
+                    "UPPER(" + Words.WORD + ")");
         }
+        return getActivity().managedQuery(
+                Words.CONTENT_URI,
+                new String[] { Words._ID, Words.WORD },
+                Words.LOCALE + "=?",
+                new String[] { locale },
+                "UPPER(" + Words.WORD + ")");
     }
 
     private ListAdapter createAdapter() {
-        return new MyAdapter(getActivity(), R.layout.user_dictionary_item, mCursor,
-                ADAPTER_FROM, ADAPTER_TO, this);
+        return new MyAdapter(
+                getActivity(),
+                R.layout.user_dictionary_item,
+                mCursor,
+                new String[] { Words.WORD },
+                new int[] { android.R.id.text1 });
     }
 
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
         final String word = getWord(position);
-        final String shortcut = getShortcut(position);
         if (word != null) {
-            showAddOrEditDialog(word, shortcut);
+            showAddOrEditDialog(word);
         }
     }
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
             final Locale systemLocale = getResources().getConfiguration().locale;
             if (!TextUtils.isEmpty(mLocale) && !mLocale.equals(systemLocale.toString())) {
                 // Hide the add button for ICS because it doesn't support specifying a locale
-                // for an entry. This new "locale"-aware API has been added in conjunction
-                // with the shortcut API.
+                // for an entry.
                 return;
             }
         }
-        MenuItem actionItem =
-                menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
-                .setIcon(R.drawable.ic_menu_add);
-        actionItem.setShowAsAction(
-                MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+        menu.add(0, Menu.FIRST, 0, R.string.user_dict_settings_add_menu_title)
+                .setIcon(R.drawable.ic_menu_add)
+                .setShowAsAction(
+                        MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == OPTIONS_MENU_ADD) {
-            showAddOrEditDialog(null, null);
+        if (item.getItemId() == Menu.FIRST) {
+            showAddOrEditDialog(null);
             return true;
         }
         return false;
@@ -229,20 +186,13 @@
     /**
      * Add or edit a word. If editingWord is null, it's an add; otherwise, it's an edit.
      * @param editingWord the word to edit, or null if it's an add.
-     * @param editingShortcut the shortcut for this entry, or null if none.
      */
-    private void showAddOrEditDialog(final String editingWord, final String editingShortcut) {
+    private void showAddOrEditDialog(final String editingWord) {
         final Bundle args = new Bundle();
-        args.putInt(UserDictionaryAddWordContents.EXTRA_MODE, null == editingWord
-                ? UserDictionaryAddWordContents.MODE_INSERT
-                : UserDictionaryAddWordContents.MODE_EDIT);
-        args.putString(UserDictionaryAddWordContents.EXTRA_WORD, editingWord);
-        args.putString(UserDictionaryAddWordContents.EXTRA_SHORTCUT, editingShortcut);
-        args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
-        android.preference.PreferenceActivity pa =
-                (android.preference.PreferenceActivity)getActivity();
-        pa.startPreferencePanel(UserDictionaryAddWordFragment.class.getName(),
-                args, R.string.user_dict_settings_add_dialog_title, null, null, 0);
+        args.putInt(EXTRA_MODE, editingWord == null ? MODE_INSERT : MODE_EDIT);
+        args.putString(EXTRA_WORD, editingWord);
+        args.putString(EXTRA_LOCALE, mLocale);
+        getActivity();
     }
 
     private String getWord(final int position) {
@@ -251,85 +201,44 @@
         // Handle a possible race-condition
         if (mCursor.isAfterLast()) return null;
 
-        return mCursor.getString(
-                mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD));
+        return mCursor.getString(mCursor.getColumnIndexOrThrow(Words.WORD));
     }
 
-    private String getShortcut(final int position) {
-        if (!IS_SHORTCUT_API_SUPPORTED) return null;
-        if (null == mCursor) return null;
-        mCursor.moveToPosition(position);
-        // Handle a possible race-condition
-        if (mCursor.isAfterLast()) return null;
-
-        return mCursor.getString(
-                mCursor.getColumnIndexOrThrow(UserDictionary.Words.SHORTCUT));
-    }
-
-    public static void deleteWord(final String word, final String shortcut,
-            final ContentResolver resolver) {
-        if (!IS_SHORTCUT_API_SUPPORTED) {
-            resolver.delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_SHORTCUT_UNSUPPORTED,
-                    new String[] { word });
-        } else if (TextUtils.isEmpty(shortcut)) {
-            resolver.delete(
-                    UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITHOUT_SHORTCUT,
-                    new String[] { word });
-        } else {
-            resolver.delete(
-                    UserDictionary.Words.CONTENT_URI, DELETE_SELECTION_WITH_SHORTCUT,
-                    new String[] { word, shortcut });
-        }
+    public static void deleteWord(final String word, final ContentResolver resolver) {
+        resolver.delete(Words.CONTENT_URI, Words.WORD + "=?", new String[] { word });
     }
 
     private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer {
-
         private AlphabetIndexer mIndexer;
 
         private ViewBinder mViewBinder = new ViewBinder() {
 
             @Override
-            public boolean setViewValue(View v, Cursor c, int columnIndex) {
-                if (!IS_SHORTCUT_API_SUPPORTED) {
-                    // just let SimpleCursorAdapter set the view values
-                    return false;
-                }
-                if (columnIndex == INDEX_SHORTCUT) {
-                    final String shortcut = c.getString(INDEX_SHORTCUT);
-                    if (TextUtils.isEmpty(shortcut)) {
-                        v.setVisibility(View.GONE);
-                    } else {
-                        ((TextView)v).setText(shortcut);
-                        v.setVisibility(View.VISIBLE);
-                    }
-                    v.invalidate();
-                    return true;
-                }
-
+            public boolean setViewValue(final View v, final Cursor c, final int columnIndex) {
+                // just let SimpleCursorAdapter set the view values
                 return false;
             }
         };
 
-        @SuppressWarnings("deprecation")
-        public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to,
-                UserDictionarySettings settings) {
-            super(context, layout, c, from, to);
+        public MyAdapter(final Context context, final int layout, final Cursor c,
+                final String[] from, final int[] to) {
+            super(context, layout, c, from, to, 0 /* flags */);
 
             if (null != c) {
                 final String alphabet = context.getString(R.string.user_dict_fast_scroll_alphabet);
-                final int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
+                final int wordColIndex = c.getColumnIndexOrThrow(Words.WORD);
                 mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
             }
             setViewBinder(mViewBinder);
         }
 
         @Override
-        public int getPositionForSection(int section) {
+        public int getPositionForSection(final int section) {
             return null == mIndexer ? 0 : mIndexer.getPositionForSection(section);
         }
 
         @Override
-        public int getSectionForPosition(int position) {
+        public int getSectionForPosition(final int position) {
             return null == mIndexer ? 0 : mIndexer.getSectionForPosition(position);
         }
 
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
index e58727e..c0a946e 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettingsUtils.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.latin.userdictionary;
 
 import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.common.LocaleUtils;
 
 import android.content.Context;
 import android.text.TextUtils;
diff --git a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
index db7f2a5..2aac7c5 100644
--- a/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtils.java
@@ -16,12 +16,12 @@
 
 package com.android.inputmethod.latin.utils;
 
-import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
 
 import android.os.Build;
 import android.text.TextUtils;
@@ -31,6 +31,7 @@
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
index d12aad6..952ac2a 100644
--- a/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
+++ b/java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java
@@ -59,11 +59,7 @@
      */
     public E get(final E defaultValue, final long timeOut) {
         try {
-            if (mLatch.await(timeOut, TimeUnit.MILLISECONDS)) {
-                return mResult;
-            } else {
-                return defaultValue;
-            }
+            return mLatch.await(timeOut, TimeUnit.MILLISECONDS) ? mResult : defaultValue;
         } catch (InterruptedException e) {
             return defaultValue;
         }
diff --git a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
index 156fcf5..c9ecade 100644
--- a/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/AutoCorrectionUtils.java
@@ -24,20 +24,22 @@
 public final class AutoCorrectionUtils {
     private static final boolean DBG = DebugFlags.DEBUG_ENABLED;
     private static final String TAG = AutoCorrectionUtils.class.getSimpleName();
-    private static final int MINIMUM_SAFETY_NET_CHAR_LENGTH = 4;
 
     private AutoCorrectionUtils() {
         // Purely static class: can't instantiate.
     }
 
-    public static boolean suggestionExceedsAutoCorrectionThreshold(
-            final SuggestedWordInfo suggestion, final String consideredWord,
-            final float autoCorrectionThreshold) {
+    public static boolean suggestionExceedsThreshold(final SuggestedWordInfo suggestion,
+            final String consideredWord, final float threshold) {
         if (null != suggestion) {
             // Shortlist a whitelisted word
             if (suggestion.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
                 return true;
             }
+            // TODO: return suggestion.isAprapreateForAutoCorrection();
+            if (!suggestion.isAprapreateForAutoCorrection()) {
+                return false;
+            }
             final int autoCorrectionSuggestionScore = suggestion.mScore;
             // TODO: when the normalized score of the first suggestion is nearly equals to
             //       the normalized score of the second suggestion, behave less aggressive.
@@ -46,47 +48,15 @@
             if (DBG) {
                 Log.d(TAG, "Normalized " + consideredWord + "," + suggestion + ","
                         + autoCorrectionSuggestionScore + ", " + normalizedScore
-                        + "(" + autoCorrectionThreshold + ")");
+                        + "(" + threshold + ")");
             }
-            if (normalizedScore >= autoCorrectionThreshold) {
+            if (normalizedScore >= threshold) {
                 if (DBG) {
-                    Log.d(TAG, "Auto corrected by S-threshold.");
+                    Log.d(TAG, "Exceeds threshold.");
                 }
-                return !shouldBlockAutoCorrectionBySafetyNet(consideredWord, suggestion.mWord);
+                return true;
             }
         }
         return false;
     }
-
-    // TODO: Resolve the inconsistencies between the native auto correction algorithms and
-    // this safety net
-    public static boolean shouldBlockAutoCorrectionBySafetyNet(final String typedWord,
-            final String suggestion) {
-        // Safety net for auto correction.
-        // Actually if we hit this safety net, it's a bug.
-        // If user selected aggressive auto correction mode, there is no need to use the safety
-        // net.
-        // If the length of typed word is less than MINIMUM_SAFETY_NET_CHAR_LENGTH,
-        // we should not use net because relatively edit distance can be big.
-        final int typedWordLength = typedWord.length();
-        if (typedWordLength < MINIMUM_SAFETY_NET_CHAR_LENGTH) {
-            return false;
-        }
-        final int maxEditDistanceOfNativeDictionary = (typedWordLength / 2) + 1;
-        final int distance = BinaryDictionaryUtils.editDistance(typedWord, suggestion);
-        if (DBG) {
-            Log.d(TAG, "Autocorrected edit distance = " + distance
-                    + ", " + maxEditDistanceOfNativeDictionary);
-        }
-        if (distance > maxEditDistanceOfNativeDictionary) {
-            if (DBG) {
-                Log.e(TAG, "Safety net: before = " + typedWord + ", after = " + suggestion);
-                Log.e(TAG, "(Error) The edit distance of this correction exceeds limit. "
-                        + "Turning off auto-correction.");
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
index 5d7deba..3bf9c62 100644
--- a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java
@@ -18,9 +18,9 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
-import com.android.inputmethod.latin.personalization.PersonalizationHelper;
 
 import java.io.File;
 import java.io.IOException;
@@ -40,10 +40,10 @@
         JniUtils.loadNativeLibrary();
     }
 
+    @UsedForTesting
     private static native boolean createEmptyDictFileNative(String filePath, long dictVersion,
             String locale, String[] attributeKeyStringArray, String[] attributeValueStringArray);
     private static native float calcNormalizedScoreNative(int[] before, int[] after, int score);
-    private static native int editDistanceNative(int[] before, int[] after);
     private static native int setCurrentTimeForTestNative(int currentTime);
 
     public static DictionaryHeader getHeader(final File dictFile)
@@ -112,14 +112,6 @@
                 StringUtils.toCodePointArray(after), score);
     }
 
-    public static int editDistance(final String before, final String after) {
-        if (before == null || after == null) {
-            throw new IllegalArgumentException();
-        }
-        return editDistanceNative(StringUtils.toCodePointArray(before),
-                StringUtils.toCodePointArray(after));
-    }
-
     /**
      * Control the current time to be used in the native code. If currentTime >= 0, this method sets
      * the current time and gets into test mode.
@@ -131,8 +123,6 @@
      */
     @UsedForTesting
     public static int setCurrentTimeForTest(final int currentTime) {
-        final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime);
-        PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp);
-        return currentNativeTimestamp;
+        return setCurrentTimeForTestNative(currentTime);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
index 9362193..0dbc7c8 100644
--- a/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CapsModeUtils.java
@@ -19,10 +19,12 @@
 import android.text.InputType;
 import android.text.TextUtils;
 
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 
+import java.util.ArrayList;
 import java.util.Locale;
 
 public final class CapsModeUtils {
@@ -213,12 +215,22 @@
         char c = cs.charAt(--j);
 
         // We found the next interesting chunk of text ; next we need to determine if it's the
-        // end of a sentence. If we have a question mark or an exclamation mark, it's the end of
-        // a sentence. If it's neither, the only remaining case is the period so we get the opposite
-        // case out of the way.
-        if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) {
-            return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
+        // end of a sentence. If we have a sentence terminator (typically a question mark or an
+        // exclamation mark), then it's the end of a sentence; however, we treat the abbreviation
+        // marker specially because usually is the same char as the sentence separator (the
+        // period in most languages) and in this case we need to apply a heuristic to determine
+        // in which of these senses it's used.
+        if (spacingAndPunctuations.isSentenceTerminator(c)
+                && !spacingAndPunctuations.isAbbreviationMarker(c)) {
+            return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
+                    | TextUtils.CAP_MODE_SENTENCES) & reqModes;
         }
+        // If we reach here, we know we have whitespace before the cursor and before that there
+        // is something that either does not terminate the sentence, or a symbol preceded by the
+        // start of the text, or it's the sentence separator AND it happens to be the same code
+        // point as the abbreviation marker.
+        // If it's a symbol or something that does not terminate the sentence, then we need to
+        // return caps for MODE_CHARACTERS and MODE_WORDS, but not for MODE_SENTENCES.
         if (!spacingAndPunctuations.isSentenceSeparator(c) || j <= 0) {
             return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
         }
@@ -315,4 +327,31 @@
         // Here we arrived at the start of the line. This should behave exactly like whitespace.
         return (START == state || LETTER == state) ? noCaps : caps;
     }
+
+    /**
+     * Convert capitalize mode flags into human readable text.
+     *
+     * @param capsFlags The modes flags to be converted. It may be any combination of
+     * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
+     * {@link TextUtils#CAP_MODE_SENTENCES}.
+     * @return the text that describe the <code>capsMode</code>.
+     */
+    public static String flagsToString(final int capsFlags) {
+        final int capsFlagsMask = TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
+                | TextUtils.CAP_MODE_SENTENCES;
+        if ((capsFlags & ~capsFlagsMask) != 0) {
+            return "unknown<0x" + Integer.toHexString(capsFlags) + ">";
+        }
+        final ArrayList<String> builder = new ArrayList<>();
+        if ((capsFlags & android.text.TextUtils.CAP_MODE_CHARACTERS) != 0) {
+            builder.add("characters");
+        }
+        if ((capsFlags & android.text.TextUtils.CAP_MODE_WORDS) != 0) {
+            builder.add("words");
+        }
+        if ((capsFlags & android.text.TextUtils.CAP_MODE_SENTENCES) != 0) {
+            builder.add("sentences");
+        }
+        return builder.isEmpty() ? "none" : TextUtils.join("|", builder);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
deleted file mode 100644
index 61292fc..0000000
--- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-
-public final class CollectionUtils {
-    private CollectionUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    public static <E> ArrayList<E> arrayAsList(final E[] array, final int start, final int end) {
-        if (array == null) {
-            throw new NullPointerException();
-        }
-        if (start < 0 || start > end || end > array.length) {
-            throw new IllegalArgumentException();
-        }
-
-        final ArrayList<E> list = new ArrayList<>(end - start);
-        for (int i = start; i < end; i++) {
-            list.add(array[i]);
-        }
-        return list;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index 34f59e8..5c0c432 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -17,8 +17,8 @@
 package com.android.inputmethod.latin.utils;
 
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
+import com.android.inputmethod.latin.makedict.NgramProperty;
 import com.android.inputmethod.latin.makedict.ProbabilityInfo;
-import com.android.inputmethod.latin.makedict.WeightedString;
 import com.android.inputmethod.latin.makedict.WordProperty;
 
 import java.util.HashMap;
@@ -26,14 +26,16 @@
 public class CombinedFormatUtils {
     public static final String DICTIONARY_TAG = "dictionary";
     public static final String BIGRAM_TAG = "bigram";
-    public static final String SHORTCUT_TAG = "shortcut";
+    public static final String NGRAM_TAG = "ngram";
+    public static final String NGRAM_PREV_WORD_TAG = "prev_word";
     public static final String PROBABILITY_TAG = "f";
     public static final String HISTORICAL_INFO_TAG = "historicalInfo";
     public static final String HISTORICAL_INFO_SEPARATOR = ":";
     public static final String WORD_TAG = "word";
     public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence";
     public static final String NOT_A_WORD_TAG = "not_a_word";
-    public static final String BLACKLISTED_TAG = "blacklisted";
+    public static final String POSSIBLY_OFFENSIVE_TAG = "possibly_offensive";
+    public static final String TRUE_VALUE = "true";
 
     public static String formatAttributeMap(final HashMap<String, String> attributeMap) {
         final StringBuilder builder = new StringBuilder();
@@ -58,29 +60,29 @@
         builder.append(",");
         builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo));
         if (wordProperty.mIsBeginningOfSentence) {
-            builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+            builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=" + TRUE_VALUE);
         }
         if (wordProperty.mIsNotAWord) {
-            builder.append("," + NOT_A_WORD_TAG + "=true");
+            builder.append("," + NOT_A_WORD_TAG + "=" + TRUE_VALUE);
         }
-        if (wordProperty.mIsBlacklistEntry) {
-            builder.append("," + BLACKLISTED_TAG + "=true");
+        if (wordProperty.mIsPossiblyOffensive) {
+            builder.append("," + POSSIBLY_OFFENSIVE_TAG + "=" + TRUE_VALUE);
         }
         builder.append("\n");
-        if (wordProperty.mShortcutTargets != null) {
-            for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                builder.append("  " + SHORTCUT_TAG + "=" + shortcutTarget.mWord);
+        if (wordProperty.mHasNgrams) {
+            for (final NgramProperty ngramProperty : wordProperty.mNgrams) {
+                builder.append(" " + NGRAM_TAG + "=" + ngramProperty.mTargetWord.mWord);
                 builder.append(",");
-                builder.append(formatProbabilityInfo(shortcutTarget.mProbabilityInfo));
+                builder.append(formatProbabilityInfo(ngramProperty.mTargetWord.mProbabilityInfo));
                 builder.append("\n");
-            }
-        }
-        if (wordProperty.mBigrams != null) {
-            for (final WeightedString bigram : wordProperty.mBigrams) {
-                builder.append("  " + BIGRAM_TAG + "=" + bigram.mWord);
-                builder.append(",");
-                builder.append(formatProbabilityInfo(bigram.mProbabilityInfo));
-                builder.append("\n");
+                for (int i = 0; i < ngramProperty.mNgramContext.getPrevWordCount(); i++) {
+                    builder.append("  " + NGRAM_PREV_WORD_TAG + "[" + i + "]="
+                            + ngramProperty.mNgramContext.getNthPrevWord(i + 1));
+                    if (ngramProperty.mNgramContext.isNthPrevWordBeginningOfSentence(i + 1)) {
+                        builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+                    }
+                    builder.append("\n");
+                }
             }
         }
         return builder.toString();
@@ -100,4 +102,8 @@
         }
         return builder.toString();
     }
+
+    public static boolean isLiteralTrue(final String value) {
+        return TRUE_VALUE.equalsIgnoreCase(value);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java b/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java
deleted file mode 100644
index 87df013..0000000
--- a/java/src/com/android/inputmethod/latin/utils/CoordinateUtils.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import java.util.Arrays;
-
-public final class CoordinateUtils {
-    private static final int INDEX_X = 0;
-    private static final int INDEX_Y = 1;
-    private static final int ELEMENT_SIZE = INDEX_Y + 1;
-
-    private CoordinateUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    public static int[] newInstance() {
-        return new int[ELEMENT_SIZE];
-    }
-
-    public static int x(final int[] coords) {
-        return coords[INDEX_X];
-    }
-
-    public static int y(final int[] coords) {
-        return coords[INDEX_Y];
-    }
-
-    public static void set(final int[] coords, final int x, final int y) {
-        coords[INDEX_X] = x;
-        coords[INDEX_Y] = y;
-    }
-
-    public static void copy(final int[] destination, final int[] source) {
-        destination[INDEX_X] = source[INDEX_X];
-        destination[INDEX_Y] = source[INDEX_Y];
-    }
-
-    public static int[] newCoordinateArray(final int arraySize) {
-        return new int[ELEMENT_SIZE * arraySize];
-    }
-
-    public static int[] newCoordinateArray(final int arraySize,
-            final int defaultX, final int defaultY) {
-        final int[] result = new int[ELEMENT_SIZE * arraySize];
-        for (int i = 0; i < arraySize; ++i) {
-            setXYInArray(result, i, defaultX, defaultY);
-        }
-        return result;
-    }
-
-    public static int xFromArray(final int[] coordsArray, final int index) {
-        return coordsArray[ELEMENT_SIZE * index + INDEX_X];
-    }
-
-    public static int yFromArray(final int[] coordsArray, final int index) {
-        return coordsArray[ELEMENT_SIZE * index + INDEX_Y];
-    }
-
-    public static int[] coordinateFromArray(final int[] coordsArray, final int index) {
-        final int baseIndex = ELEMENT_SIZE * index;
-        return Arrays.copyOfRange(coordsArray, baseIndex, baseIndex + ELEMENT_SIZE);
-    }
-
-    public static void setXYInArray(final int[] coordsArray, final int index,
-            final int x, final int y) {
-        final int baseIndex = ELEMENT_SIZE * index;
-        coordsArray[baseIndex + INDEX_X] = x;
-        coordsArray[baseIndex + INDEX_Y] = y;
-    }
-
-    public static void setCoordinateInArray(final int[] coordsArray, final int index,
-            final int[] coords) {
-        final int baseIndex = ELEMENT_SIZE * index;
-        coordsArray[baseIndex + INDEX_X] = coords[INDEX_X];
-        coordsArray[baseIndex + INDEX_Y] = coords[INDEX_Y];
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
index 9dc0524..c90d30c 100644
--- a/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CursorAnchorInfoUtils.java
@@ -16,17 +16,26 @@
 
 package com.android.inputmethod.latin.utils;
 
+import android.annotation.TargetApi;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.inputmethodservice.ExtractEditText;
 import android.inputmethodservice.InputMethodService;
+import android.os.Build;
 import android.text.Layout;
 import android.text.Spannable;
+import android.text.Spanned;
 import android.view.View;
 import android.view.ViewParent;
 import android.view.inputmethod.CursorAnchorInfo;
 import android.widget.TextView;
 
+import com.android.inputmethod.compat.BuildCompatUtils;
+import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * This class allows input methods to extract {@link CursorAnchorInfo} directly from the given
  * {@link TextView}. This is useful and even necessary to support full-screen mode where the default
@@ -77,13 +86,32 @@
     }
 
     /**
+     * Extracts {@link CursorAnchorInfoCompatWrapper} from the given {@link TextView}.
+     * @param textView the target text view from which {@link CursorAnchorInfoCompatWrapper} is to
+     * be extracted.
+     * @return the {@link CursorAnchorInfoCompatWrapper} object based on the current layout.
+     * {@code null} if {@code Build.VERSION.SDK_INT} is 20 or prior or {@link TextView} is not
+     * ready to provide layout information.
+     */
+    @Nullable
+    public static CursorAnchorInfoCompatWrapper extractFromTextView(
+            @Nonnull final TextView textView) {
+        if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            return null;
+        }
+        return CursorAnchorInfoCompatWrapper.wrap(extractFromTextViewInternal(textView));
+    }
+
+    /**
      * Returns {@link CursorAnchorInfo} from the given {@link TextView}.
      * @param textView the target text view from which {@link CursorAnchorInfo} is to be extracted.
      * @return the {@link CursorAnchorInfo} object based on the current layout. {@code null} if it
      * is not feasible.
      */
-    public static CursorAnchorInfo getCursorAnchorInfo(final TextView textView) {
-        Layout layout = textView.getLayout();
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @Nullable
+    private static CursorAnchorInfo extractFromTextViewInternal(@Nonnull final TextView textView) {
+        final Layout layout = textView.getLayout();
         if (layout == null) {
             return null;
         }
@@ -122,7 +150,7 @@
             final Object[] spans = spannable.getSpans(0, text.length(), Object.class);
             for (Object span : spans) {
                 final int spanFlag = spannable.getSpanFlags(span);
-                if ((spanFlag & Spannable.SPAN_COMPOSING) != 0) {
+                if ((spanFlag & Spanned.SPAN_COMPOSING) != 0) {
                     composingTextStart = Math.min(composingTextStart,
                             spannable.getSpanStart(span));
                     composingTextEnd = Math.max(composingTextEnd, spannable.getSpanEnd(span));
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index 1979080..25fa723 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -22,11 +22,15 @@
 import android.content.res.Resources;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.AssetFileAddress;
 import com.android.inputmethod.latin.BinaryDictionaryGetter;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
@@ -35,9 +39,13 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * This class encapsulates the logic for the Latin-IME side of dictionary information management.
  */
@@ -46,6 +54,7 @@
     private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
     private static final String DEFAULT_MAIN_DICT = "main";
     private static final String MAIN_DICT_PREFIX = "main_";
+    private static final String DECODER_DICT_SUFFIX = DecoderSpecificConstants.DECODER_DICT_SUFFIX;
     // 6 digits - unicode is limited to 21 bits
     private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6;
 
@@ -57,28 +66,36 @@
         private static final String DATE_COLUMN = "date";
         private static final String FILESIZE_COLUMN = "filesize";
         private static final String VERSION_COLUMN = "version";
+        @Nonnull
         public final String mId;
+        @Nonnull
         public final Locale mLocale;
+        @Nullable
         public final String mDescription;
         public final AssetFileAddress mFileAddress;
         public final int mVersion;
-        public DictionaryInfo(final String id, final Locale locale, final String description,
-                final AssetFileAddress fileAddress, final int version) {
+
+        public DictionaryInfo(@Nonnull final String id, @Nonnull final Locale locale,
+                @Nullable final String description, @Nullable final AssetFileAddress fileAddress,
+                final int version) {
             mId = id;
             mLocale = locale;
             mDescription = description;
             mFileAddress = fileAddress;
             mVersion = version;
         }
+
         public ContentValues toContentValues() {
             final ContentValues values = new ContentValues();
             values.put(WORDLISTID_COLUMN, mId);
             values.put(LOCALE_COLUMN, mLocale.toString());
             values.put(DESCRIPTION_COLUMN, mDescription);
-            values.put(LOCAL_FILENAME_COLUMN, mFileAddress.mFilename);
+            values.put(LOCAL_FILENAME_COLUMN,
+                    mFileAddress != null ? mFileAddress.mFilename : "");
             values.put(DATE_COLUMN, TimeUnit.MILLISECONDS.toSeconds(
-                    new File(mFileAddress.mFilename).lastModified()));
-            values.put(FILESIZE_COLUMN, mFileAddress.mLength);
+                    mFileAddress != null ? new File(mFileAddress.mFilename).lastModified() : 0));
+            values.put(FILESIZE_COLUMN,
+                    mFileAddress != null ? mFileAddress.mLength : 0);
             values.put(VERSION_COLUMN, mVersion);
             return values;
         }
@@ -140,9 +157,10 @@
     }
 
     /**
-     * Reverse escaping done by replaceFileNameDangerousCharacters.
+     * Reverse escaping done by {@link #replaceFileNameDangerousCharacters(String)}.
      */
-    public static String getWordListIdFromFileName(final String fname) {
+    @Nonnull
+    public static String getWordListIdFromFileName(@Nonnull final String fname) {
         final StringBuilder sb = new StringBuilder();
         final int fnameLength = fname.length();
         for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
@@ -174,12 +192,15 @@
      * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
      * @return The category as a string or null if it can't be found in the file name.
      */
-    public static String getCategoryFromFileName(final String fileName) {
+    @Nullable
+    public static String getCategoryFromFileName(@Nonnull final String fileName) {
         final String id = getWordListIdFromFileName(fileName);
         final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
         // An id is supposed to be in format category:locale, so splitting on the separator
         // should yield a 2-elements array
-        if (2 != idArray.length) return null;
+        if (2 != idArray.length) {
+            return null;
+        }
         return idArray[0];
     }
 
@@ -223,12 +244,26 @@
         final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
         // An id is supposed to be in format category:locale, so splitting on the separator
         // should yield a 2-elements array
-        if (2 != idArray.length) return false;
+        if (2 != idArray.length) {
+            return false;
+        }
         return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
     }
 
     /**
+     * Find out whether a dictionary is available for this locale.
+     * @param context the context on which to check resources.
+     * @param locale the locale to check for.
+     * @return whether a (non-placeholder) dictionary is available or not.
+     */
+    public static boolean isDictionaryAvailable(final Context context, final Locale locale) {
+        final Resources res = context.getResources();
+        return 0 != getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
+    }
+
+    /**
      * Helper method to return a dictionary res id for a locale, or 0 if none.
+     * @param res resources for the app
      * @param locale dictionary locale
      * @return main dictionary resource id
      */
@@ -237,8 +272,8 @@
         int resId;
         // Try to find main_language_country dictionary.
         if (!locale.getCountry().isEmpty()) {
-            final String dictLanguageCountry =
-                    MAIN_DICT_PREFIX + locale.toString().toLowerCase(Locale.ROOT);
+            final String dictLanguageCountry = MAIN_DICT_PREFIX
+                    + locale.toString().toLowerCase(Locale.ROOT) + DECODER_DICT_SUFFIX;
             if ((resId = res.getIdentifier(
                     dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
                 return resId;
@@ -246,7 +281,7 @@
         }
 
         // Try to find main_language dictionary.
-        final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
+        final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage() + DECODER_DICT_SUFFIX;
         if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
             return resId;
         }
@@ -257,13 +292,17 @@
 
     /**
      * Returns a main dictionary resource id
+     * @param res resources for the app
      * @param locale dictionary locale
      * @return main dictionary resource id
      */
     public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
         int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
-        if (0 != resourceId) return resourceId;
-        return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
+        if (0 != resourceId) {
+            return resourceId;
+        }
+        return res.getIdentifier(DEFAULT_MAIN_DICT + DecoderSpecificConstants.DECODER_DICT_SUFFIX,
+                "raw", RESOURCE_PACKAGE_NAME);
     }
 
     /**
@@ -274,19 +313,15 @@
      * unique ID to them. This ID is just the name of the language (locale-wise) they
      * are for, and this method returns this ID.
      */
-    public static String getMainDictId(final Locale locale) {
+    public static String getMainDictId(@Nonnull final Locale locale) {
         // This works because we don't include by default different dictionaries for
         // different countries. This actually needs to return the id that we would
         // like to use for word lists included in resources, and the following is okay.
         return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY +
-                BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
+                BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale.toString().toLowerCase();
     }
 
-    public static DictionaryHeader getDictionaryFileHeaderOrNull(final File file) {
-        return getDictionaryFileHeaderOrNull(file, 0, file.length());
-    }
-
-    private static DictionaryHeader getDictionaryFileHeaderOrNull(final File file,
+    public static DictionaryHeader getDictionaryFileHeaderOrNull(final File file,
             final long offset, final long length) {
         try {
             final DictionaryHeader header =
@@ -303,20 +338,27 @@
      * Returns information of the dictionary.
      *
      * @param fileAddress the asset dictionary file address.
+     * @param locale Locale for this file.
      * @return information of the specified dictionary.
      */
     private static DictionaryInfo createDictionaryInfoFromFileAddress(
-            final AssetFileAddress fileAddress) {
-        final DictionaryHeader header = getDictionaryFileHeaderOrNull(
-                new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength);
-        if (header == null) {
-            return null;
-        }
-        final String id = header.getId();
-        final Locale locale = LocaleUtils.constructLocaleFromString(header.getLocaleString());
-        final String description = header.getDescription();
-        final String version = header.getVersion();
-        return new DictionaryInfo(id, locale, description, fileAddress, Integer.parseInt(version));
+            final AssetFileAddress fileAddress, Locale locale) {
+        final String id = getMainDictId(locale);
+        final int version = DictionaryHeaderUtils.getContentVersion(fileAddress);
+        final String description = SubtypeLocaleUtils
+                .getSubtypeLocaleDisplayName(locale.toString());
+        return new DictionaryInfo(id, locale, description, fileAddress, version);
+    }
+
+    /**
+     * Returns dictionary information for the given locale.
+     */
+    private static DictionaryInfo createDictionaryInfoFromLocale(Locale locale) {
+        final String id = getMainDictId(locale);
+        final int version = -1;
+        final String description = SubtypeLocaleUtils
+                .getSubtypeLocaleDisplayName(locale.toString());
+        return new DictionaryInfo(id, locale, description, null, version);
     }
 
     private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList,
@@ -343,18 +385,23 @@
         if (null != directoryList) {
             for (final File directory : directoryList) {
                 final String localeString = getWordListIdFromFileName(directory.getName());
-                File[] dicts = BinaryDictionaryGetter.getCachedWordLists(localeString, context);
+                final File[] dicts = BinaryDictionaryGetter.getCachedWordLists(
+                        localeString, context);
                 for (final File dict : dicts) {
                     final String wordListId = getWordListIdFromFileName(dict.getName());
-                    if (!DictionaryInfoUtils.isMainWordListId(wordListId)) continue;
+                    if (!DictionaryInfoUtils.isMainWordListId(wordListId)) {
+                        continue;
+                    }
                     final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
                     final AssetFileAddress fileAddress = AssetFileAddress.makeFromFile(dict);
                     final DictionaryInfo dictionaryInfo =
-                            createDictionaryInfoFromFileAddress(fileAddress);
+                            createDictionaryInfoFromFileAddress(fileAddress, locale);
                     // Protect against cases of a less-specific dictionary being found, like an
                     // en dictionary being used for an en_US locale. In this case, the en dictionary
                     // should be used for en_US but discounted for listing purposes.
-                    if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) continue;
+                    if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) {
+                        continue;
+                    }
                     addOrUpdateDictInfo(dictList, dictionaryInfo);
                 }
             }
@@ -368,25 +415,45 @@
             final int resourceId =
                     DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
                             context.getResources(), locale);
-            if (0 == resourceId) continue;
+            if (0 == resourceId) {
+                continue;
+            }
             final AssetFileAddress fileAddress =
                     BinaryDictionaryGetter.loadFallbackResource(context, resourceId);
-            final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress);
+            final DictionaryInfo dictionaryInfo = createDictionaryInfoFromFileAddress(fileAddress,
+                    locale);
             // Protect against cases of a less-specific dictionary being found, like an
             // en dictionary being used for an en_US locale. In this case, the en dictionary
             // should be used for en_US but discounted for listing purposes.
-            if (!dictionaryInfo.mLocale.equals(locale)) continue;
+            // TODO: Remove dictionaryInfo == null when the static LMs have the headers.
+            if (dictionaryInfo == null || !dictionaryInfo.mLocale.equals(locale)) {
+                continue;
+            }
+            addOrUpdateDictInfo(dictList, dictionaryInfo);
+        }
+
+        // Generate the dictionary information from  the enabled subtypes. This will not
+        // overwrite the real records.
+        RichInputMethodManager.init(context);
+        List<InputMethodSubtype> enabledSubtypes = RichInputMethodManager
+                .getInstance().getMyEnabledInputMethodSubtypeList(true);
+        for (InputMethodSubtype subtype : enabledSubtypes) {
+            Locale locale = LocaleUtils.constructLocaleFromString(subtype.getLocale());
+            DictionaryInfo dictionaryInfo = createDictionaryInfoFromLocale(locale);
             addOrUpdateDictInfo(dictList, dictionaryInfo);
         }
 
         return dictList;
     }
 
+    @UsedForTesting
     public static boolean looksValidForDictionaryInsertion(final CharSequence text,
             final SpacingAndPunctuations spacingAndPunctuations) {
-        if (TextUtils.isEmpty(text)) return false;
+        if (TextUtils.isEmpty(text)) {
+            return false;
+        }
         final int length = text.length();
-        if (length > Constants.DICTIONARY_MAX_WORD_LENGTH) {
+        if (length > DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) {
             return false;
         }
         int i = 0;
@@ -400,7 +467,9 @@
                 digitCount += charCount;
                 continue;
             }
-            if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false;
+            if (!spacingAndPunctuations.isWordCodePoint(codePoint)) {
+                return false;
+            }
         }
         // We reject strings entirely comprised of digits to avoid using PIN codes or credit
         // card numbers. It would come in handy for word prediction though; a good example is
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
deleted file mode 100644
index 787e4a5..0000000
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import java.util.List;
-import java.util.Locale;
-
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.PrevWordsInfo;
-
-public interface DistracterFilter {
-    /**
-     * Determine whether a word is a distracter to words in dictionaries.
-     *
-     * @param prevWordsInfo the information of previous words.
-     * @param testedWord the word that will be tested to see whether it is a distracter to words
-     *                   in dictionaries.
-     * @param locale the locale of word.
-     * @return true if testedWord is a distracter, otherwise false.
-     */
-    public boolean isDistracterToWordsInDictionaries(final PrevWordsInfo prevWordsInfo,
-            final String testedWord, final Locale locale);
-
-    public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes);
-
-    public void close();
-
-    public static final DistracterFilter EMPTY_DISTRACTER_FILTER = new DistracterFilter() {
-        @Override
-        public boolean isDistracterToWordsInDictionaries(PrevWordsInfo prevWordsInfo,
-                String testedWord, Locale locale) {
-            return false;
-        }
-
-        @Override
-        public void close() {
-        }
-
-        @Override
-        public void updateEnabledSubtypes(List<InputMethodSubtype> enabledSubtypes) {
-        }
-    };
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
deleted file mode 100644
index 2797328..0000000
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingExactMatchesAndSuggestions.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.text.InputType;
-import android.util.Log;
-import android.util.LruCache;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.KeyboardLayoutSet;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.WordComposer;
-import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
-
-/**
- * This class is used to prevent distracters being added to personalization
- * or user history dictionaries
- */
-public class DistracterFilterCheckingExactMatchesAndSuggestions implements DistracterFilter {
-    private static final String TAG =
-            DistracterFilterCheckingExactMatchesAndSuggestions.class.getSimpleName();
-    private static final boolean DEBUG = false;
-
-    private static final long TIMEOUT_TO_WAIT_LOADING_DICTIONARIES_IN_SECONDS = 120;
-    private static final int MAX_DISTRACTERS_CACHE_SIZE = 512;
-
-    private final Context mContext;
-    private final Map<Locale, InputMethodSubtype> mLocaleToSubtypeMap;
-    private final Map<Locale, Keyboard> mLocaleToKeyboardMap;
-    private final DictionaryFacilitator mDictionaryFacilitator;
-    private final LruCache<String, Boolean> mDistractersCache;
-    private Keyboard mKeyboard;
-    private final Object mLock = new Object();
-
-    // If the score of the top suggestion exceeds this value, the tested word (e.g.,
-    // an OOV, a misspelling, or an in-vocabulary word) would be considered as a distractor to
-    // words in dictionary. The greater the threshold is, the less likely the tested word would
-    // become a distractor, which means the tested word will be more likely to be added to
-    // the dictionary.
-    private static final float DISTRACTER_WORD_SCORE_THRESHOLD = 0.4f;
-
-    /**
-     * Create a DistracterFilter instance.
-     *
-     * @param context the context.
-     */
-    public DistracterFilterCheckingExactMatchesAndSuggestions(final Context context) {
-        mContext = context;
-        mLocaleToSubtypeMap = new HashMap<>();
-        mLocaleToKeyboardMap = new HashMap<>();
-        mDictionaryFacilitator = new DictionaryFacilitator();
-        mDistractersCache = new LruCache<>(MAX_DISTRACTERS_CACHE_SIZE);
-        mKeyboard = null;
-    }
-
-    @Override
-    public void close() {
-        mDictionaryFacilitator.closeDictionaries();
-    }
-
-    @Override
-    public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
-        final Map<Locale, InputMethodSubtype> newLocaleToSubtypeMap = new HashMap<>();
-        if (enabledSubtypes != null) {
-            for (final InputMethodSubtype subtype : enabledSubtypes) {
-                final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
-                if (newLocaleToSubtypeMap.containsKey(locale)) {
-                    // Multiple subtypes are enabled for one locale.
-                    // TODO: Investigate what we should do for this case.
-                    continue;
-                }
-                newLocaleToSubtypeMap.put(locale, subtype);
-            }
-        }
-        if (mLocaleToSubtypeMap.equals(newLocaleToSubtypeMap)) {
-            // Enabled subtypes have not been changed.
-            return;
-        }
-        synchronized (mLock) {
-            mLocaleToSubtypeMap.clear();
-            mLocaleToSubtypeMap.putAll(newLocaleToSubtypeMap);
-            mLocaleToKeyboardMap.clear();
-        }
-    }
-
-    private void loadKeyboardForLocale(final Locale newLocale) {
-        final Keyboard cachedKeyboard = mLocaleToKeyboardMap.get(newLocale);
-        if (cachedKeyboard != null) {
-            mKeyboard = cachedKeyboard;
-            return;
-        }
-        final InputMethodSubtype subtype;
-        synchronized (mLock) {
-            subtype = mLocaleToSubtypeMap.get(newLocale);
-        }
-        if (subtype == null) {
-            return;
-        }
-        final EditorInfo editorInfo = new EditorInfo();
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT;
-        final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
-                mContext, editorInfo);
-        final Resources res = mContext.getResources();
-        final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
-        final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
-        builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
-        builder.setSubtype(subtype);
-        builder.setIsSpellChecker(false /* isSpellChecker */);
-        final KeyboardLayoutSet layoutSet = builder.build();
-        mKeyboard = layoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
-    }
-
-    private void loadDictionariesForLocale(final Locale newlocale) throws InterruptedException {
-        mDictionaryFacilitator.resetDictionaries(mContext, newlocale,
-                false /* useContactsDict */, false /* usePersonalizedDicts */,
-                false /* forceReloadMainDictionary */, null /* listener */);
-        mDictionaryFacilitator.waitForLoadingMainDictionary(
-                TIMEOUT_TO_WAIT_LOADING_DICTIONARIES_IN_SECONDS, TimeUnit.SECONDS);
-    }
-
-    /**
-     * Determine whether a word is a distracter to words in dictionaries.
-     *
-     * @param prevWordsInfo the information of previous words. Not used for now.
-     * @param testedWord the word that will be tested to see whether it is a distracter to words
-     *                   in dictionaries.
-     * @param locale the locale of word.
-     * @return true if testedWord is a distracter, otherwise false.
-     */
-    @Override
-    public boolean isDistracterToWordsInDictionaries(final PrevWordsInfo prevWordsInfo,
-            final String testedWord, final Locale locale) {
-        if (locale == null) {
-            return false;
-        }
-        if (!locale.equals(mDictionaryFacilitator.getLocale())) {
-            synchronized (mLock) {
-                if (!mLocaleToSubtypeMap.containsKey(locale)) {
-                    Log.e(TAG, "Locale " + locale + " is not enabled.");
-                    // TODO: Investigate what we should do for disabled locales.
-                    return false;
-                }
-                loadKeyboardForLocale(locale);
-                // Reset dictionaries for the locale.
-                try {
-                    mDistractersCache.evictAll();
-                    loadDictionariesForLocale(locale);
-                } catch (final InterruptedException e) {
-                    Log.e(TAG, "Interrupted while waiting for loading dicts in DistracterFilter",
-                            e);
-                    return false;
-                }
-            }
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "testedWord: " + testedWord);
-        }
-        final Boolean isCachedDistracter = mDistractersCache.get(testedWord);
-        if (isCachedDistracter != null && isCachedDistracter) {
-            if (DEBUG) {
-                Log.d(TAG, "isDistracter: true (cache hit)");
-            }
-            return true;
-        }
-
-        final boolean isDistracterCheckedByGetMaxFreqencyOfExactMatches =
-                checkDistracterUsingMaxFreqencyOfExactMatches(testedWord);
-        if (isDistracterCheckedByGetMaxFreqencyOfExactMatches) {
-            // Add the word to the cache.
-            mDistractersCache.put(testedWord, Boolean.TRUE);
-            return true;
-        }
-        final boolean isValidWord = mDictionaryFacilitator.isValidWord(testedWord,
-                false /* ignoreCase */);
-        if (isValidWord) {
-            // Valid word is not a distractor.
-            if (DEBUG) {
-                Log.d(TAG, "isDistracter: false (valid word)");
-            }
-            return false;
-        }
-
-        final boolean isDistracterCheckedByGetSuggestion =
-                checkDistracterUsingGetSuggestions(testedWord);
-        if (isDistracterCheckedByGetSuggestion) {
-            // Add the word to the cache.
-            mDistractersCache.put(testedWord, Boolean.TRUE);
-            return true;
-        }
-        return false;
-    }
-
-    private boolean checkDistracterUsingMaxFreqencyOfExactMatches(final String testedWord) {
-        // The tested word is a distracter when there is a word that is exact matched to the tested
-        // word and its probability is higher than the tested word's probability.
-        final int perfectMatchFreq = mDictionaryFacilitator.getFrequency(testedWord);
-        final int exactMatchFreq = mDictionaryFacilitator.getMaxFrequencyOfExactMatches(testedWord);
-        final boolean isDistracter = perfectMatchFreq < exactMatchFreq;
-        if (DEBUG) {
-            Log.d(TAG, "perfectMatchFreq: " + perfectMatchFreq);
-            Log.d(TAG, "exactMatchFreq: " + exactMatchFreq);
-            Log.d(TAG, "isDistracter: " + isDistracter);
-        }
-        return isDistracter;
-    }
-
-    private boolean checkDistracterUsingGetSuggestions(final String testedWord) {
-        if (mKeyboard == null) {
-            return false;
-        }
-        final SettingsValuesForSuggestion settingsValuesForSuggestion =
-                new SettingsValuesForSuggestion(false /* blockPotentiallyOffensive */,
-                        false /* spaceAwareGestureEnabled */,
-                        null /* additionalFeaturesSettingValues */);
-        final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(testedWord);
-        final String consideredWord = trailingSingleQuotesCount > 0 ?
-                testedWord.substring(0, testedWord.length() - trailingSingleQuotesCount) :
-                testedWord;
-        final WordComposer composer = new WordComposer();
-        final int[] codePoints = StringUtils.toCodePointArray(testedWord);
-
-        synchronized (mLock) {
-            final int[] coordinates = mKeyboard.getCoordinates(codePoints);
-            composer.setComposingWord(codePoints, coordinates);
-            final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
-                    composer, PrevWordsInfo.EMPTY_PREV_WORDS_INFO, mKeyboard.getProximityInfo(),
-                    settingsValuesForSuggestion, 0 /* sessionId */);
-            if (suggestionResults.isEmpty()) {
-                return false;
-            }
-            final SuggestedWordInfo firstSuggestion = suggestionResults.first();
-            final boolean isDistractor = suggestionExceedsDistracterThreshold(
-                    firstSuggestion, consideredWord, DISTRACTER_WORD_SCORE_THRESHOLD);
-            if (DEBUG) {
-                Log.d(TAG, "isDistracter: " + isDistractor);
-            }
-            return isDistractor;
-        }
-    }
-
-    private static boolean suggestionExceedsDistracterThreshold(final SuggestedWordInfo suggestion,
-            final String consideredWord, final float distracterThreshold) {
-        if (suggestion == null) {
-            return false;
-        }
-        final int suggestionScore = suggestion.mScore;
-        final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
-                consideredWord, suggestion.mWord, suggestionScore);
-        if (DEBUG) {
-            Log.d(TAG, "normalizedScore: " + normalizedScore);
-            Log.d(TAG, "distracterThreshold: " + distracterThreshold);
-        }
-        if (normalizedScore > distracterThreshold) {
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java
deleted file mode 100644
index 4ad4ba7..0000000
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterCheckingIsInDictionary.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import java.util.List;
-import java.util.Locale;
-
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-
-public class DistracterFilterCheckingIsInDictionary implements DistracterFilter {
-    private final DistracterFilter mDistracterFilter;
-    private final Dictionary mDictionary;
-
-    public DistracterFilterCheckingIsInDictionary(final DistracterFilter distracterFilter,
-            final Dictionary dictionary) {
-        mDistracterFilter = distracterFilter;
-        mDictionary = dictionary;
-    }
-
-    @Override
-    public boolean isDistracterToWordsInDictionaries(PrevWordsInfo prevWordsInfo,
-            String testedWord, Locale locale) {
-        if (mDictionary.isInDictionary(testedWord)) {
-            // This filter treats entries that are already in the dictionary as non-distracters
-            // because they have passed the filtering in the past.
-            return false;
-        } else {
-            return mDistracterFilter.isDistracterToWordsInDictionaries(
-                    prevWordsInfo, testedWord, locale);
-        }
-    }
-
-    @Override
-    public void updateEnabledSubtypes(List<InputMethodSubtype> enabledSubtypes) {
-        // Do nothing.
-    }
-
-    @Override
-    public void close() {
-        // Do nothing.
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
index 61da1b7..8ce6eff 100644
--- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java
@@ -16,64 +16,136 @@
 
 package com.android.inputmethod.latin.utils;
 
+import android.util.Log;
+
 import com.android.inputmethod.annotations.UsedForTesting;
 
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
+import java.lang.Thread.UncaughtExceptionHandler;
 import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Utilities to manage executors.
  */
 public class ExecutorUtils {
-    private static final ConcurrentHashMap<String, ExecutorService> sExecutorMap =
-            new ConcurrentHashMap<>();
 
-    private static class ThreadFactoryWithId implements ThreadFactory {
-        private final String mId;
+    private static final String TAG = "ExecutorUtils";
 
-        public ThreadFactoryWithId(final String id) {
-            mId = id;
+    public static final String KEYBOARD = "Keyboard";
+    public static final String SPELLING = "Spelling";
+
+    private static ScheduledExecutorService sKeyboardExecutorService = newExecutorService(KEYBOARD);
+    private static ScheduledExecutorService sSpellingExecutorService = newExecutorService(SPELLING);
+
+    private static ScheduledExecutorService newExecutorService(final String name) {
+        return Executors.newSingleThreadScheduledExecutor(new ExecutorFactory(name));
+    }
+
+    private static class ExecutorFactory implements ThreadFactory {
+        private final String mName;
+
+        private ExecutorFactory(final String name) {
+            mName = name;
         }
 
         @Override
-        public Thread newThread(final Runnable r) {
-            return new Thread(r, "Executor - " + mId);
-        }
-    }
-
-    /**
-     * Gets the executor for the given id.
-     */
-    public static ExecutorService getExecutor(final String id) {
-        ExecutorService executor = sExecutorMap.get(id);
-        if (executor == null) {
-            synchronized(sExecutorMap) {
-                executor = sExecutorMap.get(id);
-                if (executor == null) {
-                    executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithId(id));
-                    sExecutorMap.put(id, executor);
+        public Thread newThread(final Runnable runnable) {
+            Thread thread = new Thread(runnable, TAG);
+            thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread thread, Throwable ex) {
+                    Log.w(mName + "-" + runnable.getClass().getSimpleName(), ex);
                 }
-            }
+            });
+            return thread;
         }
-        return executor;
     }
 
-    /**
-     * Shutdowns all executors and removes all executors from the executor map for testing.
-     */
     @UsedForTesting
-    public static void shutdownAllExecutors() {
-        synchronized(sExecutorMap) {
-            for (final ExecutorService executor : sExecutorMap.values()) {
-                executor.execute(new Runnable() {
-                    @Override
-                    public void run() {
-                        executor.shutdown();
-                        sExecutorMap.remove(executor);
-                    }
-                });
+    private static ScheduledExecutorService sExecutorServiceForTests;
+
+    @UsedForTesting
+    public static void setExecutorServiceForTests(
+            final ScheduledExecutorService executorServiceForTests) {
+        sExecutorServiceForTests = executorServiceForTests;
+    }
+
+    //
+    // Public methods used to schedule a runnable for execution.
+    //
+
+    /**
+     * @param name Executor's name.
+     * @return scheduled executor service used to run background tasks
+     */
+    public static ScheduledExecutorService getBackgroundExecutor(final String name) {
+        if (sExecutorServiceForTests != null) {
+            return sExecutorServiceForTests;
+        }
+        switch (name) {
+            case KEYBOARD:
+                return sKeyboardExecutorService;
+            case SPELLING:
+                return sSpellingExecutorService;
+            default:
+                throw new IllegalArgumentException("Invalid executor: " + name);
+        }
+    }
+
+    public static void killTasks(final String name) {
+        final ScheduledExecutorService executorService = getBackgroundExecutor(name);
+        executorService.shutdownNow();
+        try {
+            executorService.awaitTermination(5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            Log.wtf(TAG, "Failed to shut down: " + name);
+        }
+        if (executorService == sExecutorServiceForTests) {
+            // Don't do anything to the test service.
+            return;
+        }
+        switch (name) {
+            case KEYBOARD:
+                sKeyboardExecutorService = newExecutorService(KEYBOARD);
+                break;
+            case SPELLING:
+                sSpellingExecutorService = newExecutorService(SPELLING);
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid executor: " + name);
+        }
+    }
+
+    @UsedForTesting
+    public static Runnable chain(final Runnable... runnables) {
+        return new RunnableChain(runnables);
+    }
+
+    @UsedForTesting
+    public static class RunnableChain implements Runnable {
+        private final Runnable[] mRunnables;
+
+        private RunnableChain(final Runnable... runnables) {
+            if (runnables == null || runnables.length == 0) {
+                throw new IllegalArgumentException("Attempting to construct an empty chain");
+            }
+            mRunnables = runnables;
+        }
+
+        @UsedForTesting
+        public Runnable[] getRunnables() {
+            return mRunnables;
+        }
+
+        @Override
+        public void run() {
+            for (Runnable runnable : mRunnables) {
+                if (Thread.interrupted()) {
+                    return;
+                }
+                runnable.run();
             }
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/utils/FileUtils.java b/java/src/com/android/inputmethod/latin/utils/FileUtils.java
deleted file mode 100644
index f1106a6..0000000
--- a/java/src/com/android/inputmethod/latin/utils/FileUtils.java
+++ /dev/null
@@ -1,54 +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.utils;
-
-import java.io.File;
-import java.io.FilenameFilter;
-
-/**
- * A simple class to help with removing directories recursively.
- */
-public class FileUtils {
-    public static boolean deleteRecursively(final File path) {
-        if (path.isDirectory()) {
-            final File[] files = path.listFiles();
-            if (files != null) {
-                for (final File child : files) {
-                    deleteRecursively(child);
-                }
-            }
-        }
-        return path.delete();
-    }
-
-    public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) {
-        if (!dir.isDirectory()) {
-            return false;
-        }
-        final File[] files = dir.listFiles(fileNameFilter);
-        if (files == null) {
-            return false;
-        }
-        boolean hasDeletedAllFiles = true;
-        for (final File file : files) {
-            if (!deleteRecursively(file)) {
-                hasDeletedAllFiles = false;
-            }
-        }
-        return hasDeletedAllFiles;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
index c2167a7..c87a7c0 100644
--- a/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/FragmentUtils.java
@@ -18,18 +18,17 @@
 
 import com.android.inputmethod.dictionarypack.DictionarySettingsFragment;
 import com.android.inputmethod.latin.about.AboutPreferences;
+import com.android.inputmethod.latin.settings.AccountsSettingsFragment;
 import com.android.inputmethod.latin.settings.AdvancedSettingsFragment;
 import com.android.inputmethod.latin.settings.AppearanceSettingsFragment;
 import com.android.inputmethod.latin.settings.CorrectionSettingsFragment;
 import com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment;
 import com.android.inputmethod.latin.settings.DebugSettingsFragment;
 import com.android.inputmethod.latin.settings.GestureSettingsFragment;
-import com.android.inputmethod.latin.settings.MultiLingualSettingsFragment;
 import com.android.inputmethod.latin.settings.PreferencesSettingsFragment;
 import com.android.inputmethod.latin.settings.SettingsFragment;
 import com.android.inputmethod.latin.settings.ThemeSettingsFragment;
 import com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment;
-import com.android.inputmethod.latin.userdictionary.UserDictionaryAddWordFragment;
 import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
 import com.android.inputmethod.latin.userdictionary.UserDictionaryLocalePicker;
 import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
@@ -42,9 +41,9 @@
         sLatinImeFragments.add(DictionarySettingsFragment.class.getName());
         sLatinImeFragments.add(AboutPreferences.class.getName());
         sLatinImeFragments.add(PreferencesSettingsFragment.class.getName());
+        sLatinImeFragments.add(AccountsSettingsFragment.class.getName());
         sLatinImeFragments.add(AppearanceSettingsFragment.class.getName());
         sLatinImeFragments.add(ThemeSettingsFragment.class.getName());
-        sLatinImeFragments.add(MultiLingualSettingsFragment.class.getName());
         sLatinImeFragments.add(CustomInputStyleSettingsFragment.class.getName());
         sLatinImeFragments.add(GestureSettingsFragment.class.getName());
         sLatinImeFragments.add(CorrectionSettingsFragment.class.getName());
@@ -52,7 +51,6 @@
         sLatinImeFragments.add(DebugSettingsFragment.class.getName());
         sLatinImeFragments.add(SettingsFragment.class.getName());
         sLatinImeFragments.add(SpellCheckerSettingsFragment.class.getName());
-        sLatinImeFragments.add(UserDictionaryAddWordFragment.class.getName());
         sLatinImeFragments.add(UserDictionaryList.class.getName());
         sLatinImeFragments.add(UserDictionaryLocalePicker.class.getName());
         sLatinImeFragments.add(UserDictionarySettings.class.getName());
diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
index ea406fa..df0cd84 100644
--- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
@@ -25,6 +25,7 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.settings.SettingsValues;
 
 import java.util.concurrent.TimeUnit;
 
@@ -53,7 +54,8 @@
         // This utility class is not publicly instantiable.
     }
 
-    private static boolean isInSystemSetupWizard(final Context context) {
+    @UsedForTesting
+    static boolean isInSystemSetupWizard(final Context context) {
         try {
             final int userSetupComplete = Settings.Secure.getInt(
                     context.getContentResolver(), Settings_Secure_USER_SETUP_COMPLETE);
@@ -84,7 +86,8 @@
         return getLastImportantNoticeVersion(context) + 1;
     }
 
-    private static boolean hasNewImportantNotice(final Context context) {
+    @UsedForTesting
+    static boolean hasNewImportantNotice(final Context context) {
         final int lastVersion = getLastImportantNoticeVersion(context);
         return getCurrentImportantNoticeVersion(context) > lastVersion;
     }
@@ -103,7 +106,12 @@
         return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE;
     }
 
-    public static boolean shouldShowImportantNotice(final Context context) {
+    public static boolean shouldShowImportantNotice(final Context context,
+            final SettingsValues settingsValues) {
+        // Check to see whether personalization is enabled by the user.
+        if (!settingsValues.isPersonalizationEnabled()) {
+            return false;
+        }
         if (!hasNewImportantNotice(context)) {
             return false;
         }
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
deleted file mode 100644
index fbce3f2..0000000
--- a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import android.util.Log;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-// Note: this class is used as a parameter type of a native method. You should be careful when you
-// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative().
-public final class LanguageModelParam {
-    private static final String TAG = LanguageModelParam.class.getSimpleName();
-    private static final boolean DEBUG = false;
-    private static final boolean DEBUG_TOKEN = false;
-
-    // For now, these probability values are being referred to only when we add new entries to
-    // decaying dynamic binary dictionaries. When these are referred to, what matters is 0 or
-    // non-0. Thus, it's not meaningful to compare 10, 100, and so on.
-    // TODO: Revise the logic in ForgettingCurveUtils in native code.
-    private static final int UNIGRAM_PROBABILITY_FOR_VALID_WORD = 100;
-    private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY;
-    private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 10;
-    private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY;
-
-    public final CharSequence mTargetWord;
-    public final int[] mWord0;
-    public final int[] mWord1;
-    // TODO: this needs to be a list of shortcuts
-    public final int[] mShortcutTarget;
-    public final int mUnigramProbability;
-    public final int mBigramProbability;
-    public final int mShortcutProbability;
-    public final boolean mIsNotAWord;
-    public final boolean mIsBlacklisted;
-    // Time stamp in seconds.
-    public final int mTimestamp;
-
-    // Constructor for unigram. TODO: support shortcuts
-    public LanguageModelParam(final CharSequence word, final int unigramProbability,
-            final int timestamp) {
-        this(null /* word0 */, word, unigramProbability, Dictionary.NOT_A_PROBABILITY, timestamp);
-    }
-
-    // Constructor for unigram and bigram.
-    public LanguageModelParam(final CharSequence word0, final CharSequence word1,
-            final int unigramProbability, final int bigramProbability,
-            final int timestamp) {
-        mTargetWord = word1;
-        mWord0 = (word0 == null) ? null : StringUtils.toCodePointArray(word0);
-        mWord1 = StringUtils.toCodePointArray(word1);
-        mShortcutTarget = null;
-        mUnigramProbability = unigramProbability;
-        mBigramProbability = bigramProbability;
-        mShortcutProbability = Dictionary.NOT_A_PROBABILITY;
-        mIsNotAWord = false;
-        mIsBlacklisted = false;
-        mTimestamp = timestamp;
-    }
-
-    // Process a list of words and return a list of {@link LanguageModelParam} objects.
-    public static ArrayList<LanguageModelParam> createLanguageModelParamsFrom(
-            final List<String> tokens, final int timestamp,
-            final DictionaryFacilitator dictionaryFacilitator,
-            final SpacingAndPunctuations spacingAndPunctuations,
-            final DistracterFilter distracterFilter) {
-        final ArrayList<LanguageModelParam> languageModelParams = new ArrayList<>();
-        final int N = tokens.size();
-        PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-        for (int i = 0; i < N; ++i) {
-            final String tempWord = tokens.get(i);
-            if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) {
-                // just skip this token
-                if (DEBUG_TOKEN) {
-                    Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\"");
-                }
-                continue;
-            }
-            if (!DictionaryInfoUtils.looksValidForDictionaryInsertion(
-                    tempWord, spacingAndPunctuations)) {
-                if (DEBUG_TOKEN) {
-                    Log.d(TAG, "--- not looksValidForDictionaryInsertion: \""
-                            + tempWord + "\"");
-                }
-                // Sentence terminator found. Split.
-                prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-                continue;
-            }
-            if (DEBUG_TOKEN) {
-                Log.d(TAG, "--- word: \"" + tempWord + "\"");
-            }
-            final LanguageModelParam languageModelParam =
-                    detectWhetherVaildWordOrNotAndGetLanguageModelParam(
-                            prevWordsInfo, tempWord, timestamp, dictionaryFacilitator,
-                            distracterFilter);
-            if (languageModelParam == null) {
-                continue;
-            }
-            languageModelParams.add(languageModelParam);
-            prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(
-                    new PrevWordsInfo.WordInfo(tempWord));
-        }
-        return languageModelParams;
-    }
-
-    private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam(
-            final PrevWordsInfo prevWordsInfo, final String targetWord, final int timestamp,
-            final DictionaryFacilitator dictionaryFacilitator,
-            final DistracterFilter distracterFilter) {
-        final Locale locale = dictionaryFacilitator.getLocale();
-        if (locale == null) {
-            return null;
-        }
-        if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) {
-            return createAndGetLanguageModelParamOfWord(prevWordsInfo, targetWord, timestamp,
-                    true /* isValidWord */, locale, distracterFilter);
-        }
-
-        final String lowerCaseTargetWord = targetWord.toLowerCase(locale);
-        if (dictionaryFacilitator.isValidWord(lowerCaseTargetWord, false /* ignoreCase */)) {
-            // Add the lower-cased word.
-            return createAndGetLanguageModelParamOfWord(prevWordsInfo, lowerCaseTargetWord,
-                    timestamp, true /* isValidWord */, locale, distracterFilter);
-        }
-
-        // Treat the word as an OOV word.
-        return createAndGetLanguageModelParamOfWord(prevWordsInfo, targetWord, timestamp,
-                false /* isValidWord */, locale, distracterFilter);
-    }
-
-    private static LanguageModelParam createAndGetLanguageModelParamOfWord(
-            final PrevWordsInfo prevWordsInfo, final String targetWord, final int timestamp,
-            final boolean isValidWord, final Locale locale,
-            final DistracterFilter distracterFilter) {
-        final String word;
-        if (StringUtils.getCapitalizationType(targetWord) == StringUtils.CAPITALIZE_FIRST
-                && !prevWordsInfo.isValid() && !isValidWord) {
-            word = targetWord.toLowerCase(locale);
-        } else {
-            word = targetWord;
-        }
-        // Check whether the word is a distracter to words in the dictionaries.
-        if (distracterFilter.isDistracterToWordsInDictionaries(prevWordsInfo, word, locale)) {
-            if (DEBUG) {
-                Log.d(TAG, "The word (" + word + ") is a distracter. Skip this word.");
-            }
-            return null;
-        }
-        final int unigramProbability = isValidWord ?
-                UNIGRAM_PROBABILITY_FOR_VALID_WORD : UNIGRAM_PROBABILITY_FOR_OOV_WORD;
-        if (!prevWordsInfo.isValid()) {
-            if (DEBUG) {
-                Log.d(TAG, "--- add unigram: current("
-                        + (isValidWord ? "Valid" : "OOV") + ") = " + word);
-            }
-            return new LanguageModelParam(word, unigramProbability, timestamp);
-        }
-        if (DEBUG) {
-            Log.d(TAG, "--- add bigram: prev = " + prevWordsInfo + ", current("
-                    + (isValidWord ? "Valid" : "OOV") + ") = " + word);
-        }
-        final int bigramProbability = isValidWord ?
-                BIGRAM_PROBABILITY_FOR_VALID_WORD : BIGRAM_PROBABILITY_FOR_OOV_WORD;
-        return new LanguageModelParam(prevWordsInfo.mPrevWordsInfo[0].mWord, word,
-                unigramProbability, bigramProbability, timestamp);
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtils.java b/java/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtils.java
new file mode 100644
index 0000000..a5a1ea9
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtils.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+
+/**
+ * This class determines that the language name on the spacebar should be displayed in what format.
+ */
+public final class LanguageOnSpacebarUtils {
+    public static final int FORMAT_TYPE_NONE = 0;
+    public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1;
+    public static final int FORMAT_TYPE_FULL_LOCALE = 2;
+
+    private static List<InputMethodSubtype> sEnabledSubtypes = Collections.emptyList();
+    private static boolean sIsSystemLanguageSameAsInputLanguage;
+
+    private LanguageOnSpacebarUtils() {
+        // This utility class is not publicly instantiable.
+    }
+
+    public static int getLanguageOnSpacebarFormatType(
+            @Nonnull final RichInputMethodSubtype subtype) {
+        if (subtype.isNoLanguage()) {
+            return FORMAT_TYPE_FULL_LOCALE;
+        }
+        // Only this subtype is enabled and equals to the system locale.
+        if (sEnabledSubtypes.size() < 2 && sIsSystemLanguageSameAsInputLanguage) {
+            return FORMAT_TYPE_NONE;
+        }
+        final Locale locale = subtype.getLocale();
+        if (locale == null) {
+            return FORMAT_TYPE_NONE;
+        }
+        final String keyboardLanguage = locale.getLanguage();
+        final String keyboardLayout = subtype.getKeyboardLayoutSetName();
+        int sameLanguageAndLayoutCount = 0;
+        for (final InputMethodSubtype ims : sEnabledSubtypes) {
+            final String language = SubtypeLocaleUtils.getSubtypeLocale(ims).getLanguage();
+            if (keyboardLanguage.equals(language) && keyboardLayout.equals(
+                    SubtypeLocaleUtils.getKeyboardLayoutSetName(ims))) {
+                sameLanguageAndLayoutCount++;
+            }
+        }
+        // Display full locale name only when there are multiple subtypes that have the same
+        // locale and keyboard layout. Otherwise displaying language name is enough.
+        return sameLanguageAndLayoutCount > 1 ? FORMAT_TYPE_FULL_LOCALE
+                : FORMAT_TYPE_LANGUAGE_ONLY;
+    }
+
+    public static void setEnabledSubtypes(@Nonnull final List<InputMethodSubtype> enabledSubtypes) {
+        sEnabledSubtypes = enabledSubtypes;
+    }
+
+    public static void onSubtypeChanged(@Nonnull final RichInputMethodSubtype subtype,
+           final boolean implicitlyEnabledSubtype, @Nonnull final Locale systemLocale) {
+        final Locale newLocale = subtype.getLocale();
+        if (systemLocale.equals(newLocale)) {
+            sIsSystemLanguageSameAsInputLanguage = true;
+            return;
+        }
+        if (!systemLocale.getLanguage().equals(newLocale.getLanguage())) {
+            sIsSystemLanguageSameAsInputLanguage = false;
+            return;
+        }
+        // If the subtype is enabled explicitly, the language name should be displayed even when
+        // the keyboard language and the system language are equal.
+        sIsSystemLanguageSameAsInputLanguage = implicitlyEnabledSubtype;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java b/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
index dd6fac6..9a5be99 100644
--- a/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
+++ b/java/src/com/android/inputmethod/latin/utils/LeakGuardHandlerWrapper.java
@@ -21,21 +21,22 @@
 
 import java.lang.ref.WeakReference;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 public class LeakGuardHandlerWrapper<T> extends Handler {
     private final WeakReference<T> mOwnerInstanceRef;
 
-    public LeakGuardHandlerWrapper(final T ownerInstance) {
+    public LeakGuardHandlerWrapper(@Nonnull final T ownerInstance) {
         this(ownerInstance, Looper.myLooper());
     }
 
-    public LeakGuardHandlerWrapper(final T ownerInstance, final Looper looper) {
+    public LeakGuardHandlerWrapper(@Nonnull final T ownerInstance, final Looper looper) {
         super(looper);
-        if (ownerInstance == null) {
-            throw new NullPointerException("ownerInstance is null");
-        }
         mOwnerInstanceRef = new WeakReference<>(ownerInstance);
     }
 
+    @Nullable
     public T getOwnerInstance() {
         return mOwnerInstanceRef.get();
     }
diff --git a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
deleted file mode 100644
index c519a0d..0000000
--- a/java/src/com/android/inputmethod/latin/utils/LocaleUtils.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2011 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.utils;
-
-import android.text.TextUtils;
-
-import java.util.HashMap;
-import java.util.Locale;
-
-/**
- * A class to help with handling Locales in string form.
- *
- * This file has the same meaning and features (and shares all of its code) with
- * the one in the dictionary pack. They need to be kept synchronized; for any
- * update/bugfix to this file, consider also updating/fixing the version in the
- * dictionary pack.
- */
-public final class LocaleUtils {
-    private LocaleUtils() {
-        // Intentional empty constructor for utility class.
-    }
-
-    // Locale match level constants.
-    // A higher level of match is guaranteed to have a higher numerical value.
-    // Some room is left within constants to add match cases that may arise necessary
-    // in the future, for example differentiating between the case where the countries
-    // are both present and different, and the case where one of the locales does not
-    // specify the countries. This difference is not needed now.
-
-    // Nothing matches.
-    public static final int LOCALE_NO_MATCH = 0;
-    // The languages matches, but the country are different. Or, the reference locale requires a
-    // country and the tested locale does not have one.
-    public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
-    // The languages and country match, but the variants are different. Or, the reference locale
-    // requires a variant and the tested locale does not have one.
-    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
-    // The required locale is null or empty so it will accept anything, and the tested locale
-    // is non-null and non-empty.
-    public static final int LOCALE_ANY_MATCH = 10;
-    // The language matches, and the tested locale specifies a country but the reference locale
-    // does not require one.
-    public static final int LOCALE_LANGUAGE_MATCH = 15;
-    // The language and the country match, and the tested locale specifies a variant but the
-    // reference locale does not require one.
-    public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
-    // The compared locales are fully identical. This is the best match level.
-    public static final int LOCALE_FULL_MATCH = 30;
-
-    // The level at which a match is "normally" considered a locale match with standard algorithms.
-    // Don't use this directly, use #isMatch to test.
-    private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
-
-    // Make this match the maximum match level. If this evolves to have more than 2 digits
-    // when written in base 10, also adjust the getMatchLevelSortedString method.
-    private static final int MATCH_LEVEL_MAX = 30;
-
-    /**
-     * Return how well a tested locale matches a reference locale.
-     *
-     * This will check the tested locale against the reference locale and return a measure of how
-     * a well it matches the reference. The general idea is that the tested locale has to match
-     * every specified part of the required locale. A full match occur when they are equal, a
-     * partial match when the tested locale agrees with the reference locale but is more specific,
-     * and a difference when the tested locale does not comply with all requirements from the
-     * reference locale.
-     * In more detail, if the reference locale specifies at least a language and the testedLocale
-     * does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
-     * reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
-     * if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
-     * tested locale agree on the language, but not on the country,
-     * LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
-     * and LOCALE_LANGUAGE_MATCH otherwise.
-     * If they agree on both the language and the country, but not on the variant,
-     * LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
-     * specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
-     * LOCALE_FULL_MATCH is returned.
-     * Examples:
-     * en <=> en_US  => LOCALE_LANGUAGE_MATCH
-     * en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
-     * en_US_POSIX <=> en_US_Android  =>  LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
-     * en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
-     * sp_US <=> en_US  =>  LOCALE_NO_MATCH
-     * de <=> de  => LOCALE_FULL_MATCH
-     * en_US <=> en_US => LOCALE_FULL_MATCH
-     * "" <=> en_US => LOCALE_ANY_MATCH
-     *
-     * @param referenceLocale the reference locale to test against.
-     * @param testedLocale the locale to test.
-     * @return a constant that measures how well the tested locale matches the reference locale.
-     */
-    public static int getMatchLevel(String referenceLocale, String testedLocale) {
-        if (TextUtils.isEmpty(referenceLocale)) {
-            return TextUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
-        }
-        if (null == testedLocale) return LOCALE_NO_MATCH;
-        String[] referenceParams = referenceLocale.split("_", 3);
-        String[] testedParams = testedLocale.split("_", 3);
-        // By spec of String#split, [0] cannot be null and length cannot be 0.
-        if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
-        switch (referenceParams.length) {
-        case 1:
-            return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
-        case 2:
-            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (!referenceParams[1].equals(testedParams[1]))
-                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
-            return LOCALE_FULL_MATCH;
-        case 3:
-            if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (!referenceParams[1].equals(testedParams[1]))
-                return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
-            if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
-            if (!referenceParams[2].equals(testedParams[2]))
-                return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
-            return LOCALE_FULL_MATCH;
-        }
-        // It should be impossible to come here
-        return LOCALE_NO_MATCH;
-    }
-
-    /**
-     * Return a string that represents this match level, with better matches first.
-     *
-     * The strings are sorted in lexicographic order: a better match will always be less than
-     * a worse match when compared together.
-     */
-    public static String getMatchLevelSortedString(int matchLevel) {
-        // This works because the match levels are 0~99 (actually 0~30)
-        // Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
-        return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
-    }
-
-    /**
-     * Find out whether a match level should be considered a match.
-     *
-     * This method takes a match level as returned by the #getMatchLevel method, and returns whether
-     * it should be considered a match in the usual sense with standard Locale functions.
-     *
-     * @param level the match level, as returned by getMatchLevel.
-     * @return whether this is a match or not.
-     */
-    public static boolean isMatch(int level) {
-        return LOCALE_MATCH <= level;
-    }
-
-    private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
-
-    /**
-     * 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/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
new file mode 100644
index 0000000..c05ffd6
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/NgramContextUtils.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+
+public final class NgramContextUtils {
+    private NgramContextUtils() {
+        // Intentional empty constructor for utility class.
+    }
+
+    private static final Pattern NEWLINE_REGEX = Pattern.compile("[\\r\\n]+");
+    private static final Pattern SPACE_REGEX = Pattern.compile("\\s+");
+    // Get context information from nth word before the cursor. n = 1 retrieves the words
+    // immediately before the cursor, n = 2 retrieves the words before that, and so on. This splits
+    // on whitespace only.
+    // Also, it won't return words that end in a separator (if the nth word before the cursor
+    // ends in a separator, it returns information representing beginning-of-sentence).
+    // Example (when Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM is 2):
+    // (n = 1) "abc def|" -> abc, def
+    // (n = 1) "abc def |" -> abc, def
+    // (n = 1) "abc 'def|" -> empty, 'def
+    // (n = 1) "abc def. |" -> beginning-of-sentence
+    // (n = 1) "abc def . |" -> beginning-of-sentence
+    // (n = 2) "abc def|" -> beginning-of-sentence, abc
+    // (n = 2) "abc def |" -> beginning-of-sentence, abc
+    // (n = 2) "abc 'def|" -> empty. The context is different from "abc def", but we cannot
+    // represent this situation using NgramContext. See TODO in the method.
+    // TODO: The next example's result should be "abc, def". This have to be fixed before we
+    // retrieve the prior context of Beginning-of-Sentence.
+    // (n = 2) "abc def. |" -> beginning-of-sentence, abc
+    // (n = 2) "abc def . |" -> abc, def
+    // (n = 2) "abc|" -> beginning-of-sentence
+    // (n = 2) "abc |" -> beginning-of-sentence
+    // (n = 2) "abc. def|" -> beginning-of-sentence
+    @Nonnull
+    public static NgramContext getNgramContextFromNthPreviousWord(final CharSequence prev,
+            final SpacingAndPunctuations spacingAndPunctuations, final int n) {
+        if (prev == null) return NgramContext.EMPTY_PREV_WORDS_INFO;
+        final String[] lines = NEWLINE_REGEX.split(prev);
+        if (lines.length == 0) {
+            return new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        }
+        final String[] w = SPACE_REGEX.split(lines[lines.length - 1]);
+        final WordInfo[] prevWordsInfo =
+                new WordInfo[DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+        Arrays.fill(prevWordsInfo, WordInfo.EMPTY_WORD_INFO);
+        for (int i = 0; i < prevWordsInfo.length; i++) {
+            final int focusedWordIndex = w.length - n - i;
+            // Referring to the word after the focused word.
+            if ((focusedWordIndex + 1) >= 0 && (focusedWordIndex + 1) < w.length) {
+                final String wordFollowingTheNthPrevWord = w[focusedWordIndex + 1];
+                if (!wordFollowingTheNthPrevWord.isEmpty()) {
+                    final char firstChar = wordFollowingTheNthPrevWord.charAt(0);
+                    if (spacingAndPunctuations.isWordConnector(firstChar)) {
+                        // The word following the focused word is starting with a word connector.
+                        // TODO: Return meaningful context for this case.
+                        break;
+                    }
+                }
+            }
+            // If we can't find (n + i) words, the context is beginning-of-sentence.
+            if (focusedWordIndex < 0) {
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
+                break;
+            }
+
+            final String focusedWord = w[focusedWordIndex];
+            // If the word is empty, the context is beginning-of-sentence.
+            final int length = focusedWord.length();
+            if (length <= 0) {
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
+                break;
+            }
+            // If the word ends in a sentence terminator, the context is beginning-of-sentence.
+            final char lastChar = focusedWord.charAt(length - 1);
+            if (spacingAndPunctuations.isSentenceTerminator(lastChar)) {
+                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO;
+                break;
+            }
+            // If ends in a word separator or connector, the context is unclear.
+            // TODO: Return meaningful context for this case.
+            if (spacingAndPunctuations.isWordSeparator(lastChar)
+                    || spacingAndPunctuations.isWordConnector(lastChar)) {
+                break;
+            }
+            prevWordsInfo[i] = new WordInfo(focusedWord);
+        }
+        return new NgramContext(prevWordsInfo);
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/PrevWordsInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/PrevWordsInfoUtils.java
deleted file mode 100644
index 3cd6361..0000000
--- a/java/src/com/android/inputmethod/latin/utils/PrevWordsInfoUtils.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import java.util.regex.Pattern;
-
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-
-public final class PrevWordsInfoUtils {
-    private PrevWordsInfoUtils() {
-        // Intentional empty constructor for utility class.
-    }
-
-    private static final Pattern SPACE_REGEX = Pattern.compile("\\s+");
-    // Get context information from nth word before the cursor. n = 1 retrieves the words
-    // immediately before the cursor, n = 2 retrieves the words before that, and so on. This splits
-    // on whitespace only.
-    // Also, it won't return words that end in a separator (if the nth word before the cursor
-    // ends in a separator, it returns information representing beginning-of-sentence).
-    // Example (when Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM is 2):
-    // (n = 1) "abc def|" -> abc, def
-    // (n = 1) "abc def |" -> abc, def
-    // (n = 1) "abc 'def|" -> empty, 'def
-    // (n = 1) "abc def. |" -> beginning-of-sentence
-    // (n = 1) "abc def . |" -> beginning-of-sentence
-    // (n = 2) "abc def|" -> beginning-of-sentence, abc
-    // (n = 2) "abc def |" -> beginning-of-sentence, abc
-    // (n = 2) "abc 'def|" -> empty. The context is different from "abc def", but we cannot
-    // represent this situation using PrevWordsInfo. See TODO in the method.
-    // TODO: The next example's result should be "abc, def". This have to be fixed before we
-    // retrieve the prior context of Beginning-of-Sentence.
-    // (n = 2) "abc def. |" -> beginning-of-sentence, abc
-    // (n = 2) "abc def . |" -> abc, def
-    // (n = 2) "abc|" -> beginning-of-sentence
-    // (n = 2) "abc |" -> beginning-of-sentence
-    // (n = 2) "abc. def|" -> beginning-of-sentence
-    public static PrevWordsInfo getPrevWordsInfoFromNthPreviousWord(final CharSequence prev,
-            final SpacingAndPunctuations spacingAndPunctuations, final int n) {
-        if (prev == null) return PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-        final String[] w = SPACE_REGEX.split(prev);
-        final WordInfo[] prevWordsInfo = new WordInfo[Constants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        for (int i = 0; i < prevWordsInfo.length; i++) {
-            final int focusedWordIndex = w.length - n - i;
-            // Referring to the word after the focused word.
-            if ((focusedWordIndex + 1) >= 0 && (focusedWordIndex + 1) < w.length) {
-                final String wordFollowingTheNthPrevWord = w[focusedWordIndex + 1];
-                if (!wordFollowingTheNthPrevWord.isEmpty()) {
-                    final char firstChar = wordFollowingTheNthPrevWord.charAt(0);
-                    if (spacingAndPunctuations.isWordConnector(firstChar)) {
-                        // The word following the focused word is starting with a word connector.
-                        // TODO: Return meaningful context for this case.
-                        prevWordsInfo[i] = WordInfo.EMPTY_WORD_INFO;
-                        break;
-                    }
-                }
-            }
-            // If we can't find (n + i) words, the context is beginning-of-sentence.
-            if (focusedWordIndex < 0) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
-                break;
-            }
-            final String focusedWord = w[focusedWordIndex];
-            // If the word is, the context is beginning-of-sentence.
-            final int length = focusedWord.length();
-            if (length <= 0) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
-                break;
-            }
-            // If ends in a sentence separator, the context is beginning-of-sentence.
-            final char lastChar = focusedWord.charAt(length - 1);
-            if (spacingAndPunctuations.isSentenceSeparator(lastChar)) {
-                prevWordsInfo[i] = WordInfo.BEGINNING_OF_SENTENCE;
-                break;
-            }
-            // If ends in a word separator or connector, the context is unclear.
-            // TODO: Return meaningful context for this case.
-            if (spacingAndPunctuations.isWordSeparator(lastChar)
-                    || spacingAndPunctuations.isWordConnector(lastChar)) {
-                prevWordsInfo[i] = WordInfo.EMPTY_WORD_INFO;
-                break;
-            }
-            prevWordsInfo[i] = new WordInfo(focusedWord);
-        }
-        return new PrevWordsInfo(prevWordsInfo);
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
index e3cac97..a381649 100644
--- a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
+++ b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
@@ -16,6 +16,8 @@
 
 package com.android.inputmethod.latin.utils;
 
+import com.android.inputmethod.latin.common.StringUtils;
+
 import java.util.Locale;
 
 /**
@@ -49,6 +51,17 @@
         }
     }
 
+    public static String modeToString(final int recapitalizeMode) {
+        switch (recapitalizeMode) {
+        case NOT_A_RECAPITALIZE_MODE: return "undefined";
+        case CAPS_MODE_ORIGINAL_MIXED_CASE: return "mixedCase";
+        case CAPS_MODE_ALL_LOWER: return "allLower";
+        case CAPS_MODE_FIRST_WORD_UPPER: return "firstWordUpper";
+        case CAPS_MODE_ALL_UPPER: return "allUpper";
+        default: return "unknown<" + recapitalizeMode + ">";
+        }
+    }
+
     /**
      * We store the location of the cursor and the string that was there before the recapitalize
      * action was done, and the location of the cursor and the string that was there after.
diff --git a/java/src/com/android/inputmethod/latin/utils/ResizableIntArray.java b/java/src/com/android/inputmethod/latin/utils/ResizableIntArray.java
deleted file mode 100644
index 64c9e2c..0000000
--- a/java/src/com/android/inputmethod/latin/utils/ResizableIntArray.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import java.util.Arrays;
-
-// TODO: This class is not thread-safe.
-public final class ResizableIntArray {
-    private int[] mArray;
-    private int mLength;
-
-    public ResizableIntArray(final int capacity) {
-        reset(capacity);
-    }
-
-    public int get(final int index) {
-        if (index < mLength) {
-            return mArray[index];
-        }
-        throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
-    }
-
-    public void addAt(final int index, final int val) {
-        if (index < mLength) {
-            mArray[index] = val;
-        } else {
-            mLength = index;
-            add(val);
-        }
-    }
-
-    public void add(final int val) {
-        final int currentLength = mLength;
-        ensureCapacity(currentLength + 1);
-        mArray[currentLength] = val;
-        mLength = currentLength + 1;
-    }
-
-    /**
-     * Calculate the new capacity of {@code mArray}.
-     * @param minimumCapacity the minimum capacity that the {@code mArray} should have.
-     * @return the new capacity that the {@code mArray} should have. Returns zero when there is no
-     * need to expand {@code mArray}.
-     */
-    private int calculateCapacity(final int minimumCapacity) {
-        final int currentCapcity = mArray.length;
-        if (currentCapcity < minimumCapacity) {
-            final int nextCapacity = currentCapcity * 2;
-            // The following is the same as return Math.max(minimumCapacity, nextCapacity);
-            return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity;
-        }
-        return 0;
-    }
-
-    private void ensureCapacity(final int minimumCapacity) {
-        final int newCapacity = calculateCapacity(minimumCapacity);
-        if (newCapacity > 0) {
-            // TODO: Implement primitive array pool.
-            mArray = Arrays.copyOf(mArray, newCapacity);
-        }
-    }
-
-    public int getLength() {
-        return mLength;
-    }
-
-    public void setLength(final int newLength) {
-        ensureCapacity(newLength);
-        mLength = newLength;
-    }
-
-    public void reset(final int capacity) {
-        // TODO: Implement primitive array pool.
-        mArray = new int[capacity];
-        mLength = 0;
-    }
-
-    public int[] getPrimitiveArray() {
-        return mArray;
-    }
-
-    public void set(final ResizableIntArray ip) {
-        // TODO: Implement primitive array pool.
-        mArray = ip.mArray;
-        mLength = ip.mLength;
-    }
-
-    public void copy(final ResizableIntArray ip) {
-        final int newCapacity = calculateCapacity(ip.mLength);
-        if (newCapacity > 0) {
-            // TODO: Implement primitive array pool.
-            mArray = new int[newCapacity];
-        }
-        System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength);
-        mLength = ip.mLength;
-    }
-
-    public void append(final ResizableIntArray src, final int startPos, final int length) {
-        if (length == 0) {
-            return;
-        }
-        final int currentLength = mLength;
-        final int newLength = currentLength + length;
-        ensureCapacity(newLength);
-        System.arraycopy(src.mArray, startPos, mArray, currentLength, length);
-        mLength = newLength;
-    }
-
-    public void fill(final int value, final int startPos, final int length) {
-        if (startPos < 0 || length < 0) {
-            throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length);
-        }
-        final int endPos = startPos + length;
-        ensureCapacity(endPos);
-        Arrays.fill(mArray, startPos, endPos, value);
-        if (mLength < endPos) {
-            mLength = endPos;
-        }
-    }
-
-    /**
-     * Shift to the left by elementCount, discarding elementCount pointers at the start.
-     * @param elementCount how many elements to shift.
-     */
-    public void shift(final int elementCount) {
-        System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount);
-        mLength -= elementCount;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < mLength; i++) {
-            if (i != 0) {
-                sb.append(",");
-            }
-            sb.append(mArray[i]);
-        }
-        return "[" + sb + "]";
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
index 093c5a6..cc0d470 100644
--- a/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ResourceUtils.java
@@ -26,6 +26,7 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.settings.SettingsValues;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -110,7 +111,6 @@
      * are true for the specified key value pairs.
      *
      * For example, "condition,constant" has the following format.
-     * (See {@link ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp()})
      *  - HARDWARE=mako,constantForNexus4
      *  - MODEL=Nexus 4:MANUFACTURER=LGE,constantForNexus4
      *  - ,defaultConstant
@@ -119,6 +119,7 @@
      * @param conditionConstantArray an array of "condition,constant" elements to be searched.
      * @return the constant part of the matched "condition,constant" element. Returns null if no
      * condition matches.
+     * @see com.android.inputmethod.latin.utils.ResourceUtilsTests#testFindConstantForKeyValuePairsRegexp()
      */
     @UsedForTesting
     static String findConstantForKeyValuePairs(final HashMap<String, String> keyValuePairs,
@@ -186,6 +187,15 @@
         return dm.widthPixels;
     }
 
+    public static int getKeyboardHeight(final Resources res, final SettingsValues settingsValues) {
+        final int defaultKeyboardHeight = getDefaultKeyboardHeight(res);
+        if (settingsValues.mHasKeyboardResize) {
+            // mKeyboardHeightScale Ranges from [.5,1.2], from xml/prefs_screen_debug.xml
+            return (int)(defaultKeyboardHeight * settingsValues.mKeyboardHeightScale);
+        }
+        return defaultKeyboardHeight;
+    }
+
     public static int getDefaultKeyboardHeight(final Resources res) {
         final DisplayMetrics dm = res.getDisplayMetrics();
         final String keyboardHeightInDp = getDeviceOverrideValue(
diff --git a/java/src/com/android/inputmethod/latin/utils/ScriptUtils.java b/java/src/com/android/inputmethod/latin/utils/ScriptUtils.java
index 0e24466..5377130 100644
--- a/java/src/com/android/inputmethod/latin/utils/ScriptUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ScriptUtils.java
@@ -23,9 +23,10 @@
  * A class to help with handling different writing scripts.
  */
 public class ScriptUtils {
+
     // Used for hardware keyboards
     public static final int SCRIPT_UNKNOWN = -1;
-    // TODO: should we use ISO 15924 identifiers instead?
+
     public static final int SCRIPT_ARABIC = 0;
     public static final int SCRIPT_ARMENIAN = 1;
     public static final int SCRIPT_BENGALI = 2;
@@ -44,35 +45,31 @@
     public static final int SCRIPT_TAMIL = 15;
     public static final int SCRIPT_TELUGU = 16;
     public static final int SCRIPT_THAI = 17;
-    public static final TreeMap<String, Integer> mSpellCheckerLanguageToScript;
+
+    private static final TreeMap<String, Integer> mLanguageCodeToScriptCode;
+
     static {
-        // List of the supported languages and their associated script. We won't check
-        // words written in another script than the selected script, because we know we
-        // don't have those in our dictionary so we will underline everything and we
-        // will never have any suggestions, so it makes no sense checking them, and this
-        // is done in {@link #shouldFilterOut}. Also, the script is used to choose which
-        // proximity to pass to the dictionary descent algorithm.
-        // IMPORTANT: this only contains languages - do not write countries in there.
-        // Only the language is searched from the map.
-        mSpellCheckerLanguageToScript = new TreeMap<>();
-        mSpellCheckerLanguageToScript.put("cs", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("da", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("de", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("el", SCRIPT_GREEK);
-        mSpellCheckerLanguageToScript.put("en", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("es", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("fi", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("fr", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("hr", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("it", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("lt", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("lv", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("nb", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("nl", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("pt", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("sl", SCRIPT_LATIN);
-        mSpellCheckerLanguageToScript.put("ru", SCRIPT_CYRILLIC);
+        mLanguageCodeToScriptCode = new TreeMap<>();
+        mLanguageCodeToScriptCode.put("", SCRIPT_LATIN); // default
+        mLanguageCodeToScriptCode.put("ar", SCRIPT_ARABIC);
+        mLanguageCodeToScriptCode.put("hy", SCRIPT_ARMENIAN);
+        mLanguageCodeToScriptCode.put("bn", SCRIPT_BENGALI);
+        mLanguageCodeToScriptCode.put("bg", SCRIPT_CYRILLIC);
+        mLanguageCodeToScriptCode.put("sr", SCRIPT_CYRILLIC);
+        mLanguageCodeToScriptCode.put("ru", SCRIPT_CYRILLIC);
+        mLanguageCodeToScriptCode.put("ka", SCRIPT_GEORGIAN);
+        mLanguageCodeToScriptCode.put("el", SCRIPT_GREEK);
+        mLanguageCodeToScriptCode.put("iw", SCRIPT_HEBREW);
+        mLanguageCodeToScriptCode.put("km", SCRIPT_KHMER);
+        mLanguageCodeToScriptCode.put("lo", SCRIPT_LAO);
+        mLanguageCodeToScriptCode.put("ml", SCRIPT_MALAYALAM);
+        mLanguageCodeToScriptCode.put("my", SCRIPT_MYANMAR);
+        mLanguageCodeToScriptCode.put("si", SCRIPT_SINHALA);
+        mLanguageCodeToScriptCode.put("ta", SCRIPT_TAMIL);
+        mLanguageCodeToScriptCode.put("te", SCRIPT_TELUGU);
+        mLanguageCodeToScriptCode.put("th", SCRIPT_THAI);
     }
+
     /*
      * Returns whether the code point is a letter that makes sense for the specified
      * locale for this spell checker.
@@ -181,11 +178,17 @@
         }
     }
 
+    /**
+     * @param locale spell checker locale
+     * @return internal Latin IME script code that maps to a language code
+     * {@see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes}
+     */
     public static int getScriptFromSpellCheckerLocale(final Locale locale) {
-        final Integer script = mSpellCheckerLanguageToScript.get(locale.getLanguage());
-        if (null == script) {
-            throw new RuntimeException("We have been called with an unsupported language: \""
-                    + locale.getLanguage() + "\". Framework bug?");
+        String language = locale.getLanguage();
+        Integer script = mLanguageCodeToScriptCode.get(language);
+        if (script == null) {
+            // Default to Latin.
+            script = mLanguageCodeToScriptCode.get("");
         }
         return script;
     }
diff --git a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java b/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
deleted file mode 100644
index 1ca895f..0000000
--- a/java/src/com/android/inputmethod/latin/utils/SpacebarLanguageUtils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import android.view.inputmethod.InputMethodSubtype;
-
-public final class SpacebarLanguageUtils {
-    private SpacebarLanguageUtils() {
-        // Intentional empty constructor for utility class.
-    }
-
-    // InputMethodSubtype's display name for spacebar text in its locale.
-    //        isAdditionalSubtype (T=true, F=false)
-    // locale layout  |  Middle      Full
-    // ------ ------- - --------- ----------------------
-    //  en_US qwerty  F  English   English (US)           exception
-    //  en_GB qwerty  F  English   English (UK)           exception
-    //  es_US spanish F  Español   Español (EE.UU.)       exception
-    //  fr    azerty  F  Français  Français
-    //  fr_CA qwerty  F  Français  Français (Canada)
-    //  fr_CH swiss   F  Français  Français (Suisse)
-    //  de    qwertz  F  Deutsch   Deutsch
-    //  de_CH swiss   T  Deutsch   Deutsch (Schweiz)
-    //  zz    qwerty  F  QWERTY    QWERTY
-    //  fr    qwertz  T  Français  Français
-    //  de    qwerty  T  Deutsch   Deutsch
-    //  en_US azerty  T  English   English (US)
-    //  zz    azerty  T  AZERTY    AZERTY
-    // Get InputMethodSubtype's full display name in its locale.
-    public static String getFullDisplayName(final InputMethodSubtype subtype) {
-        if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
-            return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
-        }
-        return SubtypeLocaleUtils.getSubtypeLocaleDisplayName(subtype.getLocale());
-    }
-
-    // Get InputMethodSubtype's middle display name in its locale.
-    public static String getMiddleDisplayName(final InputMethodSubtype subtype) {
-        if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
-            return SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype);
-        }
-        return SubtypeLocaleUtils.getSubtypeLanguageDisplayName(subtype.getLocale());
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
index 38164cb..c41817f 100644
--- a/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SpannableStringUtils.java
@@ -24,6 +24,12 @@
 import android.text.style.SuggestionSpan;
 import android.text.style.URLSpan;
 
+import com.android.inputmethod.annotations.UsedForTesting;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 public final class SpannableStringUtils {
     /**
      * Copies the spans from the region <code>start...end</code> in
@@ -51,7 +57,7 @@
             // of a word. But the spans have been split into two by the getText{Before,After}Cursor
             // methods, so after concatenation they may end in the middle of a word.
             // Since we don't use them, we can just remove them and avoid crashing.
-            fl &= ~Spannable.SPAN_PARAGRAPH;
+            fl &= ~Spanned.SPAN_PARAGRAPH;
 
             int st = source.getSpanStart(spans[i]);
             int en = source.getSpanEnd(spans[i]);
@@ -125,4 +131,53 @@
         final URLSpan[] spans = spanned.getSpans(startIndex - 1, endIndex + 1, URLSpan.class);
         return null != spans && spans.length > 0;
     }
+
+    /**
+     * Splits the given {@code charSequence} with at occurrences of the given {@code regex}.
+     * <p>
+     * This is equivalent to
+     * {@code charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0)}
+     * except that the spans are preserved in the result array.
+     * </p>
+     * @param charSequence the character sequence to be split.
+     * @param regex the regex pattern to be used as the separator.
+     * @param preserveTrailingEmptySegments {@code true} to preserve the trailing empty
+     * segments. Otherwise, trailing empty segments will be removed before being returned.
+     * @return the array which contains the result. All the spans in the <code>charSequence</code>
+     * is preserved.
+     */
+    @UsedForTesting
+    public static CharSequence[] split(final CharSequence charSequence, final String regex,
+            final boolean preserveTrailingEmptySegments) {
+        // A short-cut for non-spanned strings.
+        if (!(charSequence instanceof Spanned)) {
+            // -1 means that trailing empty segments will be preserved.
+            return charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0);
+        }
+
+        // Hereafter, emulate String.split for CharSequence.
+        final ArrayList<CharSequence> sequences = new ArrayList<>();
+        final Matcher matcher = Pattern.compile(regex).matcher(charSequence);
+        int nextStart = 0;
+        boolean matched = false;
+        while (matcher.find()) {
+            sequences.add(charSequence.subSequence(nextStart, matcher.start()));
+            nextStart = matcher.end();
+            matched = true;
+        }
+        if (!matched) {
+            // never matched. preserveTrailingEmptySegments is ignored in this case.
+            return new CharSequence[] { charSequence };
+        }
+        sequences.add(charSequence.subSequence(nextStart, charSequence.length()));
+        if (!preserveTrailingEmptySegments) {
+            for (int i = sequences.size() - 1; i >= 0; --i) {
+                if (!TextUtils.isEmpty(sequences.get(i))) {
+                    break;
+                }
+                sequences.remove(i);
+            }
+        }
+        return sequences.toArray(new CharSequence[sequences.size()]);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
deleted file mode 100644
index 79128db..0000000
--- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
-
-import android.text.Spanned;
-import android.text.TextUtils;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Locale;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public final class StringUtils {
-    public static final int CAPITALIZE_NONE = 0;  // No caps, or mixed case
-    public static final int CAPITALIZE_FIRST = 1; // First only
-    public static final int CAPITALIZE_ALL = 2;   // All caps
-
-    private static final String EMPTY_STRING = "";
-
-    private static final char CHAR_LINE_FEED = 0X000A;
-    private static final char CHAR_VERTICAL_TAB = 0X000B;
-    private static final char CHAR_FORM_FEED = 0X000C;
-    private static final char CHAR_CARRIAGE_RETURN = 0X000D;
-    private static final char CHAR_NEXT_LINE = 0X0085;
-    private static final char CHAR_LINE_SEPARATOR = 0X2028;
-    private static final char CHAR_PARAGRAPH_SEPARATOR = 0X2029;
-
-    private StringUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    public static int codePointCount(final String text) {
-        if (TextUtils.isEmpty(text)) return 0;
-        return text.codePointCount(0, text.length());
-    }
-
-    public static String newSingleCodePointString(int codePoint) {
-        if (Character.charCount(codePoint) == 1) {
-            // Optimization: avoid creating a temporary array for characters that are
-            // represented by a single char value
-            return String.valueOf((char) codePoint);
-        }
-        // For surrogate pair
-        return new String(Character.toChars(codePoint));
-    }
-
-    public static boolean containsInArray(final String text, final String[] array) {
-        for (final String element : array) {
-            if (text.equals(element)) return true;
-        }
-        return false;
-    }
-
-    /**
-     * Comma-Splittable Text is similar to Comma-Separated Values (CSV) but has much simpler syntax.
-     * Unlike CSV, Comma-Splittable Text has no escaping mechanism, so that the text can't contain
-     * a comma character in it.
-     */
-    private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ",";
-
-    public static boolean containsInCommaSplittableText(final String text,
-            final String extraValues) {
-        if (TextUtils.isEmpty(extraValues)) {
-            return false;
-        }
-        return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT));
-    }
-
-    public static String removeFromCommaSplittableTextIfExists(final String text,
-            final String extraValues) {
-        if (TextUtils.isEmpty(extraValues)) {
-            return EMPTY_STRING;
-        }
-        final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT);
-        if (!containsInArray(text, elements)) {
-            return extraValues;
-        }
-        final ArrayList<String> result = new ArrayList<>(elements.length - 1);
-        for (final String element : elements) {
-            if (!text.equals(element)) {
-                result.add(element);
-            }
-        }
-        return TextUtils.join(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT, result);
-    }
-
-    /**
-     * Remove duplicates from an array of strings.
-     *
-     * This method will always keep the first occurrence of all strings at their position
-     * in the array, removing the subsequent ones.
-     */
-    public static void removeDupes(final ArrayList<String> suggestions) {
-        if (suggestions.size() < 2) return;
-        int i = 1;
-        // Don't cache suggestions.size(), since we may be removing items
-        while (i < suggestions.size()) {
-            final String cur = suggestions.get(i);
-            // Compare each suggestion with each previous suggestion
-            for (int j = 0; j < i; j++) {
-                final String previous = suggestions.get(j);
-                if (TextUtils.equals(cur, previous)) {
-                    suggestions.remove(i);
-                    i--;
-                    break;
-                }
-            }
-            i++;
-        }
-    }
-
-    public static String capitalizeFirstCodePoint(final String s, final Locale locale) {
-        if (s.length() <= 1) {
-            return toUpperCaseOfStringForLocale(s, true /* needsToUpperCase */, locale);
-        }
-        // Please refer to the comment below in
-        // {@link #capitalizeFirstAndDowncaseRest(String,Locale)} as this has the same shortcomings
-        final int cutoff = s.offsetByCodePoints(0, 1);
-        return toUpperCaseOfStringForLocale(
-                s.substring(0, cutoff), true /* needsToUpperCase */, locale) + s.substring(cutoff);
-    }
-
-    public static String capitalizeFirstAndDowncaseRest(final String s, final Locale locale) {
-        if (s.length() <= 1) {
-            return toUpperCaseOfStringForLocale(s, true /* needsToUpperCase */, locale);
-        }
-        // TODO: fix the bugs below
-        // - It does not work for Serbian, because it fails to account for the "lj" character,
-        // which should be "Lj" in title case and "LJ" in upper case.
-        // - It does not work for Dutch, because it fails to account for the "ij" digraph when it's
-        // written as two separate code points. They are two different characters but both should
-        // be capitalized as "IJ" as if they were a single letter in most words (not all). If the
-        // unicode char for the ligature is used however, it works.
-        final int cutoff = s.offsetByCodePoints(0, 1);
-        final String titleCaseFirstLetter = toUpperCaseOfStringForLocale(
-                s.substring(0, cutoff), true /* needsToUpperCase */, locale);
-        return titleCaseFirstLetter + s.substring(cutoff).toLowerCase(locale);
-    }
-
-    private static final int[] EMPTY_CODEPOINTS = {};
-
-    public static int[] toCodePointArray(final CharSequence charSequence) {
-        return toCodePointArray(charSequence, 0, charSequence.length());
-    }
-
-    /**
-     * Converts a range of a string to an array of code points.
-     * @param charSequence the source string.
-     * @param startIndex the start index inside the string in java chars, inclusive.
-     * @param endIndex the end index inside the string in java chars, exclusive.
-     * @return a new array of code points. At most endIndex - startIndex, but possibly less.
-     */
-    public static int[] toCodePointArray(final CharSequence charSequence,
-            final int startIndex, final int endIndex) {
-        final int length = charSequence.length();
-        if (length <= 0) {
-            return EMPTY_CODEPOINTS;
-        }
-        final int[] codePoints =
-                new int[Character.codePointCount(charSequence, startIndex, endIndex)];
-        copyCodePointsAndReturnCodePointCount(codePoints, charSequence, startIndex, endIndex,
-                false /* downCase */);
-        return codePoints;
-    }
-
-    /**
-     * Copies the codepoints in a CharSequence to an int array.
-     *
-     * This method assumes there is enough space in the array to store the code points. The size
-     * can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
-     * method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
-     * Also, this method makes no effort to be thread-safe. Do not modify the CharSequence while
-     * this method is running, or the behavior is undefined.
-     * This method can optionally downcase code points before copying them, but it pays no attention
-     * to locale while doing so.
-     *
-     * @param destination the int array.
-     * @param charSequence the CharSequence.
-     * @param startIndex the start index inside the string in java chars, inclusive.
-     * @param endIndex the end index inside the string in java chars, exclusive.
-     * @param downCase if this is true, code points will be downcased before being copied.
-     * @return the number of copied code points.
-     */
-    public static int copyCodePointsAndReturnCodePointCount(final int[] destination,
-            final CharSequence charSequence, final int startIndex, final int endIndex,
-            final boolean downCase) {
-        int destIndex = 0;
-        for (int index = startIndex; index < endIndex;
-                index = Character.offsetByCodePoints(charSequence, index, 1)) {
-            final int codePoint = Character.codePointAt(charSequence, index);
-            // TODO: stop using this, as it's not aware of the locale and does not always do
-            // the right thing.
-            destination[destIndex] = downCase ? Character.toLowerCase(codePoint) : codePoint;
-            destIndex++;
-        }
-        return destIndex;
-    }
-
-    public static int[] toSortedCodePointArray(final String string) {
-        final int[] codePoints = toCodePointArray(string);
-        Arrays.sort(codePoints);
-        return codePoints;
-    }
-
-    /**
-     * Construct a String from a code point array
-     *
-     * @param codePoints a code point array that is null terminated when its logical length is
-     * shorter than the array length.
-     * @return a string constructed from the code point array.
-     */
-    public static String getStringFromNullTerminatedCodePointArray(final int[] codePoints) {
-        int stringLength = codePoints.length;
-        for (int i = 0; i < codePoints.length; i++) {
-            if (codePoints[i] == 0) {
-                stringLength = i;
-                break;
-            }
-        }
-        return new String(codePoints, 0 /* offset */, stringLength);
-    }
-
-    // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
-    public static int getCapitalizationType(final String text) {
-        // If the first char is not uppercase, then the word is either all lower case or
-        // camel case, and in either case we return CAPITALIZE_NONE.
-        final int len = text.length();
-        int index = 0;
-        for (; index < len; index = text.offsetByCodePoints(index, 1)) {
-            if (Character.isLetter(text.codePointAt(index))) {
-                break;
-            }
-        }
-        if (index == len) return CAPITALIZE_NONE;
-        if (!Character.isUpperCase(text.codePointAt(index))) {
-            return CAPITALIZE_NONE;
-        }
-        int capsCount = 1;
-        int letterCount = 1;
-        for (index = text.offsetByCodePoints(index, 1); index < len;
-                index = text.offsetByCodePoints(index, 1)) {
-            if (1 != capsCount && letterCount != capsCount) break;
-            final int codePoint = text.codePointAt(index);
-            if (Character.isUpperCase(codePoint)) {
-                ++capsCount;
-                ++letterCount;
-            } else if (Character.isLetter(codePoint)) {
-                // We need to discount non-letters since they may not be upper-case, but may
-                // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
-                ++letterCount;
-            }
-        }
-        // We know the first char is upper case. So we want to test if either every letter other
-        // than the first is lower case, or if they are all upper case. If the string is exactly
-        // one char long, then we will arrive here with letterCount 1, and this is correct, too.
-        if (1 == capsCount) return CAPITALIZE_FIRST;
-        return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
-    }
-
-    public static boolean isIdenticalAfterUpcase(final String text) {
-        final int length = text.length();
-        int i = 0;
-        while (i < length) {
-            final int codePoint = text.codePointAt(i);
-            if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) {
-                return false;
-            }
-            i += Character.charCount(codePoint);
-        }
-        return true;
-    }
-
-    public static boolean isIdenticalAfterDowncase(final String text) {
-        final int length = text.length();
-        int i = 0;
-        while (i < length) {
-            final int codePoint = text.codePointAt(i);
-            if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) {
-                return false;
-            }
-            i += Character.charCount(codePoint);
-        }
-        return true;
-    }
-
-    public static boolean isIdenticalAfterCapitalizeEachWord(final String text,
-            final int[] sortedSeparators) {
-        boolean needsCapsNext = true;
-        final int len = text.length();
-        for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
-            final int codePoint = text.codePointAt(i);
-            if (Character.isLetter(codePoint)) {
-                if ((needsCapsNext && !Character.isUpperCase(codePoint))
-                        || (!needsCapsNext && !Character.isLowerCase(codePoint))) {
-                    return false;
-                }
-            }
-            // We need a capital letter next if this is a separator.
-            needsCapsNext = (Arrays.binarySearch(sortedSeparators, codePoint) >= 0);
-        }
-        return true;
-    }
-
-    // TODO: like capitalizeFirst*, this does not work perfectly for Dutch because of the IJ digraph
-    // which should be capitalized together in *some* cases.
-    public static String capitalizeEachWord(final String text, final int[] sortedSeparators,
-            final Locale locale) {
-        final StringBuilder builder = new StringBuilder();
-        boolean needsCapsNext = true;
-        final int len = text.length();
-        for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
-            final String nextChar = text.substring(i, text.offsetByCodePoints(i, 1));
-            if (needsCapsNext) {
-                builder.append(nextChar.toUpperCase(locale));
-            } else {
-                builder.append(nextChar.toLowerCase(locale));
-            }
-            // We need a capital letter next if this is a separator.
-            needsCapsNext = (Arrays.binarySearch(sortedSeparators, nextChar.codePointAt(0)) >= 0);
-        }
-        return builder.toString();
-    }
-
-    /**
-     * Approximates whether the text before the cursor looks like a URL.
-     *
-     * This is not foolproof, but it should work well in the practice.
-     * Essentially it walks backward from the cursor until it finds something that's not a letter,
-     * digit, or common URL symbol like underscore. If it hasn't found a period yet, then it
-     * does not look like a URL.
-     * If the text:
-     * - starts with www and contains a period
-     * - starts with a slash preceded by either a slash, whitespace, or start-of-string
-     * Then it looks like a URL and we return true. Otherwise, we return false.
-     *
-     * Note: this method is called quite often, and should be fast.
-     *
-     * TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the
-     * code complexity, but ideally it should not. It's acceptable for now.
-     */
-    public static boolean lastPartLooksLikeURL(final CharSequence text) {
-        int i = text.length();
-        if (0 == i) return false;
-        int wCount = 0;
-        int slashCount = 0;
-        boolean hasSlash = false;
-        boolean hasPeriod = false;
-        int codePoint = 0;
-        while (i > 0) {
-            codePoint = Character.codePointBefore(text, i);
-            if (codePoint < Constants.CODE_PERIOD || codePoint > 'z') {
-                // Handwavy heuristic to see if that's a URL character. Anything between period
-                // and z. This includes all lower- and upper-case ascii letters, period,
-                // underscore, arrobase, question mark, equal sign. It excludes spaces, exclamation
-                // marks, double quotes...
-                // Anything that's not a URL-like character causes us to break from here and
-                // evaluate normally.
-                break;
-            }
-            if (Constants.CODE_PERIOD == codePoint) {
-                hasPeriod = true;
-            }
-            if (Constants.CODE_SLASH == codePoint) {
-                hasSlash = true;
-                if (2 == ++slashCount) {
-                    return true;
-                }
-            } else {
-                slashCount = 0;
-            }
-            if ('w' == codePoint) {
-                ++wCount;
-            } else {
-                wCount = 0;
-            }
-            i = Character.offsetByCodePoints(text, i, -1);
-        }
-        // End of the text run.
-        // If it starts with www and includes a period, then it looks like a URL.
-        if (wCount >= 3 && hasPeriod) return true;
-        // If it starts with a slash, and the code point before is whitespace, it looks like an URL.
-        if (1 == slashCount && (0 == i || Character.isWhitespace(codePoint))) return true;
-        // If it has both a period and a slash, it looks like an URL.
-        if (hasPeriod && hasSlash) return true;
-        // Otherwise, it doesn't look like an URL.
-        return false;
-    }
-
-    /**
-     * Examines the string and returns whether we're inside a double quote.
-     *
-     * This is used to decide whether we should put an automatic space before or after a double
-     * quote character. If we're inside a quotation, then we want to close it, so we want a space
-     * after and not before. Otherwise, we want to open the quotation, so we want a space before
-     * and not after. Exception: after a digit, we never want a space because the "inch" or
-     * "minutes" use cases is dominant after digits.
-     * In the practice, we determine whether we are in a quotation or not by finding the previous
-     * double quote character, and looking at whether it's followed by whitespace. If so, that
-     * was a closing quotation mark, so we're not inside a double quote. If it's not followed
-     * by whitespace, then it was an opening quotation mark, and we're inside a quotation.
-     *
-     * @param text the text to examine.
-     * @return whether we're inside a double quote.
-     */
-    public static boolean isInsideDoubleQuoteOrAfterDigit(final CharSequence text) {
-        int i = text.length();
-        if (0 == i) return false;
-        int codePoint = Character.codePointBefore(text, i);
-        if (Character.isDigit(codePoint)) return true;
-        int prevCodePoint = 0;
-        while (i > 0) {
-            codePoint = Character.codePointBefore(text, i);
-            if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
-                // If we see a double quote followed by whitespace, then that
-                // was a closing quote.
-                if (Character.isWhitespace(prevCodePoint)) return false;
-            }
-            if (Character.isWhitespace(codePoint) && Constants.CODE_DOUBLE_QUOTE == prevCodePoint) {
-                // If we see a double quote preceded by whitespace, then that
-                // was an opening quote. No need to continue seeking.
-                return true;
-            }
-            i -= Character.charCount(codePoint);
-            prevCodePoint = codePoint;
-        }
-        // We reached the start of text. If the first char is a double quote, then we're inside
-        // a double quote. Otherwise we're not.
-        return Constants.CODE_DOUBLE_QUOTE == codePoint;
-    }
-
-    public static boolean isEmptyStringOrWhiteSpaces(final String s) {
-        final int N = codePointCount(s);
-        for (int i = 0; i < N; ++i) {
-            if (!Character.isWhitespace(s.codePointAt(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @UsedForTesting
-    public static String byteArrayToHexString(final byte[] bytes) {
-        if (bytes == null || bytes.length == 0) {
-            return EMPTY_STRING;
-        }
-        final StringBuilder sb = new StringBuilder();
-        for (byte b : bytes) {
-            sb.append(String.format("%02x", b & 0xff));
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Convert hex string to byte array. The string length must be an even number.
-     */
-    @UsedForTesting
-    public static byte[] hexStringToByteArray(final String hexString) {
-        if (TextUtils.isEmpty(hexString)) {
-            return null;
-        }
-        final int N = hexString.length();
-        if (N % 2 != 0) {
-            throw new NumberFormatException("Input hex string length must be an even number."
-                    + " Length = " + N);
-        }
-        final byte[] bytes = new byte[N / 2];
-        for (int i = 0; i < N; i += 2) {
-            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
-                    + Character.digit(hexString.charAt(i + 1), 16));
-        }
-        return bytes;
-    }
-
-    private static final String LANGUAGE_GREEK = "el";
-
-    private static Locale getLocaleUsedForToTitleCase(final Locale locale) {
-        // In Greek locale {@link String#toUpperCase(Locale)} eliminates accents from its result.
-        // In order to get accented upper case letter, {@link Locale#ROOT} should be used.
-        if (LANGUAGE_GREEK.equals(locale.getLanguage())) {
-            return Locale.ROOT;
-        }
-        return locale;
-    }
-
-    public static String toUpperCaseOfStringForLocale(final String text,
-            final boolean needsToUpperCase, final Locale locale) {
-        if (text == null || !needsToUpperCase) {
-            return text;
-        }
-        return text.toUpperCase(getLocaleUsedForToTitleCase(locale));
-    }
-
-    public static int toUpperCaseOfCodeForLocale(final int code, final boolean needsToUpperCase,
-            final Locale locale) {
-        if (!Constants.isLetterCode(code) || !needsToUpperCase) return code;
-        final String text = newSingleCodePointString(code);
-        final String casedText = toUpperCaseOfStringForLocale(
-                text, needsToUpperCase, locale);
-        return codePointCount(casedText) == 1
-                ? casedText.codePointAt(0) : CODE_UNSPECIFIED;
-    }
-
-    public static int getTrailingSingleQuotesCount(final CharSequence charSequence) {
-        final int lastIndex = charSequence.length() - 1;
-        int i = lastIndex;
-        while (i >= 0 && charSequence.charAt(i) == Constants.CODE_SINGLE_QUOTE) {
-            --i;
-        }
-        return lastIndex - i;
-    }
-
-    /**
-     * Splits the given {@code charSequence} with at occurrences of the given {@code regex}.
-     * <p>
-     * This is equivalent to
-     * {@code charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0)}
-     * except that the spans are preserved in the result array.
-     * </p>
-     * @param input the character sequence to be split.
-     * @param regex the regex pattern to be used as the separator.
-     * @param preserveTrailingEmptySegments {@code true} to preserve the trailing empty
-     * segments. Otherwise, trailing empty segments will be removed before being returned.
-     * @return the array which contains the result. All the spans in the {@param input} is
-     * preserved.
-     */
-    @UsedForTesting
-    public static CharSequence[] split(final CharSequence charSequence, final String regex,
-            final boolean preserveTrailingEmptySegments) {
-        // A short-cut for non-spanned strings.
-        if (!(charSequence instanceof Spanned)) {
-            // -1 means that trailing empty segments will be preserved.
-            return charSequence.toString().split(regex, preserveTrailingEmptySegments ? -1 : 0);
-        }
-
-        // Hereafter, emulate String.split for CharSequence.
-        final ArrayList<CharSequence> sequences = new ArrayList<>();
-        final Matcher matcher = Pattern.compile(regex).matcher(charSequence);
-        int nextStart = 0;
-        boolean matched = false;
-        while (matcher.find()) {
-            sequences.add(charSequence.subSequence(nextStart, matcher.start()));
-            nextStart = matcher.end();
-            matched = true;
-        }
-        if (!matched) {
-            // never matched. preserveTrailingEmptySegments is ignored in this case.
-            return new CharSequence[] { charSequence };
-        }
-        sequences.add(charSequence.subSequence(nextStart, charSequence.length()));
-        if (!preserveTrailingEmptySegments) {
-            for (int i = sequences.size() - 1; i >= 0; --i) {
-                if (!TextUtils.isEmpty(sequences.get(i))) {
-                    break;
-                }
-                sequences.remove(i);
-            }
-        }
-        return sequences.toArray(new CharSequence[sequences.size()]);
-    }
-
-    @UsedForTesting
-    public static class Stringizer<E> {
-        public String stringize(final E element) {
-            return element != null ? element.toString() : "null";
-        }
-
-        @UsedForTesting
-        public final String join(final E[] array) {
-            return joinStringArray(toStringArray(array), null /* delimiter */);
-        }
-
-        @UsedForTesting
-        public final String join(final E[] array, final String delimiter) {
-            return joinStringArray(toStringArray(array), delimiter);
-        }
-
-        protected String[] toStringArray(final E[] array) {
-            final String[] stringArray = new String[array.length];
-            for (int index = 0; index < array.length; index++) {
-                stringArray[index] = stringize(array[index]);
-            }
-            return stringArray;
-        }
-
-        protected String joinStringArray(final String[] stringArray, final String delimiter) {
-            if (stringArray == null) {
-                return "null";
-            }
-            if (delimiter == null) {
-                return Arrays.toString(stringArray);
-            }
-            final StringBuilder sb = new StringBuilder();
-            for (int index = 0; index < stringArray.length; index++) {
-                sb.append(index == 0 ? "[" : delimiter);
-                sb.append(stringArray[index]);
-            }
-            return sb + "]";
-        }
-    }
-
-    /**
-     * Returns whether the last composed word contains line-breaking character (e.g. CR or LF).
-     * @param text the text to be examined.
-     * @return {@code true} if the last composed word contains line-breaking separator.
-     */
-    @UsedForTesting
-    public static boolean hasLineBreakCharacter(final String text) {
-        if (TextUtils.isEmpty(text)) {
-            return false;
-        }
-        for (int i = text.length() - 1; i >= 0; --i) {
-            final char c = text.charAt(i);
-            switch (c) {
-                case CHAR_LINE_FEED:
-                case CHAR_VERTICAL_TAB:
-                case CHAR_FORM_FEED:
-                case CHAR_CARRIAGE_RETURN:
-                case CHAR_NEXT_LINE:
-                case CHAR_LINE_SEPARATOR:
-                case CHAR_PARAGRAPH_SEPARATOR:
-                    return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 351d014..54a3fc3 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -16,8 +16,9 @@
 
 package com.android.inputmethod.latin.utils;
 
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.COMBINING_RULES;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -25,18 +26,25 @@
 import android.util.Log;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Locale;
 
-public final class SubtypeLocaleUtils {
-    private static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
-    // This reference class {@link Constants} must be located in the same package as LatinIME.java.
-    private static final String RESOURCE_PACKAGE_NAME = Constants.class.getPackage().getName();
+/**
+ * A helper class to deal with subtype locales.
+  */
+// TODO: consolidate this into RichInputMethodSubtype
+public final class SubtypeLocaleUtils {
+    static final String TAG = SubtypeLocaleUtils.class.getSimpleName();
+
+    // This reference class {@link R} must be located in the same package as LatinIME.java.
+    private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
 
     // Special language code to represent "no language".
     public static final String NO_LANGUAGE = "zz";
@@ -47,11 +55,13 @@
     private static volatile boolean sInitialized = false;
     private static final Object sInitializeLock = new Object();
     private static Resources sResources;
-    private static String[] sPredefinedKeyboardLayoutSet;
     // Keyboard layout to its display name map.
     private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap = new HashMap<>();
     // Keyboard layout to subtype name resource id map.
     private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap = new HashMap<>();
+    // Exceptional locale whose name should be displayed in Locale.ROOT.
+    private static final HashMap<String, Integer> sExceptionalLocaleDisplayedInRootLocale =
+            new HashMap<>();
     // Exceptional locale to subtype name resource id map.
     private static final HashMap<String, Integer> sExceptionalLocaleToNameIdsMap = new HashMap<>();
     // Exceptional locale to subtype name with layout resource id map.
@@ -65,6 +75,8 @@
             "string/subtype_with_layout_";
     private static final String SUBTYPE_NAME_RESOURCE_NO_LANGUAGE_PREFIX =
             "string/subtype_no_language_";
+    private static final String SUBTYPE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX =
+            "string/subtype_in_root_locale_";
     // Keyboard layout set name for the subtypes that don't have a keyboardLayoutSet extra value.
     // This is for compatibility to keep the same subtype ids as pre-JellyBean.
     private static final HashMap<String, String> sLocaleAndExtraValueToKeyboardLayoutSetMap =
@@ -89,7 +101,6 @@
         sResources = res;
 
         final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
-        sPredefinedKeyboardLayoutSet = predefinedLayoutSet;
         final String[] layoutDisplayNames = res.getStringArray(
                 R.array.predefined_layout_display_names);
         for (int i = 0; i < predefinedLayoutSet.length; i++) {
@@ -106,6 +117,15 @@
             sKeyboardLayoutToNameIdsMap.put(key, noLanguageResId);
         }
 
+        final String[] exceptionalLocaleInRootLocale = res.getStringArray(
+                R.array.subtype_locale_displayed_in_root_locale);
+        for (int i = 0; i < exceptionalLocaleInRootLocale.length; i++) {
+            final String localeString = exceptionalLocaleInRootLocale[i];
+            final String resourceName = SUBTYPE_NAME_RESOURCE_IN_ROOT_LOCALE_PREFIX + localeString;
+            final int resId = res.getIdentifier(resourceName, null, RESOURCE_PACKAGE_NAME);
+            sExceptionalLocaleDisplayedInRootLocale.put(localeString, resId);
+        }
+
         final String[] exceptionalLocales = res.getStringArray(
                 R.array.subtype_locale_exception_keys);
         for (int i = 0; i < exceptionalLocales.length; i++) {
@@ -129,10 +149,6 @@
         }
     }
 
-    public static String[] getPredefinedKeyboardLayoutSet() {
-        return sPredefinedKeyboardLayoutSet;
-    }
-
     public static boolean isExceptionalLocale(final String localeString) {
         return sExceptionalLocaleToNameIdsMap.containsKey(localeString);
     }
@@ -153,36 +169,58 @@
         return nameId == null ? UNKNOWN_KEYBOARD_LAYOUT : nameId;
     }
 
-    private static Locale getDisplayLocaleOfSubtypeLocale(final String localeString) {
+    @Nonnull
+    public static Locale getDisplayLocaleOfSubtypeLocale(@Nonnull final String localeString) {
         if (NO_LANGUAGE.equals(localeString)) {
             return sResources.getConfiguration().locale;
         }
+        if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
+            return Locale.ROOT;
+        }
         return LocaleUtils.constructLocaleFromString(localeString);
     }
 
-    public static String getSubtypeLocaleDisplayNameInSystemLocale(final String localeString) {
+    public static String getSubtypeLocaleDisplayNameInSystemLocale(
+            @Nonnull final String localeString) {
         final Locale displayLocale = sResources.getConfiguration().locale;
         return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
     }
 
-    public static String getSubtypeLocaleDisplayName(final String localeString) {
+    @Nonnull
+    public static String getSubtypeLocaleDisplayName(@Nonnull final String localeString) {
         final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
         return getSubtypeLocaleDisplayNameInternal(localeString, displayLocale);
     }
 
-    public static String getSubtypeLanguageDisplayName(final String localeString) {
-        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
+    @Nonnull
+    public static String getSubtypeLanguageDisplayName(@Nonnull final String localeString) {
         final Locale displayLocale = getDisplayLocaleOfSubtypeLocale(localeString);
-        return getSubtypeLocaleDisplayNameInternal(locale.getLanguage(), displayLocale);
+        final String languageString;
+        if (sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
+            languageString = localeString;
+        } else {
+            languageString = LocaleUtils.constructLocaleFromString(localeString).getLanguage();
+        }
+        return getSubtypeLocaleDisplayNameInternal(languageString, displayLocale);
     }
 
-    private static String getSubtypeLocaleDisplayNameInternal(final String localeString,
-            final Locale displayLocale) {
+    @Nonnull
+    private static String getSubtypeLocaleDisplayNameInternal(@Nonnull final String localeString,
+            @Nonnull final Locale displayLocale) {
         if (NO_LANGUAGE.equals(localeString)) {
             // No language subtype should be displayed in system locale.
             return sResources.getString(R.string.subtype_no_language);
         }
-        final Integer exceptionalNameResId = sExceptionalLocaleToNameIdsMap.get(localeString);
+        final Integer exceptionalNameResId;
+        if (displayLocale.equals(Locale.ROOT)
+                && sExceptionalLocaleDisplayedInRootLocale.containsKey(localeString)) {
+            exceptionalNameResId = sExceptionalLocaleDisplayedInRootLocale.get(localeString);
+        } else if (sExceptionalLocaleToNameIdsMap.containsKey(localeString)) {
+            exceptionalNameResId = sExceptionalLocaleToNameIdsMap.get(localeString);
+        } else {
+            exceptionalNameResId = null;
+        }
+
         final String displayName;
         if (exceptionalNameResId != null) {
             final RunInLocale<String> getExceptionalName = new RunInLocale<String>() {
@@ -193,8 +231,8 @@
             };
             displayName = getExceptionalName.runInLocale(sResources, displayLocale);
         } else {
-            final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
-            displayName = locale.getDisplayName(displayLocale);
+            displayName = LocaleUtils.constructLocaleFromString(localeString)
+                    .getDisplayName(displayLocale);
         }
         return StringUtils.capitalizeFirstCodePoint(displayName, displayLocale);
     }
@@ -217,31 +255,36 @@
     //  en_US azerty  T  English (US) (AZERTY)   exception
     //  zz    azerty  T  Alphabet (AZERTY)       in system locale
 
-    private static String getReplacementString(final InputMethodSubtype subtype,
-            final Locale displayLocale) {
+    @Nonnull
+    private static String getReplacementString(@Nonnull final InputMethodSubtype subtype,
+            @Nonnull final Locale displayLocale) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
                 && subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
             return subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
-        } else {
-            return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
         }
+        return getSubtypeLocaleDisplayNameInternal(subtype.getLocale(), displayLocale);
     }
 
-    public static String getSubtypeDisplayNameInSystemLocale(final InputMethodSubtype subtype) {
+    @Nonnull
+    public static String getSubtypeDisplayNameInSystemLocale(
+            @Nonnull final InputMethodSubtype subtype) {
         final Locale displayLocale = sResources.getConfiguration().locale;
         return getSubtypeDisplayNameInternal(subtype, displayLocale);
     }
 
-    public static String getSubtypeNameForLogging(final InputMethodSubtype subtype) {
+    @Nonnull
+    public static String getSubtypeNameForLogging(@Nullable final InputMethodSubtype subtype) {
         if (subtype == null) {
             return "<null subtype>";
         }
         return getSubtypeLocale(subtype) + "/" + getKeyboardLayoutSetName(subtype);
     }
 
-    private static String getSubtypeDisplayNameInternal(final InputMethodSubtype subtype,
-            final Locale displayLocale) {
+    @Nonnull
+    private static String getSubtypeDisplayNameInternal(@Nonnull final InputMethodSubtype subtype,
+            @Nonnull final Locale displayLocale) {
         final String replacementString = getReplacementString(subtype, displayLocale);
+        // TODO: rework this for multi-lingual subtypes
         final int nameResId = subtype.getNameResId();
         final RunInLocale<String> getSubtypeName = new RunInLocale<String>() {
             @Override
@@ -264,25 +307,25 @@
                 getSubtypeName.runInLocale(sResources, displayLocale), displayLocale);
     }
 
-    public static boolean isNoLanguage(final InputMethodSubtype subtype) {
-        final String localeString = subtype.getLocale();
-        return NO_LANGUAGE.equals(localeString);
-    }
-
-    public static Locale getSubtypeLocale(final InputMethodSubtype subtype) {
+    @Nonnull
+    public static Locale getSubtypeLocale(@Nonnull final InputMethodSubtype subtype) {
         final String localeString = subtype.getLocale();
         return LocaleUtils.constructLocaleFromString(localeString);
     }
 
-    public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) {
+    @Nonnull
+    public static String getKeyboardLayoutSetDisplayName(
+            @Nonnull final InputMethodSubtype subtype) {
         final String layoutName = getKeyboardLayoutSetName(subtype);
         return getKeyboardLayoutSetDisplayName(layoutName);
     }
 
-    public static String getKeyboardLayoutSetDisplayName(final String layoutName) {
+    @Nonnull
+    public static String getKeyboardLayoutSetDisplayName(@Nonnull final String layoutName) {
         return sKeyboardLayoutToDisplayNameMap.get(layoutName);
     }
 
+    @Nonnull
     public static String getKeyboardLayoutSetName(final InputMethodSubtype subtype) {
         String keyboardLayoutSet = subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET);
         if (keyboardLayoutSet == null) {
@@ -302,27 +345,7 @@
         return keyboardLayoutSet;
     }
 
-    // TODO: Get this information from the framework instead of maintaining here by ourselves.
-    // Sorted list of known Right-To-Left language codes.
-    private static final String[] SORTED_RTL_LANGUAGES = {
-        "ar", // Arabic
-        "fa", // Persian
-        "iw", // Hebrew
-    };
-    static {
-        Arrays.sort(SORTED_RTL_LANGUAGES);
-    }
-
-    public static boolean isRtlLanguage(final Locale locale) {
-        final String language = locale.getLanguage();
-        return Arrays.binarySearch(SORTED_RTL_LANGUAGES, language) >= 0;
-    }
-
-    public static boolean isRtlLanguage(final InputMethodSubtype subtype) {
-        return isRtlLanguage(getSubtypeLocale(subtype));
-    }
-
     public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) {
-        return subtype.getExtraValueOf(Constants.Subtype.ExtraValue.COMBINING_RULES);
+        return subtype.getExtraValueOf(COMBINING_RULES);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
index 8cd4950..9813551 100644
--- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
+++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
@@ -22,7 +22,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
-import java.util.Locale;
 import java.util.TreeSet;
 
 /**
@@ -30,22 +29,23 @@
  * than its limit
  */
 public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
-    public final Locale mLocale;
     public final ArrayList<SuggestedWordInfo> mRawSuggestions;
     // TODO: Instead of a boolean , we may want to include the context of this suggestion results,
-    // such as {@link PrevWordsInfo}.
+    // such as {@link NgramContext}.
     public final boolean mIsBeginningOfSentence;
+    public final boolean mFirstSuggestionExceedsConfidenceThreshold;
     private final int mCapacity;
 
-    public SuggestionResults(final Locale locale, final int capacity,
-            final boolean isBeginningOfSentence) {
-        this(locale, sSuggestedWordInfoComparator, capacity, isBeginningOfSentence);
+    public SuggestionResults(final int capacity, final boolean isBeginningOfSentence,
+            final boolean firstSuggestionExceedsConfidenceThreshold) {
+        this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence,
+                firstSuggestionExceedsConfidenceThreshold);
     }
 
-    private SuggestionResults(final Locale locale, final Comparator<SuggestedWordInfo> comparator,
-            final int capacity, final boolean isBeginningOfSentence) {
+    private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity,
+            final boolean isBeginningOfSentence,
+            final boolean firstSuggestionExceedsConfidenceThreshold) {
         super(comparator);
-        mLocale = locale;
         mCapacity = capacity;
         if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) {
             mRawSuggestions = new ArrayList<>();
@@ -53,6 +53,7 @@
             mRawSuggestions = null;
         }
         mIsBeginningOfSentence = isBeginningOfSentence;
+        mFirstSuggestionExceedsConfidenceThreshold = firstSuggestionExceedsConfidenceThreshold;
     }
 
     @Override
@@ -70,8 +71,7 @@
         return super.addAll(e);
     }
 
-    private static final class SuggestedWordInfoComparator
-            implements Comparator<SuggestedWordInfo> {
+    static final class SuggestedWordInfoComparator implements Comparator<SuggestedWordInfo> {
         // This comparator ranks the word info with the higher frequency first. That's because
         // that's the order we want our elements in.
         @Override
diff --git a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
index dd122b6..0bcba27 100644
--- a/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ViewLayoutUtils.java
@@ -57,7 +57,7 @@
 
     public static void updateLayoutHeightOf(final Window window, final int layoutHeight) {
         final WindowManager.LayoutParams params = window.getAttributes();
-        if (params.height != layoutHeight) {
+        if (params != null && params.height != layoutHeight) {
             params.height = layoutHeight;
             window.setAttributes(params);
         }
@@ -65,7 +65,7 @@
 
     public static void updateLayoutHeightOf(final View view, final int layoutHeight) {
         final ViewGroup.LayoutParams params = view.getLayoutParams();
-        if (params.height != layoutHeight) {
+        if (params != null && params.height != layoutHeight) {
             params.height = layoutHeight;
             view.setLayoutParams(params);
         }
diff --git a/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
new file mode 100644
index 0000000..fc0a9cb
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.util.Log;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+// Note: this class is used as a parameter type of a native method. You should be careful when you
+// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative().
+public final class WordInputEventForPersonalization {
+    private static final String TAG = WordInputEventForPersonalization.class.getSimpleName();
+    private static final boolean DEBUG_TOKEN = false;
+
+    public final int[] mTargetWord;
+    public final int mPrevWordsCount;
+    public final int[][] mPrevWordArray =
+            new int[DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM][];
+    public final boolean[] mIsPrevWordBeginningOfSentenceArray =
+            new boolean[DecoderSpecificConstants.MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    // Time stamp in seconds.
+    public final int mTimestamp;
+
+    @UsedForTesting
+    public WordInputEventForPersonalization(final CharSequence targetWord,
+            final NgramContext ngramContext, final int timestamp) {
+        mTargetWord = StringUtils.toCodePointArray(targetWord);
+        mPrevWordsCount = ngramContext.getPrevWordCount();
+        ngramContext.outputToArray(mPrevWordArray, mIsPrevWordBeginningOfSentenceArray);
+        mTimestamp = timestamp;
+    }
+
+    // Process a list of words and return a list of {@link WordInputEventForPersonalization}
+    // objects.
+    public static ArrayList<WordInputEventForPersonalization> createInputEventFrom(
+            final List<String> tokens, final int timestamp,
+            final SpacingAndPunctuations spacingAndPunctuations, final Locale locale) {
+        final ArrayList<WordInputEventForPersonalization> inputEvents = new ArrayList<>();
+        final int N = tokens.size();
+        NgramContext ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+        for (int i = 0; i < N; ++i) {
+            final String tempWord = tokens.get(i);
+            if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) {
+                // just skip this token
+                if (DEBUG_TOKEN) {
+                    Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\"");
+                }
+                continue;
+            }
+            if (!DictionaryInfoUtils.looksValidForDictionaryInsertion(
+                    tempWord, spacingAndPunctuations)) {
+                if (DEBUG_TOKEN) {
+                    Log.d(TAG, "--- not looksValidForDictionaryInsertion: \""
+                            + tempWord + "\"");
+                }
+                // Sentence terminator found. Split.
+                // TODO: Detect whether the context is beginning-of-sentence.
+                ngramContext = NgramContext.EMPTY_PREV_WORDS_INFO;
+                continue;
+            }
+            if (DEBUG_TOKEN) {
+                Log.d(TAG, "--- word: \"" + tempWord + "\"");
+            }
+            final WordInputEventForPersonalization inputEvent =
+                    detectWhetherVaildWordOrNotAndGetInputEvent(
+                            ngramContext, tempWord, timestamp, locale);
+            if (inputEvent == null) {
+                continue;
+            }
+            inputEvents.add(inputEvent);
+            ngramContext = ngramContext.getNextNgramContext(new NgramContext.WordInfo(tempWord));
+        }
+        return inputEvents;
+    }
+
+    private static WordInputEventForPersonalization detectWhetherVaildWordOrNotAndGetInputEvent(
+            final NgramContext ngramContext, final String targetWord, final int timestamp,
+            final Locale locale) {
+        if (locale == null) {
+            return null;
+        }
+        return new WordInputEventForPersonalization(targetWord, ngramContext, timestamp);
+    }
+}
diff --git a/native/dicttoolkit/Android.mk b/native/dicttoolkit/Android.mk
new file mode 100644
index 0000000..118682d
--- /dev/null
+++ b/native/dicttoolkit/Android.mk
@@ -0,0 +1,67 @@
+# Copyright (C) 2014 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.
+
+ifeq (,$(TARGET_BUILD_APPS))
+
+# Only build if it's explicitly requested, or running mm/mmm.
+ifneq ($(ONE_SHOT_MAKEFILE)$(filter $(MAKECMDGOALS),dicttoolkit),)
+
+# HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11.
+LATINIME_HOST_OSNAME := $(shell uname -s)
+ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LATIN_IME_CORE_PATH := $(LOCAL_PATH)/../jni
+
+LATIN_IME_DICT_TOOLKIT_SRC_DIR := src
+LATIN_IME_CORE_SRC_DIR := ../jni/src
+
+LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \
+    -Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls \
+    -Woverloaded-virtual -Wsign-promo -Wno-system-headers
+
+# To suppress compiler warnings for unused variables/functions used for debug features etc.
+LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-function
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+
+include $(LOCAL_PATH)/NativeFileList.mk
+include $(LATIN_IME_CORE_PATH)/NativeFileList.mk
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_DICT_TOOLKIT_SRC_DIR) \
+    $(LATIN_IME_CORE_PATH)/$(LATIN_IME_CORE_SRC_DIR)
+
+LOCAL_SRC_FILES := $(LATIN_IME_DICT_TOOLKIT_MAIN_SRC_FILES) \
+    $(addprefix $(LATIN_IME_DICT_TOOLKIT_SRC_DIR)/, $(LATIN_IME_DICT_TOOLKIT_SRC_FILES)) \
+    $(addprefix $(LATIN_IME_CORE_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
+
+LOCAL_MODULE := dicttoolkit
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CLANG := true
+LOCAL_CXX_STL := libc++
+
+include $(BUILD_HOST_EXECUTABLE)
+#################### Clean up the tmp vars
+include $(LOCAL_PATH)/CleanupNativeFileList.mk
+#################### Unit test
+include $(LOCAL_PATH)/UnitTests.mk
+
+endif # Darwin - TODO: Remove this
+
+endif
+
+endif # TARGET_BUILD_APPS
diff --git a/native/dicttoolkit/CleanupNativeFileList.mk b/native/dicttoolkit/CleanupNativeFileList.mk
new file mode 100644
index 0000000..b804b41
--- /dev/null
+++ b/native/dicttoolkit/CleanupNativeFileList.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2014 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.
+
+LATIN_IME_DICT_TOOLKIT_MAIN_SRC_FILES :=
+LATIN_IME_DICT_TOOLKIT_SRC_FILES :=
+LATIN_IME_DICT_TOOLKIT_TEST_FILES :=
diff --git a/native/dicttoolkit/NativeFileList.mk b/native/dicttoolkit/NativeFileList.mk
new file mode 100644
index 0000000..9a547b0
--- /dev/null
+++ b/native/dicttoolkit/NativeFileList.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2014 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.
+
+LATIN_IME_DICT_TOOLKIT_MAIN_SRC_FILES := \
+    dict_toolkit_main.cpp
+
+LATIN_IME_DICT_TOOLKIT_SRC_FILES := \
+    $(addprefix command_executors/, \
+        diff_executor.cpp \
+        header_executor.cpp \
+        help_executor.cpp \
+        info_executor.cpp \
+        makedict_executor.cpp) \
+    $(addprefix offdevice_intermediate_dict/, \
+        offdevice_intermediate_dict.cpp) \
+    $(addprefix utils/, \
+        arguments_parser.cpp \
+        command_utils.cpp \
+        utf8_utils.cpp)
+
+LATIN_IME_DICT_TOOLKIT_TEST_FILES := \
+    $(addprefix command_executors/, \
+        diff_executor_test.cpp \
+        header_executor_test.cpp \
+        info_executor_test.cpp \
+        makedict_executor_test.cpp) \
+    dict_toolkit_defines_test.cpp \
+    $(addprefix offdevice_intermediate_dict/, \
+        offdevice_intermediate_dict_test.cpp) \
+    $(addprefix utils/, \
+        arguments_parser_test.cpp \
+        command_utils_test.cpp \
+        utf8_utils_test.cpp)
diff --git a/native/dicttoolkit/UnitTests.mk b/native/dicttoolkit/UnitTests.mk
new file mode 100644
index 0000000..96e2873
--- /dev/null
+++ b/native/dicttoolkit/UnitTests.mk
@@ -0,0 +1,69 @@
+# Copyright (C) 2014 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.
+
+ifeq (,$(TARGET_BUILD_APPS))
+
+LOCAL_PATH := $(call my-dir)
+
+######################################
+include $(CLEAR_VARS)
+
+LATIN_IME_CORE_PATH := $(LOCAL_PATH)/../jni
+
+LATIN_IME_DICT_TOOLKIT_SRC_DIR := src
+LATIN_IME_CORE_SRC_DIR := ../jni/src
+LATIN_DICT_TOOLKIT_TEST_SRC_DIR := tests
+
+include $(LOCAL_PATH)/NativeFileList.mk
+include $(LATIN_IME_CORE_PATH)/NativeFileList.mk
+
+# TODO: Remove -std=c++11 once it is set by default on host build.
+LATIN_IME_SRC_DIR := src
+LOCAL_ADDRESS_SANITIZER := true
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_CXX_STL := libc++
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_DICT_TOOLKIT_SRC_DIR) \
+    $(LATIN_IME_CORE_PATH)/$(LATIN_IME_CORE_SRC_DIR)
+LOCAL_MODULE := liblatinime_dicttoolkit_host_static_for_unittests
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := \
+    $(addprefix $(LATIN_IME_DICT_TOOLKIT_SRC_DIR)/, $(LATIN_IME_DICT_TOOLKIT_SRC_FILES)) \
+    $(addprefix $(LATIN_IME_CORE_SRC_DIR)/, $(LATIN_IME_CORE_SRC_FILES))
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+# TODO: Remove -std=c++11 once it is set by default on host build.
+LOCAL_ADDRESS_SANITIZER := true
+LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
+LOCAL_CLANG := true
+LOCAL_CXX_STL := libc++
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_DICT_TOOLKIT_SRC_DIR) \
+    $(LATIN_IME_CORE_PATH)/$(LATIN_IME_CORE_SRC_DIR)
+LOCAL_MODULE := dicttoolkit_unittests
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := \
+    $(addprefix $(LATIN_DICT_TOOLKIT_TEST_SRC_DIR)/, $(LATIN_IME_DICT_TOOLKIT_TEST_FILES))
+LOCAL_STATIC_LIBRARIES += liblatinime_dicttoolkit_host_static_for_unittests
+include $(BUILD_HOST_NATIVE_TEST)
+
+include $(LOCAL_PATH)/CleanupNativeFileList.mk
+
+#################### Clean up the tmp vars
+LATINIME_HOST_OSNAME :=
+LATIN_IME_SRC_DIR :=
+LATIN_IME_TEST_SRC_DIR :=
+
+endif # TARGET_BUILD_APPS
diff --git a/native/dicttoolkit/dict_toolkit_main.cpp b/native/dicttoolkit/dict_toolkit_main.cpp
new file mode 100644
index 0000000..53cc5e9
--- /dev/null
+++ b/native/dicttoolkit/dict_toolkit_main.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <cstdio>
+
+#include "dict_toolkit_defines.h"
+#include "utils/command_utils.h"
+
+void usage(int argc, char **argv) {
+    fprintf(stderr, "Usage: %s <command> [arguments]\n", argc > 0 ? argv[0] : "dicttoolkit");
+}
+
+int main(int argc, char **argv) {
+    if (argc < MIN_ARG_COUNT) {
+        usage(argc, argv);
+        return 1;
+    }
+    using namespace latinime::dicttoolkit;
+    const CommandType commandType = CommandUtils::getCommandType(argv[1]);
+    if (commandType == CommandType::Unknown) {
+        CommandUtils::printCommandUnknownMessage(argv[0], argv[1]);
+        return 1;
+    }
+    const auto executor = CommandUtils::getCommandExecutor(commandType);
+    return executor(argc - 1, argv + 1);
+}
diff --git a/native/dicttoolkit/run_tests.sh b/native/dicttoolkit/run_tests.sh
new file mode 100755
index 0000000..44c99c1
--- /dev/null
+++ b/native/dicttoolkit/run_tests.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# Copyright 2014, 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.
+
+# check script arguments
+if [[ $(type -t mmm) != function ]]; then
+if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
+fi
+
+# Host build is never supported in unbundled (NDK/tapas) build
+if [[ -n $TARGET_BUILD_APPS ]]; then
+  echo "Host build is never supported in tapas build."  1>&2
+  echo "Use lunch command instead."  1>&2
+  if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
+fi
+
+test_name=dicttoolkit_unittests
+
+pushd $PWD > /dev/null
+cd $(gettop)
+(mmm -j16 packages/inputmethods/LatinIME/native/dicttoolkit) || (make -j16 $test_name)
+$ANDROID_HOST_OUT/bin/$test_name
+popd > /dev/null
diff --git a/native/dicttoolkit/src/command_executors/diff_executor.cpp b/native/dicttoolkit/src/command_executors/diff_executor.cpp
new file mode 100644
index 0000000..bf68306
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/diff_executor.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/diff_executor.h"
+
+#include <cstdio>
+
+namespace latinime {
+namespace dicttoolkit {
+
+const char *const DiffExecutor::COMMAND_NAME = "diff";
+
+/* static */ int DiffExecutor::run(const int argc, char **argv) {
+    fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME);
+    return 0;
+}
+
+/* static */ void DiffExecutor::printUsage() {
+    printf("*** %s\n", COMMAND_NAME);
+    getArgumentsParser().printUsage(COMMAND_NAME, "Shows differences between two dictionaries.");
+}
+
+/* static */ const ArgumentsParser DiffExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict1", "dictionary file"),
+        ArgumentSpec::singleArgument("dict2", "dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/diff_executor.h b/native/dicttoolkit/src/command_executors/diff_executor.h
new file mode 100644
index 0000000..f92ae49
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/diff_executor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_DIFF_EXECUTOR_H
+#define LATINIME_DICT_TOOLKIT_DIFF_EXECUTOR_H
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class DiffExecutor final {
+ public:
+    static const char *const COMMAND_NAME;
+
+    static int run(const int argc, char **argv);
+    static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DiffExecutor);
+};
+
+} // namespace dicttoolkit
+} // namepsace latinime
+#endif // LATINIME_DICT_TOOLKIT_DIFF_EXECUTOR_H
diff --git a/native/dicttoolkit/src/command_executors/header_executor.cpp b/native/dicttoolkit/src/command_executors/header_executor.cpp
new file mode 100644
index 0000000..b3d273b
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/header_executor.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/header_executor.h"
+
+#include <cstdio>
+
+namespace latinime {
+namespace dicttoolkit {
+
+const char *const HeaderExecutor::COMMAND_NAME = "header";
+
+/* static */ int HeaderExecutor::run(const int argc, char **argv) {
+    fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME);
+    return 0;
+}
+
+/* static */ void HeaderExecutor::printUsage() {
+    printf("*** %s\n", COMMAND_NAME);
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Prints the header contents of a dictionary file.");
+}
+
+/* static */ const ArgumentsParser HeaderExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict", "prints the header contents of a dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+}
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/header_executor.h b/native/dicttoolkit/src/command_executors/header_executor.h
new file mode 100644
index 0000000..44cc9cf
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/header_executor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_HEADER_EXECUTOR_H
+#define LATINIME_DICT_TOOLKIT_HEADER_EXECUTOR_H
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class HeaderExecutor final {
+ public:
+    static const char *const COMMAND_NAME;
+
+    static int run(const int argc, char **argv);
+    static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderExecutor);
+};
+
+} // namespace dicttoolkit
+} // namepsace latinime
+#endif // LATINIME_DICT_TOOLKIT_HEADER_EXECUTOR_H
diff --git a/native/dicttoolkit/src/command_executors/help_executor.cpp b/native/dicttoolkit/src/command_executors/help_executor.cpp
new file mode 100644
index 0000000..bd29a5b
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/help_executor.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/help_executor.h"
+
+#include <cstdio>
+#include <functional>
+#include <vector>
+
+#include "command_executors/diff_executor.h"
+#include "command_executors/header_executor.h"
+#include "command_executors/info_executor.h"
+#include "command_executors/makedict_executor.h"
+#include "utils/command_utils.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+const char *const HelpExecutor::COMMAND_NAME = "help";
+
+/* static */ int HelpExecutor::run(const int argc, char **argv) {
+    printf("Available commands:\n\n");
+    const std::vector<std::function<void(void)>> printUsageMethods = {DiffExecutor::printUsage,
+            HeaderExecutor::printUsage, InfoExecutor::printUsage, MakedictExecutor::printUsage,
+            printUsage};
+    for (const auto &printUsageMethod : printUsageMethods) {
+        printUsageMethod();
+    }
+    return 0;
+}
+
+/* static */ void HelpExecutor::printUsage() {
+    printf("*** %s\n", COMMAND_NAME);
+    printf("Usage: %s\n", COMMAND_NAME);
+    printf("Show this help list.\n\n");
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/help_executor.h b/native/dicttoolkit/src/command_executors/help_executor.h
new file mode 100644
index 0000000..280610e
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/help_executor.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_HELP_EXECUTOR_H
+#define LATINIME_DICT_TOOLKIT_HELP_EXECUTOR_H
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class HelpExecutor final {
+ public:
+    static const char *const COMMAND_NAME;
+
+    static int run(const int argc, char **argv);
+    static void printUsage();
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(HelpExecutor);
+};
+
+} // namespace dicttoolkit
+} // namepsace latinime
+#endif // LATINIME_DICT_TOOLKIT_HELP_EXECUTOR_H
diff --git a/native/dicttoolkit/src/command_executors/info_executor.cpp b/native/dicttoolkit/src/command_executors/info_executor.cpp
new file mode 100644
index 0000000..351da4a
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/info_executor.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/info_executor.h"
+
+#include <cstdio>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace latinime {
+namespace dicttoolkit {
+
+const char *const InfoExecutor::COMMAND_NAME = "info";
+
+/* static */ int InfoExecutor::run(const int argc, char **argv) {
+    fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME);
+    return 0;
+}
+
+/* static */ void InfoExecutor::printUsage() {
+    printf("*** %s\n", COMMAND_NAME);
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Prints various information about a dictionary file.");
+}
+
+/* static */const ArgumentsParser InfoExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["p"] = OptionSpec::switchOption("(plumbing) produce output suitable for a script");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("dict", "dictionary file name"),
+        ArgumentSpec::variableLengthArguments("word", 0 /* minCount */,
+                ArgumentSpec::UNLIMITED_COUNT, "word to show information")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/info_executor.h b/native/dicttoolkit/src/command_executors/info_executor.h
new file mode 100644
index 0000000..d4106d5
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/info_executor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_INFO_EXECUTOR_H
+#define LATINIME_DICT_TOOLKIT_INFO_EXECUTOR_H
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class InfoExecutor final {
+ public:
+    static const char *const COMMAND_NAME;
+
+    static int run(const int argc, char **argv);
+    static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(InfoExecutor);
+};
+
+} // namepsace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_INFO_EXECUTOR_H
diff --git a/native/dicttoolkit/src/command_executors/makedict_executor.cpp b/native/dicttoolkit/src/command_executors/makedict_executor.cpp
new file mode 100644
index 0000000..4b0a5ae
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/makedict_executor.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/makedict_executor.h"
+
+#include <cstdio>
+
+namespace latinime {
+namespace dicttoolkit {
+
+const char *const MakedictExecutor::COMMAND_NAME = "makedict";
+
+/* static */ int MakedictExecutor::run(const int argc, char **argv) {
+    const ArgumentsAndOptions argumentsAndOptions =
+            getArgumentsParser().parseArguments(argc, argv, true /* printErrorMessages */);
+    if (!argumentsAndOptions.isValid()) {
+        printUsage();
+        return 1;
+    }
+    fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME);
+    return 0;
+}
+
+/* static */ void MakedictExecutor::printUsage() {
+    printf("*** %s\n", COMMAND_NAME);
+    getArgumentsParser().printUsage(COMMAND_NAME,
+            "Converts a source dictionary file to one or several outputs.\n"
+            "Source can be a binary dictionary file or a combined format file.\n"
+            "Binary version 2 (Jelly Bean), 4, and combined format outputs are supported.");
+}
+
+/* static */const ArgumentsParser MakedictExecutor::getArgumentsParser() {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["o"] = OptionSpec::keyValueOption("format", "2",
+            "output format version: 2/4/combined");
+    optionSpecs["t"] = OptionSpec::keyValueOption("mode", "off",
+            "code point table switch: on/off/auto");
+
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("src_dict", "source dictionary file"),
+        ArgumentSpec::singleArgument("dest_dict", "output dictionary file")
+    };
+
+    return ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/command_executors/makedict_executor.h b/native/dicttoolkit/src/command_executors/makedict_executor.h
new file mode 100644
index 0000000..c3de977
--- /dev/null
+++ b/native/dicttoolkit/src/command_executors/makedict_executor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_MAKEDICT_EXECUTOR_H
+#define LATINIME_DICT_TOOLKIT_MAKEDICT_EXECUTOR_H
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_parser.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class MakedictExecutor final {
+ public:
+    static const char *const COMMAND_NAME;
+
+    static int run(const int argc, char **argv);
+    static void printUsage();
+    static const ArgumentsParser getArgumentsParser();
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(MakedictExecutor);
+};
+
+} // namespace dicttoolkit
+} // namepsace latinime
+#endif // LATINIME_DICT_TOOLKIT_MAKEDICT_EXECUTOR_H
diff --git a/native/dicttoolkit/src/dict_toolkit_defines.h b/native/dicttoolkit/src/dict_toolkit_defines.h
new file mode 100644
index 0000000..dbaae0c
--- /dev/null
+++ b/native/dicttoolkit/src/dict_toolkit_defines.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_DEFINES_H
+#define LATINIME_DICT_TOOLKIT_DEFINES_H
+
+#include "defines.h"
+
+#define MIN_ARG_COUNT 2
+
+#endif // LATINIME_DICT_TOOLKIT_DEFINES_H
diff --git a/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.cpp b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.cpp
new file mode 100644
index 0000000..af28131
--- /dev/null
+++ b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict.h"
+
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+bool OffdeviceIntermediateDict::addWord(const WordProperty &wordProperty) {
+    const CodePointArrayView codePoints = wordProperty.getCodePoints();
+    if (codePoints.empty() || codePoints.size() > MAX_WORD_LENGTH) {
+        return false;
+    }
+    return addWordInner(codePoints, wordProperty, mRootPtNodeArray);
+}
+
+bool OffdeviceIntermediateDict::addWordInner(const CodePointArrayView codePoints,
+        const WordProperty &wordProperty, OffdeviceIntermediateDictPtNodeArray &ptNodeArray) {
+    auto ptNodeList = ptNodeArray.getMutablePtNodeList();
+    auto ptNodeIt = ptNodeList->begin();
+    for (; ptNodeIt != ptNodeList->end(); ++ptNodeIt) {
+        const auto &ptNode = *ptNodeIt;
+        const CodePointArrayView ptNodeCodePoints = ptNode->getPtNodeCodePoints();
+        if (codePoints[0] < ptNodeCodePoints[0]) {
+            continue;
+        }
+        if (codePoints[0] > ptNodeCodePoints[0]) {
+            break;
+        }
+        size_t i = 1;
+        for (; i < codePoints.size(); ++i) {
+            if (i >= ptNodeCodePoints.size()) {
+                // Add new child.
+                return addWordInner(codePoints.skip(i), wordProperty,
+                        ptNode->getChildrenPtNodeArray());
+            }
+            if (codePoints[i] != ptNodeCodePoints[i]) {
+                break;
+            }
+        }
+        if (codePoints.size() == i && codePoints.size() == ptNodeCodePoints.size()) {
+            // All code points matched.
+            if (ptNode->getWordProperty()) {
+                //  Adding the same word multiple times is not supported.
+                return false;
+            }
+            ptNodeList->insert(ptNodeIt,
+                    std::make_shared<OffdeviceIntermediateDictPtNode>(wordProperty, *ptNode));
+            ptNodeList->erase(ptNodeIt);
+            return true;
+        }
+        // The (i+1)-th elements are different.
+        // Create and Add new parent ptNode for the common part.
+        auto newPtNode = codePoints.size() == i
+                ? std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints, wordProperty)
+                : std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints.limit(i));
+        ptNodeList->insert(ptNodeIt, newPtNode);
+        OffdeviceIntermediateDictPtNodeArray &childrenPtNodeArray =
+                newPtNode->getChildrenPtNodeArray();
+        // Add new child for the existing ptNode.
+        childrenPtNodeArray.getMutablePtNodeList()->push_back(
+                std::make_shared<OffdeviceIntermediateDictPtNode>(
+                        ptNodeCodePoints.skip(i), *ptNode));
+        ptNodeList->erase(ptNodeIt);
+        if (codePoints.size() != i) {
+            // Add a child for the new word.
+            return addWordInner(codePoints.skip(i), wordProperty, childrenPtNodeArray);
+        }
+        return true;
+    }
+    ptNodeList->insert(ptNodeIt,
+            std::make_shared<OffdeviceIntermediateDictPtNode>(codePoints, wordProperty));
+    return true;
+}
+
+const WordProperty *OffdeviceIntermediateDict::getWordProperty(
+        const CodePointArrayView codePoints) const {
+    const OffdeviceIntermediateDictPtNodeArray *ptNodeArray = &mRootPtNodeArray;
+    for (size_t i = 0; i < codePoints.size();) {
+        bool foundNext = false;
+        for (const auto ptNode : ptNodeArray->getPtNodeList()) {
+            const CodePointArrayView ptNodeCodePoints = ptNode->getPtNodeCodePoints();
+            if (codePoints[i] < ptNodeCodePoints[0]) {
+                continue;
+            }
+            if (codePoints[i] > ptNodeCodePoints[0]
+                     || codePoints.size() < ptNodeCodePoints.size()) {
+                return nullptr;
+            }
+            for (size_t j = 1; j < ptNodeCodePoints.size(); ++j) {
+                if (codePoints[i + j] != ptNodeCodePoints[j]) {
+                    return nullptr;
+                }
+            }
+            i += ptNodeCodePoints.size();
+            if (i == codePoints.size()) {
+                return ptNode->getWordProperty();
+            }
+            ptNodeArray = &ptNode->getChildrenPtNodeArray();
+            foundNext = true;
+            break;
+        }
+        if (!foundNext) {
+            break;
+        }
+    }
+    return nullptr;
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.h b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.h
new file mode 100644
index 0000000..13d26ba
--- /dev/null
+++ b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_H
+#define LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_H
+
+#include "dict_toolkit_defines.h"
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict_header.h"
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node_array.h"
+#include "suggest/core/dictionary/property/word_property.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+/**
+ * On memory patricia trie to represent a dictionary.
+ */
+class OffdeviceIntermediateDict final {
+ public:
+    OffdeviceIntermediateDict(const OffdeviceIntermediateDictHeader &header)
+            : mHeader(header), mRootPtNodeArray() {}
+
+    bool addWord(const WordProperty &wordProperty);
+    // The returned value will be invalid after modifying the dictionary. e.g. calling addWord().
+    const WordProperty *getWordProperty(const CodePointArrayView codePoints) const;
+    const OffdeviceIntermediateDictHeader &getHeader() const { return mHeader; }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(OffdeviceIntermediateDict);
+
+    const OffdeviceIntermediateDictHeader mHeader;
+    OffdeviceIntermediateDictPtNodeArray mRootPtNodeArray;
+
+    bool addWordInner(const CodePointArrayView codePoints, const WordProperty &wordProperty,
+            OffdeviceIntermediateDictPtNodeArray &ptNodeArray);
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_H
diff --git a/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_header.h b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_header.h
new file mode 100644
index 0000000..440627a
--- /dev/null
+++ b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_header.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_HEADER_H
+#define LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_HEADER_H
+
+#include <map>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class OffdeviceIntermediateDictHeader final {
+ public:
+    using AttributeMap = std::map<std::vector<int>, std::vector<int>>;
+
+    OffdeviceIntermediateDictHeader(const AttributeMap &attributesMap)
+            : mAttributeMap(attributesMap) {}
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(OffdeviceIntermediateDictHeader);
+    DISALLOW_ASSIGNMENT_OPERATOR(OffdeviceIntermediateDictHeader);
+
+    const AttributeMap mAttributeMap;
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_HEADER_H
diff --git a/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node.h b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node.h
new file mode 100644
index 0000000..721ccd7
--- /dev/null
+++ b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_H
+#define LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_H
+
+#include <memory>
+
+#include "dict_toolkit_defines.h"
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node_array.h"
+#include "suggest/core/dictionary/property/word_property.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class OffdeviceIntermediateDictPtNode final {
+ public:
+    // Non-terminal
+    OffdeviceIntermediateDictPtNode(const CodePointArrayView ptNodeCodePoints)
+            : mPtNodeCodePoints(ptNodeCodePoints.toVector()), mChildrenPtNodeArray(),
+              mWortProperty(nullptr) {}
+
+    // Terminal
+    OffdeviceIntermediateDictPtNode(const CodePointArrayView ptNodeCodePoints,
+            const WordProperty &wordProperty)
+             : mPtNodeCodePoints(ptNodeCodePoints.toVector()), mChildrenPtNodeArray(),
+               mWortProperty(new WordProperty(wordProperty)) {}
+
+    // Replacing PtNodeCodePoints.
+    OffdeviceIntermediateDictPtNode(const CodePointArrayView ptNodeCodePoints,
+            const OffdeviceIntermediateDictPtNode &ptNode)
+            : mPtNodeCodePoints(ptNodeCodePoints.toVector()),
+              mChildrenPtNodeArray(ptNode.mChildrenPtNodeArray),
+              mWortProperty(new WordProperty(*ptNode.mWortProperty)) {}
+
+    // Replacing WordProperty.
+    OffdeviceIntermediateDictPtNode(const WordProperty &wordProperty,
+            const OffdeviceIntermediateDictPtNode &ptNode)
+            : mPtNodeCodePoints(ptNode.mPtNodeCodePoints),
+              mChildrenPtNodeArray(ptNode.mChildrenPtNodeArray),
+              mWortProperty(new WordProperty(wordProperty)) {}
+
+    const WordProperty *getWordProperty() const {
+        return mWortProperty.get();
+    }
+
+    const CodePointArrayView getPtNodeCodePoints() const {
+        return CodePointArrayView(mPtNodeCodePoints);
+    }
+
+    OffdeviceIntermediateDictPtNodeArray &getChildrenPtNodeArray() {
+        return mChildrenPtNodeArray;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(OffdeviceIntermediateDictPtNode);
+
+    const std::vector<int> mPtNodeCodePoints;
+    OffdeviceIntermediateDictPtNodeArray mChildrenPtNodeArray;
+    const std::unique_ptr<WordProperty> mWortProperty;
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_H
diff --git a/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node_array.h b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node_array.h
new file mode 100644
index 0000000..f87456c
--- /dev/null
+++ b/native/dicttoolkit/src/offdevice_intermediate_dict/offdevice_intermediate_dict_pt_node_array.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_ARRAY_H
+#define LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_ARRAY_H
+
+#include <list>
+#include <memory>
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class OffdeviceIntermediateDictPtNode;
+
+class OffdeviceIntermediateDictPtNodeArray final {
+ public:
+    const std::list<std::shared_ptr<OffdeviceIntermediateDictPtNode>> &getPtNodeList() const {
+        return mPtNodes;
+    }
+
+    std::list<std::shared_ptr<OffdeviceIntermediateDictPtNode>> *getMutablePtNodeList() {
+        return &mPtNodes;
+    }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(OffdeviceIntermediateDictPtNodeArray);
+
+    std::list<std::shared_ptr<OffdeviceIntermediateDictPtNode>> mPtNodes;
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_OFFDEVICE_INTERMEDIATE_DICT_PT_NODE_ARRAY_H
diff --git a/native/dicttoolkit/src/utils/arguments_and_options.h b/native/dicttoolkit/src/utils/arguments_and_options.h
new file mode 100644
index 0000000..2d81b1e
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_and_options.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
+#define LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class ArgumentsAndOptions {
+ public:
+    ArgumentsAndOptions() : mIsValid(false), mOptions(), mArguments() {}
+
+    ArgumentsAndOptions(std::unordered_map<std::string, std::string> &&options,
+            std::unordered_map<std::string, std::vector<std::string>> &&arguments)
+            : mIsValid(true), mOptions(std::move(options)), mArguments(std::move(arguments)) {}
+
+    bool isValid() const {
+        return mIsValid;
+    }
+
+    bool hasOption(const std::string &optionName) const {
+        return mOptions.find(optionName) != mOptions.end();
+    }
+
+    const std::string &getOptionValue(const std::string &optionName) const {
+        const auto &it = mOptions.find(optionName);
+        ASSERT(it != mOptions.end());
+        return it->second;
+    }
+
+    bool hasArgument(const std::string &name) const {
+        const auto &it = mArguments.find(name);
+        return it != mArguments.end() && !it->second.empty();
+    }
+
+    const std::string &getSingleArgument(const std::string &name) const {
+        const auto &it = mArguments.find(name);
+        ASSERT(it != mArguments.end() && !it->second.empty());
+        return it->second.front();
+    }
+
+    const std::vector<std::string> &getVariableLengthArguments(const std::string &name) const {
+        const auto &it = mArguments.find(name);
+        ASSERT(it != mArguments.end());
+        return it->second;
+    }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsAndOptions);
+
+    const bool mIsValid;
+    const std::unordered_map<std::string, std::string> mOptions;
+    const std::unordered_map<std::string, std::vector<std::string>> mArguments;
+};
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_ARGUMENTS_AND_OPTIONS_H
diff --git a/native/dicttoolkit/src/utils/arguments_parser.cpp b/native/dicttoolkit/src/utils/arguments_parser.cpp
new file mode 100644
index 0000000..1451284
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_parser.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/arguments_parser.h"
+
+#include <unordered_set>
+
+namespace latinime {
+namespace dicttoolkit {
+
+const size_t ArgumentSpec::UNLIMITED_COUNT = S_INT_MAX;
+
+bool ArgumentsParser::validateSpecs() const {
+    std::unordered_set<std::string> argumentNameSet;
+    for (size_t i = 0; i < mArgumentSpecs.size() ; ++i) {
+        if (mArgumentSpecs[i].getMinCount() == 0 && mArgumentSpecs[i].getMaxCount() == 0) {
+            AKLOGE("minCount = maxCount = 0 for %s.", mArgumentSpecs[i].getName().c_str());
+            return false;
+        }
+        if (mArgumentSpecs[i].getMinCount() != mArgumentSpecs[i].getMaxCount()
+                && i != mArgumentSpecs.size() - 1) {
+            AKLOGE("Variable length argument must be at the end.",
+                    mArgumentSpecs[i].getName().c_str()v  );
+            return false;
+        }
+        if (argumentNameSet.count(mArgumentSpecs[i].getName()) > 0) {
+            AKLOGE("Multiple arguments have the same name \"%s\".",
+                    mArgumentSpecs[i].getName().c_str());
+            return false;
+        }
+        argumentNameSet.insert(mArgumentSpecs[i].getName());
+    }
+    return true;
+}
+
+void ArgumentsParser::printUsage(const std::string &commandName,
+        const std::string &description) const {
+    printf("Usage: %s", commandName.c_str());
+    for (const auto &option : mOptionSpecs) {
+        const std::string &optionName = option.first;
+        const OptionSpec &spec = option.second;
+        printf(" [-%s", optionName.c_str());
+        if (spec.needsValue()) {
+            printf(" <%s>", spec.getValueName().c_str());
+        }
+        printf("]");
+    }
+    for (const auto &argSpec : mArgumentSpecs) {
+        if (argSpec.getMinCount() == 0 && argSpec.getMaxCount() == 1) {
+            printf(" [<%s>]", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 1 && argSpec.getMaxCount() == 1) {
+            printf(" <%s>", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 0) {
+            printf(" [<%s>...]", argSpec.getName().c_str());
+        } else if (argSpec.getMinCount() == 1) {
+            printf(" <%s>...", argSpec.getName().c_str());
+        }
+    }
+    printf("\n%s\n\n", description.c_str());
+    for (const auto &option : mOptionSpecs) {
+        const std::string &optionName = option.first;
+        const OptionSpec &spec = option.second;
+        printf(" -%s", optionName.c_str());
+        if (spec.needsValue()) {
+            printf(" <%s>", spec.getValueName().c_str());
+        }
+        printf("\t\t\t%s", spec.getDescription().c_str());
+        if (spec.needsValue() && !spec.getDefaultValue().empty()) {
+            printf("\tdefault: %s", spec.getDefaultValue().c_str());
+        }
+        printf("\n");
+    }
+    for (const auto &argSpec : mArgumentSpecs) {
+        printf(" <%s>\t\t\t%s\n", argSpec.getName().c_str(), argSpec.getDescription().c_str());
+    }
+    printf("\n\n");
+}
+
+const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv,
+        const bool printErrorMessage) const {
+    if (argc <= 0) {
+        AKLOGE("Invalid argc (%d).", argc);
+        ASSERT(false);
+        return ArgumentsAndOptions();
+    }
+    std::unordered_map<std::string, std::string> options;
+    for (const auto &entry : mOptionSpecs) {
+        const std::string &optionName = entry.first;
+        const OptionSpec &optionSpec = entry.second;
+        if (optionSpec.needsValue() && !optionSpec.getDefaultValue().empty()) {
+            // Set default value.
+            options[optionName] = optionSpec.getDefaultValue();
+        }
+    }
+    std::unordered_map<std::string, std::vector<std::string>> arguments;
+    auto argumentSpecIt = mArgumentSpecs.cbegin();
+    for (int i = 1; i < argc; ++i) {
+        const std::string arg = argv[i];
+        if (arg.length() > 1 && arg[0] == '-') {
+            // option
+            const std::string optionName = arg.substr(1);
+            const auto it = mOptionSpecs.find(optionName);
+            if (it == mOptionSpecs.end()) {
+                if (printErrorMessage) {
+                    fprintf(stderr, "Unknown option: '%s'\n", optionName.c_str());
+                }
+                return ArgumentsAndOptions();
+            }
+            std::string optionValue;
+            if (it->second.needsValue()) {
+                ++i;
+                if (i >= argc) {
+                    if (printErrorMessage) {
+                        fprintf(stderr, "Missing argument for option '%s'\n", optionName.c_str());
+                    }
+                    return ArgumentsAndOptions();
+                }
+                optionValue = argv[i];
+            }
+            options[optionName] = optionValue;
+        } else {
+            // argument
+            if (argumentSpecIt == mArgumentSpecs.end()) {
+                if (printErrorMessage) {
+                    fprintf(stderr, "Too many arguments.\n");
+                }
+                return ArgumentsAndOptions();
+            }
+            arguments[argumentSpecIt->getName()].push_back(arg);
+            if (arguments[argumentSpecIt->getName()].size() >= argumentSpecIt->getMaxCount()) {
+                ++argumentSpecIt;
+            }
+        }
+    }
+
+    if (argumentSpecIt != mArgumentSpecs.end()) {
+        const auto &it = arguments.find(argumentSpecIt->getName());
+        const size_t minCount = argumentSpecIt->getMinCount();
+        const size_t actualcount = it == arguments.end() ? 0 : it->second.size();
+        if (minCount > actualcount) {
+            if (printErrorMessage) {
+                fprintf(stderr, "Not enough arguments. %zd argumant(s) required for <%s>\n",
+                        minCount, argumentSpecIt->getName().c_str());
+            }
+            return ArgumentsAndOptions();
+        }
+    }
+    return ArgumentsAndOptions(std::move(options), std::move(arguments));
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/utils/arguments_parser.h b/native/dicttoolkit/src/utils/arguments_parser.h
new file mode 100644
index 0000000..32bd328
--- /dev/null
+++ b/native/dicttoolkit/src/utils/arguments_parser.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
+#define LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+#include "utils/arguments_and_options.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class OptionSpec {
+ public:
+    // Default constructor and assignment operator is enabled to be used with std::unordered_map.
+    OptionSpec() = default;
+    OptionSpec &operator=(const OptionSpec &) = default;
+
+    static OptionSpec keyValueOption(const std::string &valueName, const std::string &defaultValue,
+            const std::string &description) {
+        return OptionSpec(true /* needsValue */, valueName, defaultValue, description);
+    }
+
+    static OptionSpec switchOption(const std::string &description) {
+        return OptionSpec(false /* needsValue */, "" /* valueName */, "" /* defaultValue */,
+                description);
+    }
+
+    bool needsValue() const { return mNeedsValue; }
+    const std::string &getValueName() const { return mValueName; }
+    const std::string &getDefaultValue() const { return mDefaultValue; }
+    const std::string &getDescription() const { return mDescription; }
+
+ private:
+    OptionSpec(const bool needsValue, const std::string &valueName, const std::string &defaultValue,
+            const std::string &description)
+            : mNeedsValue(needsValue), mValueName(valueName), mDefaultValue(defaultValue),
+              mDescription(description) {}
+
+    // Whether the option have to be used with a value or just a switch.
+    // e.g. 'f' in "command -f /path/to/file" is mNeedsValue == true.
+    //      'f' in "command -f -t" is mNeedsValue == false.
+    bool mNeedsValue;
+    // Name of the value used to show usage.
+    std::string mValueName;
+    std::string mDefaultValue;
+    std::string mDescription;
+};
+
+class ArgumentSpec {
+ public:
+    static const size_t UNLIMITED_COUNT;
+
+    static ArgumentSpec singleArgument(const std::string &name, const std::string &description) {
+        return ArgumentSpec(name, 1 /* minCount */, 1 /* maxCount */, description);
+    }
+
+    static ArgumentSpec variableLengthArguments(const std::string &name, const size_t minCount,
+            const size_t maxCount, const std::string &description) {
+        return ArgumentSpec(name, minCount, maxCount, description);
+    }
+
+    const std::string &getName() const { return mName; }
+    size_t getMinCount() const { return mMinCount; }
+    size_t getMaxCount() const { return mMaxCount; }
+    const std::string &getDescription() const { return mDescription; }
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentSpec);
+
+    ArgumentSpec(const std::string &name, const size_t minCount, const size_t maxCount,
+            const std::string &description)
+            : mName(name), mMinCount(minCount), mMaxCount(maxCount), mDescription(description) {}
+
+    const std::string mName;
+    const size_t mMinCount;
+    const size_t mMaxCount;
+    const std::string mDescription;
+};
+
+class ArgumentsParser {
+ public:
+    ArgumentsParser(const std::unordered_map<std::string, OptionSpec> &&optionSpecs,
+            const std::vector<ArgumentSpec> &&argumentSpecs)
+            : mOptionSpecs(std::move(optionSpecs)), mArgumentSpecs(std::move(argumentSpecs)) {}
+
+    const ArgumentsAndOptions parseArguments(const int argc, char **argv,
+            const bool printErrorMessage) const;
+    bool validateSpecs() const;
+    void printUsage(const std::string &commandName, const std::string &description) const;
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentsParser);
+    DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsParser);
+
+    const std::unordered_map<std::string, OptionSpec> mOptionSpecs;
+    const std::vector<ArgumentSpec> mArgumentSpecs;
+};
+
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_ARGUMENTS_PARSER_H
diff --git a/native/dicttoolkit/src/utils/command_utils.cpp b/native/dicttoolkit/src/utils/command_utils.cpp
new file mode 100644
index 0000000..3419642
--- /dev/null
+++ b/native/dicttoolkit/src/utils/command_utils.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/command_utils.h"
+
+#include <cstdio>
+
+#include "command_executors/diff_executor.h"
+#include "command_executors/header_executor.h"
+#include "command_executors/help_executor.h"
+#include "command_executors/info_executor.h"
+#include "command_executors/makedict_executor.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+/* static */ CommandType CommandUtils::getCommandType(const std::string &commandName) {
+    if (commandName == InfoExecutor::COMMAND_NAME) {
+        return CommandType::Info;
+    } else if (commandName == DiffExecutor::COMMAND_NAME) {
+        return CommandType::Diff;
+    } else if (commandName == MakedictExecutor::COMMAND_NAME) {
+        return CommandType::Makedict;
+    } else if (commandName == HeaderExecutor::COMMAND_NAME) {
+        return CommandType::Header;
+    } else if (commandName == HelpExecutor::COMMAND_NAME) {
+        return CommandType::Help;
+    } else {
+        return CommandType::Unknown;
+    }
+}
+
+/* static */ void CommandUtils::printCommandUnknownMessage(const std::string &programName,
+        const std::string &commandName) {
+    fprintf(stderr, "Command '%s' is unknown. Try '%s %s' for more information.\n",
+            commandName.c_str(), programName.c_str(), HelpExecutor::COMMAND_NAME);
+}
+
+/* static */ std::function<int(int, char **)> CommandUtils::getCommandExecutor(
+        const CommandType commandType) {
+    switch (commandType) {
+        case CommandType::Info:
+            return InfoExecutor::run;
+        case CommandType::Diff:
+            return DiffExecutor::run;
+        case CommandType::Makedict:
+            return MakedictExecutor::run;
+        case CommandType::Header:
+            return HeaderExecutor::run;
+        case CommandType::Help:
+            return HelpExecutor::run;
+        default:
+            return [] (int, char **) -> int {
+                printf("Command executor not found.");
+                return 1;
+            };
+    }
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/utils/command_utils.h b/native/dicttoolkit/src/utils/command_utils.h
new file mode 100644
index 0000000..4a181f1
--- /dev/null
+++ b/native/dicttoolkit/src/utils/command_utils.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_COMMAND_UTILS_H
+#define LATINIME_DICT_TOOLKIT_COMMAND_UTILS_H
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "dict_toolkit_defines.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+enum class CommandType : int {
+    Info,
+    Diff,
+    Makedict,
+    Header,
+    Help,
+    Unknown
+};
+
+class CommandUtils {
+public:
+    static CommandType getCommandType(const std::string &commandName);
+    static void printCommandUnknownMessage(const std::string &programName,
+            const std::string &commandName);
+    static std::function<int(int, char **)> getCommandExecutor(const CommandType commandType);
+
+private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(CommandUtils);
+};
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_COMMAND_UTILS_H
diff --git a/native/dicttoolkit/src/utils/utf8_utils.cpp b/native/dicttoolkit/src/utils/utf8_utils.cpp
new file mode 100644
index 0000000..0f349f5
--- /dev/null
+++ b/native/dicttoolkit/src/utils/utf8_utils.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/utf8_utils.h"
+
+#include "utils/char_utils.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+const size_t Utf8Utils::MAX_SEQUENCE_SIZE_FOR_A_CODE_POINT = 4;
+const uint8_t Utf8Utils::FIRST_BYTE_MARKER_MASKS[] = {0, 0x80, 0xE0, 0xF0, 0xF8};
+const uint8_t Utf8Utils::FIRST_BYTE_MARKERS[] = {0, 0x00, 0xC0, 0xE0, 0xF0};
+const uint8_t Utf8Utils::FIRST_BYTE_CODE_POINT_BITS_MASKS[] = {0, 0x7F, 0x1F, 0x0F, 0x03};
+const int Utf8Utils::MAX_ENCODED_CODE_POINT_VALUES[] = {-1, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
+
+const uint8_t Utf8Utils::TRAILING_BYTE_CODE_POINT_BITS_MASK = 0x3F;
+const uint8_t Utf8Utils::TRAILING_BYTE_MARKER = 0x80;
+const size_t Utf8Utils::CODE_POINT_BIT_COUNT_IN_TRAILING_BYTE = 6;
+
+/* static */ std::vector<int> Utf8Utils::getCodePoints(const std::string &utf8Str) {
+    std::vector<int> codePoints;
+    int remainingByteCountForCurrentCodePoint = 0;
+    int currentCodePointSequenceSize = 0;
+    int codePoint = 0;
+    for (const char c : utf8Str) {
+        if (remainingByteCountForCurrentCodePoint == 0) {
+            currentCodePointSequenceSize = getSequenceSizeByCheckingFirstByte(c);
+            if (currentCodePointSequenceSize <= 0) {
+                AKLOGE("%x is an invalid utf8 first byte value.", c);
+                return std::vector<int>();
+            }
+            remainingByteCountForCurrentCodePoint = currentCodePointSequenceSize;
+            codePoint = maskFirstByte(c, remainingByteCountForCurrentCodePoint);
+        } else {
+            codePoint <<= CODE_POINT_BIT_COUNT_IN_TRAILING_BYTE;
+            codePoint += maskTrailingByte(c);
+        }
+        remainingByteCountForCurrentCodePoint--;
+        if (remainingByteCountForCurrentCodePoint == 0) {
+            if (codePoint <= MAX_ENCODED_CODE_POINT_VALUES[currentCodePointSequenceSize - 1]) {
+                AKLOGE("%d bytes encode for codePoint(%x) is a redundant UTF-8 sequence.",
+                        currentCodePointSequenceSize,  codePoint);
+                return std::vector<int>();
+            }
+            codePoints.push_back(codePoint);
+        }
+    }
+    return codePoints;
+}
+
+/* static */ int Utf8Utils::getSequenceSizeByCheckingFirstByte(const uint8_t firstByte) {
+    for (size_t i = 1; i <= MAX_SEQUENCE_SIZE_FOR_A_CODE_POINT; ++i) {
+        if ((firstByte & FIRST_BYTE_MARKER_MASKS[i]) == FIRST_BYTE_MARKERS[i]) {
+            return i;
+        }
+    }
+    // Not a valid utf8 char first byte.
+    return -1;
+}
+
+/* static */ AK_FORCE_INLINE int Utf8Utils::maskFirstByte(const uint8_t firstByte,
+        const int sequenceSize) {
+    return firstByte & FIRST_BYTE_CODE_POINT_BITS_MASKS[sequenceSize];
+}
+
+/* static */ AK_FORCE_INLINE int Utf8Utils::maskTrailingByte(const uint8_t secondOrLaterByte) {
+    return secondOrLaterByte & TRAILING_BYTE_CODE_POINT_BITS_MASK;
+}
+
+/* static */ std::string Utf8Utils::getUtf8String(const CodePointArrayView codePoints) {
+    std::string utf8String;
+    for (const int codePoint : codePoints) {
+        const int sequenceSize = getSequenceSizeToEncodeCodePoint(codePoint);
+        if (sequenceSize <= 0) {
+            AKLOGE("Cannot encode code point (%d).", codePoint);
+            return std::string();
+        }
+        const int trailingByteCount = sequenceSize - 1;
+        // Output first byte.
+        const int value = codePoint >> (trailingByteCount * CODE_POINT_BIT_COUNT_IN_TRAILING_BYTE);
+        utf8String.push_back(static_cast<char>(value | FIRST_BYTE_MARKERS[sequenceSize]));
+        // Output second and later bytes.
+        for (int i = 1; i < sequenceSize; ++i) {
+            const int shiftAmount = (trailingByteCount - i) * CODE_POINT_BIT_COUNT_IN_TRAILING_BYTE;
+            const int value = (codePoint >> shiftAmount) & TRAILING_BYTE_CODE_POINT_BITS_MASK;
+            utf8String.push_back(static_cast<char>(value | TRAILING_BYTE_MARKER));
+        }
+    }
+    return utf8String;
+}
+
+/* static */ int Utf8Utils::getSequenceSizeToEncodeCodePoint(const int codePoint) {
+    if (codePoint < 0) {
+        return -1;
+    }
+    for (size_t i = 1; i <= MAX_SEQUENCE_SIZE_FOR_A_CODE_POINT; ++i) {
+        if (codePoint <= MAX_ENCODED_CODE_POINT_VALUES[i]) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/src/utils/utf8_utils.h b/native/dicttoolkit/src/utils/utf8_utils.h
new file mode 100644
index 0000000..35818e5
--- /dev/null
+++ b/native/dicttoolkit/src/utils/utf8_utils.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_DICT_TOOLKIT_UTF8_UTILS_H
+#define LATINIME_DICT_TOOLKIT_UTF8_UTILS_H
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "dict_toolkit_defines.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace dicttoolkit {
+
+class Utf8Utils {
+public:
+    static std::vector<int> getCodePoints(const std::string &utf8Str);
+    static std::string getUtf8String(const CodePointArrayView codePoints);
+
+private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8Utils);
+
+    // Values indexed by sequence size.
+    static const size_t MAX_SEQUENCE_SIZE_FOR_A_CODE_POINT;
+    static const uint8_t FIRST_BYTE_MARKER_MASKS[];
+    static const uint8_t FIRST_BYTE_MARKERS[];
+    static const uint8_t FIRST_BYTE_CODE_POINT_BITS_MASKS[];
+    static const int MAX_ENCODED_CODE_POINT_VALUES[];
+
+    static const uint8_t TRAILING_BYTE_CODE_POINT_BITS_MASK;
+    static const uint8_t TRAILING_BYTE_MARKER;
+    static const size_t CODE_POINT_BIT_COUNT_IN_TRAILING_BYTE;
+
+    static int getSequenceSizeByCheckingFirstByte(const uint8_t firstByte);
+    static int maskFirstByte(const uint8_t firstByte, const int encodeSize);
+    static int maskTrailingByte(const uint8_t secondOrLaterByte);
+    static int getSequenceSizeToEncodeCodePoint(const int codePoint);
+};
+} // namespace dicttoolkit
+} // namespace latinime
+#endif // LATINIME_DICT_TOOLKIT_UTF8_UTILS_H
diff --git a/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp b/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp
new file mode 100644
index 0000000..4441414
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/diff_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/diff_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(DiffExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(DiffExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/header_executor_test.cpp b/native/dicttoolkit/tests/command_executors/header_executor_test.cpp
new file mode 100644
index 0000000..a94150b
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/header_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/header_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(HeaderExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(HeaderExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/info_executor_test.cpp b/native/dicttoolkit/tests/command_executors/info_executor_test.cpp
new file mode 100644
index 0000000..debe8c6
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/info_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/info_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(InfoExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(InfoExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp b/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp
new file mode 100644
index 0000000..44eb3dc
--- /dev/null
+++ b/native/dicttoolkit/tests/command_executors/makedict_executor_test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "command_executors/makedict_executor.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(MakedictExecutorTests, TestArguemntSpecs) {
+    EXPECT_TRUE(MakedictExecutor::getArgumentsParser().validateSpecs());
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/dict_toolkit_defines_test.cpp b/native/dicttoolkit/tests/dict_toolkit_defines_test.cpp
new file mode 100644
index 0000000..3445bd0
--- /dev/null
+++ b/native/dicttoolkit/tests/dict_toolkit_defines_test.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dict_toolkit_defines.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+// Initial trivial test case.
+TEST(DictToolkitDefinesTest, TestKeycodeSpace) {
+    EXPECT_EQ(' ', KEYCODE_SPACE);
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/offdevice_intermediate_dict/offdevice_intermediate_dict_test.cpp b/native/dicttoolkit/tests/offdevice_intermediate_dict/offdevice_intermediate_dict_test.cpp
new file mode 100644
index 0000000..f2e24ab
--- /dev/null
+++ b/native/dicttoolkit/tests/offdevice_intermediate_dict/offdevice_intermediate_dict_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "offdevice_intermediate_dict/offdevice_intermediate_dict.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "suggest/core/dictionary/property/word_property.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+const std::vector<int> getCodePointVector(const char *str) {
+    std::vector<int> codePoints;
+    while (*str) {
+        codePoints.push_back(*str);
+        ++str;
+    }
+    return codePoints;
+}
+
+const WordProperty getDummpWordProperty(const std::vector<int> &&codePoints) {
+    return WordProperty(std::move(codePoints), UnigramProperty(), std::vector<NgramProperty>());
+}
+
+TEST(OffdeviceIntermediateDictTest, TestAddWordProperties) {
+    OffdeviceIntermediateDict dict = OffdeviceIntermediateDict(
+            OffdeviceIntermediateDictHeader(OffdeviceIntermediateDictHeader::AttributeMap()));
+    EXPECT_EQ(nullptr, dict.getWordProperty(CodePointArrayView()));
+
+    const WordProperty wordProperty0 = getDummpWordProperty(getCodePointVector("abcd"));
+    EXPECT_TRUE(dict.addWord(wordProperty0));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty0.getCodePoints()));
+
+    const WordProperty wordProperty1 = getDummpWordProperty(getCodePointVector("efgh"));
+    EXPECT_TRUE(dict.addWord(wordProperty1));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty1.getCodePoints()));
+
+    const WordProperty wordProperty2 = getDummpWordProperty(getCodePointVector("ab"));
+    EXPECT_TRUE(dict.addWord(wordProperty2));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty2.getCodePoints()));
+
+    const WordProperty wordProperty3 = getDummpWordProperty(getCodePointVector("abcdefg"));
+    EXPECT_TRUE(dict.addWord(wordProperty3));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty3.getCodePoints()));
+
+    const WordProperty wordProperty4 = getDummpWordProperty(getCodePointVector("efef"));
+    EXPECT_TRUE(dict.addWord(wordProperty4));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty4.getCodePoints()));
+
+    const WordProperty wordProperty5 = getDummpWordProperty(getCodePointVector("ef"));
+    EXPECT_TRUE(dict.addWord(wordProperty5));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty5.getCodePoints()));
+
+    const WordProperty wordProperty6 = getDummpWordProperty(getCodePointVector("abcd"));
+    EXPECT_FALSE(dict.addWord(wordProperty6)) << "Adding the same word multiple times should fail.";
+
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty0.getCodePoints()));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty1.getCodePoints()));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty2.getCodePoints()));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty3.getCodePoints()));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty4.getCodePoints()));
+    EXPECT_NE(nullptr, dict.getWordProperty(wordProperty5.getCodePoints()));
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/utils/arguments_parser_test.cpp b/native/dicttoolkit/tests/utils/arguments_parser_test.cpp
new file mode 100644
index 0000000..58b4998
--- /dev/null
+++ b/native/dicttoolkit/tests/utils/arguments_parser_test.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/arguments_parser.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(ArgumentsParserTests, TestValitadeSpecs) {
+    {
+        std::unordered_map<std::string, OptionSpec> optionSpecs;
+        std::vector<ArgumentSpec> argumentSpecs;
+        EXPECT_TRUE(
+                ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs)).validateSpecs());
+    }
+    {
+        std::unordered_map<std::string, OptionSpec> optionSpecs;
+        optionSpecs["a"] = OptionSpec::keyValueOption("valueName", "default", "description");
+        const std::vector<ArgumentSpec> argumentSpecs = {
+            ArgumentSpec::singleArgument("name", "description"),
+            ArgumentSpec::variableLengthArguments("name2", 0 /* minCount */,  1 /* maxCount */,
+                    "description2")
+        };
+        EXPECT_TRUE(
+                ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs)).validateSpecs());
+    }
+    {
+        const std::vector<ArgumentSpec> argumentSpecs = {
+            ArgumentSpec::variableLengthArguments("name", 0 /* minCount */,  0 /* maxCount */,
+                    "description")
+        };
+        EXPECT_FALSE(ArgumentsParser(std::unordered_map<std::string, OptionSpec>(),
+                std::move(argumentSpecs)).validateSpecs());
+    }
+    {
+        const std::vector<ArgumentSpec> argumentSpecs = {
+            ArgumentSpec::singleArgument("name", "description"),
+            ArgumentSpec::variableLengthArguments("name", 0 /* minCount */,  1 /* maxCount */,
+                    "description")
+        };
+        EXPECT_FALSE(ArgumentsParser(std::unordered_map<std::string, OptionSpec>(),
+                std::move(argumentSpecs)).validateSpecs());
+    }
+    {
+        const std::vector<ArgumentSpec> argumentSpecs = {
+            ArgumentSpec::variableLengthArguments("name", 0 /* minCount */,  1 /* maxCount */,
+                    "description"),
+            ArgumentSpec::singleArgument("name2", "description2")
+        };
+        EXPECT_FALSE(ArgumentsParser(std::unordered_map<std::string, OptionSpec>(),
+                std::move(argumentSpecs)).validateSpecs());
+    }
+}
+
+int initArgv(char *mutableCommandLine, char **argv) {
+    bool readingSeparator = false;
+    int argc = 1;
+    argv[0] = mutableCommandLine;
+    const size_t length = strlen(mutableCommandLine);
+    for (size_t i = 0; i < length; ++i) {
+        if (mutableCommandLine[i] != ' ' && readingSeparator) {
+            readingSeparator = false;
+            argv[argc] = mutableCommandLine + i;
+            ++argc;
+        } else if (mutableCommandLine[i] == ' ' && !readingSeparator) {
+            readingSeparator = true;
+            mutableCommandLine[i] = '\0';
+        }
+    }
+    argv[argc] = nullptr;
+    return argc;
+}
+
+TEST(ArgumentsParserTests, TestParseArguments) {
+    std::unordered_map<std::string, OptionSpec> optionSpecs;
+    optionSpecs["a"] = OptionSpec::switchOption("description");
+    optionSpecs["b"] = OptionSpec::keyValueOption("valueName", "default", "description");
+    const std::vector<ArgumentSpec> argumentSpecs = {
+        ArgumentSpec::singleArgument("arg0", "description"),
+        ArgumentSpec::variableLengthArguments("arg1", 0 /* minCount */,  2 /* maxCount */,
+                "description"),
+    };
+    const ArgumentsParser parser =
+            ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs));
+
+    {
+        char kMutableCommandLine[1024] = "command arg";
+        char *argv[128] = {};
+        const int argc = initArgv(kMutableCommandLine, argv);
+        ASSERT_EQ(2, argc);
+        const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments(
+                argc, argv, false /* printErrorMessages */);
+        EXPECT_FALSE(argumentsAndOptions.hasOption("a"));
+        EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b"));
+        EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0"));
+        EXPECT_FALSE(argumentsAndOptions.hasArgument("arg1"));
+    }
+    {
+        char kArgumentBuffer[1024] = "command -a arg arg";
+        char *argv[128] = {};
+        const int argc = initArgv(kArgumentBuffer, argv);
+        ASSERT_EQ(4, argc);
+        const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments(
+                argc, argv, false /* printErrorMessages */);
+        EXPECT_TRUE(argumentsAndOptions.hasOption("a"));
+        EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b"));
+        EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0"));
+        EXPECT_TRUE(argumentsAndOptions.hasArgument("arg1"));
+        EXPECT_EQ(1u, argumentsAndOptions.getVariableLengthArguments("arg1").size());
+    }
+    {
+        char kArgumentBuffer[1024] = "command -b value arg arg1 arg2";
+        char *argv[128] = {};
+        const int argc = initArgv(kArgumentBuffer, argv);
+        ASSERT_EQ(6, argc);
+        const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments(
+                argc, argv, false /* printErrorMessages */);
+        EXPECT_FALSE(argumentsAndOptions.hasOption("a"));
+        EXPECT_EQ("value", argumentsAndOptions.getOptionValue("b"));
+        EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0"));
+        const std::vector<std::string> &arg1 =
+                argumentsAndOptions.getVariableLengthArguments("arg1");
+        EXPECT_EQ(2u, arg1.size());
+        EXPECT_EQ("arg1", arg1[0]);
+        EXPECT_EQ("arg2", arg1[1]);
+    }
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/utils/command_utils_test.cpp b/native/dicttoolkit/tests/utils/command_utils_test.cpp
new file mode 100644
index 0000000..9d79c9d
--- /dev/null
+++ b/native/dicttoolkit/tests/utils/command_utils_test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/command_utils.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(CommandUtilsTests, TestGetCommandType) {
+    EXPECT_EQ(CommandUtils::getCommandType(""), CommandType::Unknown);
+    EXPECT_EQ(CommandUtils::getCommandType("abc"), CommandType::Unknown);
+    EXPECT_EQ(CommandUtils::getCommandType("info"), CommandType::Info);
+    EXPECT_EQ(CommandUtils::getCommandType("diff"), CommandType::Diff);
+    EXPECT_EQ(CommandUtils::getCommandType("makedict"), CommandType::Makedict);
+    EXPECT_EQ(CommandUtils::getCommandType("header"), CommandType::Header);
+    EXPECT_EQ(CommandUtils::getCommandType("help"), CommandType::Help);
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/dicttoolkit/tests/utils/utf8_utils_test.cpp b/native/dicttoolkit/tests/utils/utf8_utils_test.cpp
new file mode 100644
index 0000000..9c59a8b
--- /dev/null
+++ b/native/dicttoolkit/tests/utils/utf8_utils_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/utf8_utils.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace dicttoolkit {
+namespace {
+
+TEST(Utf8UtilsTests, TestGetCodePoints) {
+    {
+        const std::vector<int> codePoints = Utf8Utils::getCodePoints("");
+        EXPECT_EQ(0u, codePoints.size());
+    }
+    {
+        const std::vector<int> codePoints = Utf8Utils::getCodePoints("test");
+        EXPECT_EQ(4u, codePoints.size());
+        EXPECT_EQ('t', codePoints[0]);
+        EXPECT_EQ('e', codePoints[1]);
+        EXPECT_EQ('s', codePoints[2]);
+        EXPECT_EQ('t', codePoints[3]);
+    }
+    {
+        const std::vector<int> codePoints = Utf8Utils::getCodePoints(u8"\u3042a\u03C2\u0410");
+        EXPECT_EQ(4u, codePoints.size());
+        EXPECT_EQ(0x3042, codePoints[0]); // HIRAGANA LETTER A
+        EXPECT_EQ('a', codePoints[1]);
+        EXPECT_EQ(0x03C2, codePoints[2]); // CYRILLIC CAPITAL LETTER A
+        EXPECT_EQ(0x0410, codePoints[3]); // GREEK SMALL LETTER FINAL SIGMA
+    }
+    {
+        const std::vector<int> codePoints = Utf8Utils::getCodePoints(u8"\U0001F36A?\U0001F752");
+        EXPECT_EQ(3u, codePoints.size());
+        EXPECT_EQ(0x1F36A, codePoints[0]); // COOKIE
+        EXPECT_EQ('?', codePoints[1]);
+        EXPECT_EQ(0x1F752, codePoints[2]); // ALCHEMICAL SYMBOL FOR STARRED TRIDENT
+    }
+
+    // Redundant UTF-8 sequences must be rejected.
+    EXPECT_TRUE(Utf8Utils::getCodePoints("\xC0\xAF").empty());
+    EXPECT_TRUE(Utf8Utils::getCodePoints("\xE0\x80\xAF").empty());
+    EXPECT_TRUE(Utf8Utils::getCodePoints("\xF0\x80\x80\xAF").empty());
+}
+
+TEST(Utf8UtilsTests, TestGetUtf8String) {
+    {
+        const std::vector<int> codePoints = {'t', 'e', 's', 't'};
+        EXPECT_EQ("test", Utf8Utils::getUtf8String(CodePointArrayView(codePoints)));
+    }
+    {
+        const std::vector<int> codePoints = {
+                0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
+                0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */,
+                0x0430 /* CYRILLIC SMALL LETTER A */,
+                0x3042 /* HIRAGANA LETTER A */,
+                0x1F36A /* COOKIE */,
+                0x1F752 /* ALCHEMICAL SYMBOL FOR STARRED TRIDENT */
+        };
+        EXPECT_EQ(u8"\u00E0\u03C2\u0430\u3042\U0001F36A\U0001F752",
+                Utf8Utils::getUtf8String(CodePointArrayView(codePoints)));
+    }
+}
+
+} // namespace
+} // namespace dicttoolkit
+} // namespace latinime
diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index 3a2073f..6003a6f 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -48,7 +48,7 @@
 
 ifeq ($(FLAG_DO_PROFILE), true)
     $(warning Making profiling version of native library)
-    LOCAL_CFLAGS += -DFLAG_DO_PROFILE -funwind-tables -fno-inline
+    LOCAL_CFLAGS += -DFLAG_DO_PROFILE -funwind-tables
 else # FLAG_DO_PROFILE
 ifeq ($(FLAG_DBG), true)
     $(warning Making debug version of native library)
diff --git a/native/jni/HostUnitTests.mk b/native/jni/HostUnitTests.mk
index 6967d9b..e30d50a 100644
--- a/native/jni/HostUnitTests.mk
+++ b/native/jni/HostUnitTests.mk
@@ -12,6 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Host build is never supported in unbundled (NDK/tapas) build
+ifeq (,$(TARGET_BUILD_APPS))
+
 # HACK: Temporarily disable host tool build on Mac until the build system is ready for C++11.
 LATINIME_HOST_OSNAME := $(shell uname -s)
 ifneq ($(LATINIME_HOST_OSNAME), Darwin) # TODO: Remove this
@@ -26,8 +29,10 @@
 #################### Host library for unit test
 # TODO: Remove -std=c++11 once it is set by default on host build.
 LATIN_IME_SRC_DIR := src
+LOCAL_ADDRESS_SANITIZER := true
 LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
 LOCAL_CLANG := true
+LOCAL_CXX_STL := libc++
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
 LOCAL_MODULE := liblatinime_host_static_for_unittests
 LOCAL_MODULE_TAGS := optional
@@ -37,9 +42,11 @@
 #################### Host native tests
 include $(CLEAR_VARS)
 LATIN_IME_TEST_SRC_DIR := tests
+LOCAL_ADDRESS_SANITIZER := true
 # TODO: Remove -std=c++11 once it is set by default on host build.
 LOCAL_CFLAGS += -std=c++11 -Wno-unused-parameter -Wno-unused-function
 LOCAL_CLANG := true
+LOCAL_CXX_STL := libc++
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(LATIN_IME_SRC_DIR)
 LOCAL_MODULE := liblatinime_host_unittests
 LOCAL_MODULE_TAGS := tests
@@ -47,10 +54,13 @@
 LOCAL_STATIC_LIBRARIES += liblatinime_host_static_for_unittests
 include $(BUILD_HOST_NATIVE_TEST)
 
+include $(LOCAL_PATH)/CleanupNativeFileList.mk
+
 endif # Darwin - TODO: Remove this
 
+endif # TARGET_BUILD_APPS
+
 #################### Clean up the tmp vars
 LATINIME_HOST_OSNAME :=
 LATIN_IME_SRC_DIR :=
 LATIN_IME_TEST_SRC_DIR :=
-include $(LOCAL_PATH)/CleanupNativeFileList.mk
diff --git a/native/jni/NativeFileList.mk b/native/jni/NativeFileList.mk
index 7a732a5..d8b69bf 100644
--- a/native/jni/NativeFileList.mk
+++ b/native/jni/NativeFileList.mk
@@ -20,6 +20,52 @@
     jni_common.cpp
 
 LATIN_IME_CORE_SRC_FILES := \
+    $(addprefix dictionary/header/, \
+        header_policy.cpp \
+        header_read_write_utils.cpp) \
+    dictionary/property/ngram_context.cpp \
+    dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp \
+    $(addprefix dictionary/structure/pt_common/, \
+        bigram/bigram_list_read_write_utils.cpp \
+        dynamic_pt_gc_event_listeners.cpp \
+        dynamic_pt_reading_helper.cpp \
+        dynamic_pt_reading_utils.cpp \
+        dynamic_pt_updating_helper.cpp \
+        dynamic_pt_writing_utils.cpp \
+        patricia_trie_reading_utils.cpp \
+        shortcut/shortcut_list_reading_utils.cpp) \
+    $(addprefix dictionary/structure/v2/, \
+        patricia_trie_policy.cpp \
+        ver2_patricia_trie_node_reader.cpp \
+        ver2_pt_node_array_reader.cpp) \
+    $(addprefix dictionary/structure/v4/, \
+        ver4_dict_buffers.cpp \
+        ver4_dict_constants.cpp \
+        ver4_patricia_trie_node_reader.cpp \
+        ver4_patricia_trie_node_writer.cpp \
+        ver4_patricia_trie_policy.cpp \
+        ver4_patricia_trie_reading_utils.cpp \
+        ver4_patricia_trie_writing_helper.cpp \
+        ver4_pt_node_array_reader.cpp) \
+    $(addprefix dictionary/structure/v4/content/, \
+        dynamic_language_model_probability_utils.cpp \
+        language_model_dict_content.cpp \
+        language_model_dict_content_global_counters.cpp \
+        shortcut_dict_content.cpp \
+        sparse_table_dict_content.cpp \
+        terminal_position_lookup_table.cpp) \
+    $(addprefix dictionary/utils/, \
+        buffer_with_extendable_buffer.cpp \
+        byte_array_utils.cpp \
+        dict_file_writing_utils.cpp \
+        file_utils.cpp \
+        forgetting_curve_utils.cpp \
+        format_utils.cpp \
+        mmapped_buffer.cpp \
+        multi_bigram_map.cpp \
+        probability_utils.cpp \
+        sparse_table.cpp \
+        trie_map.cpp ) \
     suggest/core/suggest.cpp \
     $(addprefix suggest/core/dicnode/, \
         dic_node.cpp \
@@ -29,9 +75,7 @@
         dictionary.cpp \
         dictionary_utils.cpp \
         digraph_utils.cpp \
-        error_type_utils.cpp \
-        multi_bigram_map.cpp \
-        property/word_property.cpp) \
+        error_type_utils.cpp ) \
     $(addprefix suggest/core/layout/, \
         additional_proximity_chars.cpp \
         proximity_info.cpp \
@@ -43,49 +87,6 @@
     $(addprefix suggest/core/result/, \
         suggestion_results.cpp \
         suggestions_output_utils.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/, \
-        header/header_policy.cpp \
-        header/header_read_write_utils.cpp \
-        structure/dictionary_structure_with_buffer_policy_factory.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/structure/pt_common/, \
-        bigram/bigram_list_read_write_utils.cpp \
-        dynamic_pt_gc_event_listeners.cpp \
-        dynamic_pt_reading_helper.cpp \
-        dynamic_pt_reading_utils.cpp \
-        dynamic_pt_updating_helper.cpp \
-        dynamic_pt_writing_utils.cpp \
-        patricia_trie_reading_utils.cpp \
-        shortcut/shortcut_list_reading_utils.cpp ) \
-    $(addprefix suggest/policyimpl/dictionary/structure/v2/, \
-        patricia_trie_policy.cpp \
-        ver2_patricia_trie_node_reader.cpp \
-        ver2_pt_node_array_reader.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/structure/v4/, \
-        bigram/ver4_bigram_list_policy.cpp \
-        ver4_dict_buffers.cpp \
-        ver4_dict_constants.cpp \
-        ver4_patricia_trie_node_reader.cpp \
-        ver4_patricia_trie_node_writer.cpp \
-        ver4_patricia_trie_policy.cpp \
-        ver4_patricia_trie_reading_utils.cpp \
-        ver4_patricia_trie_writing_helper.cpp \
-        ver4_pt_node_array_reader.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/structure/v4/content/, \
-        bigram_dict_content.cpp \
-        language_model_dict_content.cpp \
-        shortcut_dict_content.cpp \
-        sparse_table_dict_content.cpp \
-        terminal_position_lookup_table.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/utils/, \
-        buffer_with_extendable_buffer.cpp \
-        byte_array_utils.cpp \
-        dict_file_writing_utils.cpp \
-        file_utils.cpp \
-        forgetting_curve_utils.cpp \
-        format_utils.cpp \
-        mmapped_buffer.cpp \
-        sparse_table.cpp \
-        trie_map.cpp ) \
     suggest/policyimpl/gesture/gesture_suggest_policy_factory.cpp \
     $(addprefix suggest/policyimpl/typing/, \
         scoring_params.cpp \
@@ -101,7 +102,7 @@
         time_keeper.cpp)
 
 LATIN_IME_CORE_SRC_FILES_BACKWARD_V402 := \
-    $(addprefix suggest/policyimpl/dictionary/structure/backward/v402/, \
+    $(addprefix dictionary/structure/backward/v402/, \
         ver4_dict_buffers.cpp \
         ver4_dict_constants.cpp \
         ver4_patricia_trie_node_reader.cpp \
@@ -110,24 +111,36 @@
         ver4_patricia_trie_reading_utils.cpp \
         ver4_patricia_trie_writing_helper.cpp \
         ver4_pt_node_array_reader.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/structure/backward/v402/content/, \
+    $(addprefix dictionary/structure/backward/v402/content/, \
         bigram_dict_content.cpp \
         probability_dict_content.cpp \
         shortcut_dict_content.cpp \
         sparse_table_dict_content.cpp \
         terminal_position_lookup_table.cpp) \
-    $(addprefix suggest/policyimpl/dictionary/structure/backward/v402/bigram/, \
+    $(addprefix dictionary/structure/backward/v402/bigram/, \
         ver4_bigram_list_policy.cpp)
 
 LATIN_IME_CORE_SRC_FILES += $(LATIN_IME_CORE_SRC_FILES_BACKWARD_V402)
 
 LATIN_IME_CORE_TEST_FILES := \
     defines_test.cpp \
+    dictionary/header/header_read_write_utils_test.cpp \
+    dictionary/structure/v4/content/language_model_dict_content_test.cpp \
+    dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp \
+    dictionary/structure/v4/content/probability_entry_test.cpp \
+    dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp \
+    dictionary/utils/bloom_filter_test.cpp \
+    dictionary/utils/buffer_with_extendable_buffer_test.cpp \
+    dictionary/utils/byte_array_utils_test.cpp \
+    dictionary/utils/format_utils_test.cpp \
+    dictionary/utils/probability_utils_test.cpp \
+    dictionary/utils/sparse_table_test.cpp \
+    dictionary/utils/trie_map_test.cpp \
+    suggest/core/dicnode/dic_node_pool_test.cpp \
+    suggest/core/layout/geometry_utils_test.cpp \
     suggest/core/layout/normal_distribution_2d_test.cpp \
-    suggest/core/dictionary/bloom_filter_test.cpp \
-    suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp \
-    suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp \
-    suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp \
-    suggest/policyimpl/dictionary/utils/trie_map_test.cpp \
+    suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy_test.cpp \
     utils/autocorrection_threshold_utils_test.cpp \
-    utils/int_array_view_test.cpp
+    utils/char_utils_test.cpp \
+    utils/int_array_view_test.cpp \
+    utils/time_keeper_test.cpp
diff --git a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
index f88d37e..80419b3 100644
--- a/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
+++ b/native/jni/com_android_inputmethod_keyboard_ProximityInfo.cpp
@@ -25,13 +25,13 @@
 
 namespace latinime {
 
-static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jclass clazz, jstring localeJStr,
+static jlong latinime_Keyboard_setProximityInfo(JNIEnv *env, jclass clazz,
         jint displayWidth, jint displayHeight, jint gridWidth, jint gridHeight,
         jint mostCommonkeyWidth, jint mostCommonkeyHeight, jintArray proximityChars, jint keyCount,
         jintArray keyXCoordinates, jintArray keyYCoordinates, jintArray keyWidths,
         jintArray keyHeights, jintArray keyCharCodes, jfloatArray sweetSpotCenterXs,
         jfloatArray sweetSpotCenterYs, jfloatArray sweetSpotRadii) {
-    ProximityInfo *proximityInfo = new ProximityInfo(env, localeJStr, displayWidth, displayHeight,
+    ProximityInfo *proximityInfo = new ProximityInfo(env, displayWidth, displayHeight,
             gridWidth, gridHeight, mostCommonkeyWidth, mostCommonkeyHeight, proximityChars,
             keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes,
             sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii);
@@ -46,7 +46,7 @@
 static const JNINativeMethod sMethods[] = {
     {
         const_cast<char *>("setProximityInfoNative"),
-        const_cast<char *>("(Ljava/lang/String;IIIIII[II[I[I[I[I[I[F[F[F)J"),
+        const_cast<char *>("(IIIIII[II[I[I[I[I[I[F[F[F)J"),
         reinterpret_cast<void *>(latinime_Keyboard_setProximityInfo)
     },
     {
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 22ad2d0..3341e11 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -22,18 +22,20 @@
 #include <vector>
 
 #include "defines.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/property/ngram_context.h"
+#include "dictionary/property/word_property.h"
+#include "dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
 #include "jni.h"
 #include "jni_common.h"
 #include "suggest/core/dictionary/dictionary.h"
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/core/dictionary/property/word_property.h"
 #include "suggest/core/result/suggestion_results.h"
-#include "suggest/core/session/prev_words_info.h"
 #include "suggest/core/suggest_options.h"
-#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
 #include "utils/char_utils.h"
+#include "utils/int_array_view.h"
 #include "utils/jni_data_utils.h"
 #include "utils/log_utils.h"
+#include "utils/profiler.h"
 #include "utils/time_keeper.h"
 
 namespace latinime {
@@ -42,8 +44,8 @@
 
 static jlong latinime_BinaryDictionary_open(JNIEnv *env, jclass clazz, jstring sourceDir,
         jlong dictOffset, jlong dictSize, jboolean isUpdatable) {
-    PROF_OPEN;
-    PROF_START(66);
+    PROF_INIT;
+    PROF_TIMER_START(66);
     const jsize sourceDirUtf8Length = env->GetStringUTFLength(sourceDir);
     if (sourceDirUtf8Length <= 0) {
         AKLOGE("DICT: Can't get sourceDir string");
@@ -62,8 +64,7 @@
 
     Dictionary *const dictionary =
             new Dictionary(env, std::move(dictionaryStructureWithBufferPolicy));
-    PROF_END(66);
-    PROF_CLOSE;
+    PROF_TIMER_END(66);
     return reinterpret_cast<jlong>(dictionary);
 }
 
@@ -179,9 +180,10 @@
         jintArray yCoordinatesArray, jintArray timesArray, jintArray pointerIdsArray,
         jintArray inputCodePointsArray, jint inputSize, jintArray suggestOptions,
         jobjectArray prevWordCodePointArrays, jbooleanArray isBeginningOfSentenceArray,
-        jintArray outSuggestionCount, jintArray outCodePointsArray, jintArray outScoresArray,
-        jintArray outSpaceIndicesArray, jintArray outTypesArray,
-        jintArray outAutoCommitFirstWordConfidenceArray, jfloatArray inOutLanguageWeight) {
+        jint prevWordCount, jintArray outSuggestionCount, jintArray outCodePointsArray,
+        jintArray outScoresArray, jintArray outSpaceIndicesArray, jintArray outTypesArray,
+        jintArray outAutoCommitFirstWordConfidenceArray,
+        jfloatArray inOutWeightOfLangModelVsSpatialModel) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     // Assign 0 to outSuggestionCount here in case of returning earlier in this method.
     JniDataUtils::putIntToArray(env, outSuggestionCount, 0 /* index */, 0);
@@ -236,42 +238,47 @@
         ASSERT(false);
         return;
     }
-    float languageWeight;
-    env->GetFloatArrayRegion(inOutLanguageWeight, 0, 1 /* len */, &languageWeight);
+    float weightOfLangModelVsSpatialModel;
+    env->GetFloatArrayRegion(inOutWeightOfLangModelVsSpatialModel, 0, 1 /* len */,
+            &weightOfLangModelVsSpatialModel);
     SuggestionResults suggestionResults(MAX_RESULTS);
-    const PrevWordsInfo prevWordsInfo = JniDataUtils::constructPrevWordsInfo(env,
-            prevWordCodePointArrays, isBeginningOfSentenceArray);
+    const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+            prevWordCodePointArrays, isBeginningOfSentenceArray, prevWordCount);
     if (givenSuggestOptions.isGesture() || inputSize > 0) {
         // TODO: Use SuggestionResults to return suggestions.
         dictionary->getSuggestions(pInfo, traverseSession, xCoordinates, yCoordinates,
-                times, pointerIds, inputCodePoints, inputSize, &prevWordsInfo,
-                &givenSuggestOptions, languageWeight, &suggestionResults);
+                times, pointerIds, inputCodePoints, inputSize, &ngramContext,
+                &givenSuggestOptions, weightOfLangModelVsSpatialModel, &suggestionResults);
     } else {
-        dictionary->getPredictions(&prevWordsInfo, &suggestionResults);
+        dictionary->getPredictions(&ngramContext, &suggestionResults);
+    }
+    if (DEBUG_DICT) {
+        suggestionResults.dumpSuggestions();
     }
     suggestionResults.outputSuggestions(env, outSuggestionCount, outCodePointsArray,
             outScoresArray, outSpaceIndicesArray, outTypesArray,
-            outAutoCommitFirstWordConfidenceArray, inOutLanguageWeight);
+            outAutoCommitFirstWordConfidenceArray, inOutWeightOfLangModelVsSpatialModel);
 }
 
 static jint latinime_BinaryDictionary_getProbability(JNIEnv *env, jclass clazz, jlong dict,
         jintArray word) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return NOT_A_PROBABILITY;
-    const jsize wordLength = env->GetArrayLength(word);
-    int codePoints[wordLength];
-    env->GetIntArrayRegion(word, 0, wordLength, codePoints);
-    return dictionary->getProbability(codePoints, wordLength);
+    const jsize codePointCount = env->GetArrayLength(word);
+    int codePoints[codePointCount];
+    env->GetIntArrayRegion(word, 0, codePointCount, codePoints);
+    return dictionary->getProbability(CodePointArrayView(codePoints, codePointCount));
 }
 
 static jint latinime_BinaryDictionary_getMaxProbabilityOfExactMatches(
         JNIEnv *env, jclass clazz, jlong dict, jintArray word) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return NOT_A_PROBABILITY;
-    const jsize wordLength = env->GetArrayLength(word);
-    int codePoints[wordLength];
-    env->GetIntArrayRegion(word, 0, wordLength, codePoints);
-    return dictionary->getMaxProbabilityOfExactMatches(codePoints, wordLength);
+    const jsize codePointCount = env->GetArrayLength(word);
+    int codePoints[codePointCount];
+    env->GetIntArrayRegion(word, 0, codePointCount, codePoints);
+    return dictionary->getMaxProbabilityOfExactMatches(
+            CodePointArrayView(codePoints, codePointCount));
 }
 
 static jint latinime_BinaryDictionary_getNgramProbability(JNIEnv *env, jclass clazz,
@@ -282,9 +289,11 @@
     const jsize wordLength = env->GetArrayLength(word);
     int wordCodePoints[wordLength];
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    const PrevWordsInfo prevWordsInfo = JniDataUtils::constructPrevWordsInfo(env,
-            prevWordCodePointArrays, isBeginningOfSentenceArray);
-    return dictionary->getNgramProbability(&prevWordsInfo, wordCodePoints, wordLength);
+    const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+            prevWordCodePointArrays, isBeginningOfSentenceArray,
+            env->GetArrayLength(prevWordCodePointArrays));
+    return dictionary->getNgramProbability(&ngramContext,
+            CodePointArrayView(wordCodePoints, wordLength));
 }
 
 // Method to iterate all words in the dictionary for makedict.
@@ -318,8 +327,9 @@
 
 static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz,
         jlong dict, jintArray word, jboolean isBeginningOfSentence, jintArray outCodePoints,
-        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
-        jobject outBigramProbabilityInfo, jobject outShortcutTargets,
+        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outNgramPrevWordsArray,
+        jobject outNgramPrevWordIsBeginningOfSentenceArray, jobject outNgramTargets,
+        jobject outNgramProbabilityInfo, jobject outShortcutTargets,
         jobject outShortcutProbabilities) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) return;
@@ -339,15 +349,16 @@
             return;
         }
     }
-    const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints, codePointCount);
-    wordProperty.outputProperties(env, outCodePoints, outFlags, outProbabilityInfo,
-            outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
-            outShortcutProbabilities);
+    const WordProperty wordProperty = dictionary->getWordProperty(
+            CodePointArrayView(wordCodePoints, codePointCount));
+    JniDataUtils::outputWordProperty(env, wordProperty, outCodePoints, outFlags, outProbabilityInfo,
+            outNgramPrevWordsArray, outNgramPrevWordIsBeginningOfSentenceArray,
+            outNgramTargets, outNgramProbabilityInfo, outShortcutTargets, outShortcutProbabilities);
 }
 
 static bool latinime_BinaryDictionary_addUnigramEntry(JNIEnv *env, jclass clazz, jlong dict,
         jintArray word, jint probability, jintArray shortcutTarget, jint shortcutProbability,
-        jboolean isBeginningOfSentence, jboolean isNotAWord, jboolean isBlacklisted,
+        jboolean isBeginningOfSentence, jboolean isNotAWord, jboolean isPossiblyOffensive,
         jint timestamp) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) {
@@ -357,15 +368,19 @@
     int codePoints[codePointCount];
     env->GetIntArrayRegion(word, 0, codePointCount, codePoints);
     std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-    std::vector<int> shortcutTargetCodePoints;
-    JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
-    if (!shortcutTargetCodePoints.empty()) {
-        shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
+    {
+        std::vector<int> shortcutTargetCodePoints;
+        JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
+        if (!shortcutTargetCodePoints.empty()) {
+            shortcuts.emplace_back(std::move(shortcutTargetCodePoints), shortcutProbability);
+        }
     }
     // Use 1 for count to indicate the word has inputted.
     const UnigramProperty unigramProperty(isBeginningOfSentence, isNotAWord,
-            isBlacklisted, probability, timestamp, 0 /* level */, 1 /* count */, &shortcuts);
-    return dictionary->addUnigramEntry(codePoints, codePointCount, &unigramProperty);
+            isPossiblyOffensive, probability, HistoricalInfo(timestamp, 0 /* level */,
+            1 /* count */), std::move(shortcuts));
+    return dictionary->addUnigramEntry(CodePointArrayView(codePoints, codePointCount),
+            &unigramProperty);
 }
 
 static bool latinime_BinaryDictionary_removeUnigramEntry(JNIEnv *env, jclass clazz, jlong dict,
@@ -377,7 +392,7 @@
     jsize codePointCount = env->GetArrayLength(word);
     int codePoints[codePointCount];
     env->GetIntArrayRegion(word, 0, codePointCount, codePoints);
-    return dictionary->removeUnigramEntry(codePoints, codePointCount);
+    return dictionary->removeUnigramEntry(CodePointArrayView(codePoints, codePointCount));
 }
 
 static bool latinime_BinaryDictionary_addNgramEntry(JNIEnv *env, jclass clazz, jlong dict,
@@ -387,17 +402,17 @@
     if (!dictionary) {
         return false;
     }
-    const PrevWordsInfo prevWordsInfo = JniDataUtils::constructPrevWordsInfo(env,
-            prevWordCodePointArrays, isBeginningOfSentenceArray);
+    const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+            prevWordCodePointArrays, isBeginningOfSentenceArray,
+            env->GetArrayLength(prevWordCodePointArrays));
     jsize wordLength = env->GetArrayLength(word);
     int wordCodePoints[wordLength];
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    const std::vector<int> bigramTargetCodePoints(
-            wordCodePoints, wordCodePoints + wordLength);
-    // Use 1 for count to indicate the bigram has inputted.
-    const BigramProperty bigramProperty(&bigramTargetCodePoints, probability,
-            timestamp, 0 /* level */, 1 /* count */);
-    return dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty);
+    // Use 1 for count to indicate the ngram has inputted.
+    const NgramProperty ngramProperty(ngramContext,
+            CodePointArrayView(wordCodePoints, wordLength).toVector(),
+            probability, HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
+    return dictionary->addNgramEntry(&ngramProperty);
 }
 
 static bool latinime_BinaryDictionary_removeNgramEntry(JNIEnv *env, jclass clazz, jlong dict,
@@ -407,103 +422,90 @@
     if (!dictionary) {
         return false;
     }
-    const PrevWordsInfo prevWordsInfo = JniDataUtils::constructPrevWordsInfo(env,
-            prevWordCodePointArrays, isBeginningOfSentenceArray);
-    jsize wordLength = env->GetArrayLength(word);
-    int wordCodePoints[wordLength];
-    env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    return dictionary->removeNgramEntry(&prevWordsInfo, wordCodePoints, wordLength);
+    const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+            prevWordCodePointArrays, isBeginningOfSentenceArray,
+            env->GetArrayLength(prevWordCodePointArrays));
+    jsize codePointCount = env->GetArrayLength(word);
+    int wordCodePoints[codePointCount];
+    env->GetIntArrayRegion(word, 0, codePointCount, wordCodePoints);
+    return dictionary->removeNgramEntry(&ngramContext,
+            CodePointArrayView(wordCodePoints, codePointCount));
 }
 
-// Returns how many language model params are processed.
-static int latinime_BinaryDictionary_addMultipleDictionaryEntries(JNIEnv *env, jclass clazz,
-        jlong dict, jobjectArray languageModelParams, jint startIndex) {
+static bool latinime_BinaryDictionary_updateEntriesForWordWithNgramContext(JNIEnv *env,
+        jclass clazz, jlong dict, jobjectArray prevWordCodePointArrays,
+        jbooleanArray isBeginningOfSentenceArray, jintArray word, jboolean isValidWord, jint count,
+        jint timestamp) {
+    Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
+    if (!dictionary) {
+        return false;
+    }
+    const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+            prevWordCodePointArrays, isBeginningOfSentenceArray,
+            env->GetArrayLength(prevWordCodePointArrays));
+    jsize codePointCount = env->GetArrayLength(word);
+    int wordCodePoints[codePointCount];
+    env->GetIntArrayRegion(word, 0, codePointCount, wordCodePoints);
+    const HistoricalInfo historicalInfo(timestamp, 0 /* level */, count);
+    return dictionary->updateEntriesForWordWithNgramContext(&ngramContext,
+            CodePointArrayView(wordCodePoints, codePointCount), isValidWord == JNI_TRUE,
+            historicalInfo);
+}
+
+// Returns how many input events are processed.
+static int latinime_BinaryDictionary_updateEntriesForInputEvents(JNIEnv *env, jclass clazz,
+        jlong dict, jobjectArray inputEvents, jint startIndex) {
     Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
     if (!dictionary) {
         return 0;
     }
-    jsize languageModelParamCount = env->GetArrayLength(languageModelParams);
-    if (languageModelParamCount == 0 || startIndex >= languageModelParamCount) {
+    jsize inputEventCount = env->GetArrayLength(inputEvents);
+    if (inputEventCount == 0 || startIndex >= inputEventCount) {
         return 0;
     }
-    jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, 0);
-    jclass languageModelParamClass = env->GetObjectClass(languageModelParam);
-    env->DeleteLocalRef(languageModelParam);
+    jobject inputEvent = env->GetObjectArrayElement(inputEvents, 0);
+    jclass wordInputEventClass = env->GetObjectClass(inputEvent);
+    env->DeleteLocalRef(inputEvent);
 
-    jfieldID word0FieldId = env->GetFieldID(languageModelParamClass, "mWord0", "[I");
-    jfieldID word1FieldId = env->GetFieldID(languageModelParamClass, "mWord1", "[I");
-    jfieldID unigramProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mUnigramProbability", "I");
-    jfieldID bigramProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mBigramProbability", "I");
-    jfieldID timestampFieldId =
-            env->GetFieldID(languageModelParamClass, "mTimestamp", "I");
-    jfieldID shortcutTargetFieldId =
-            env->GetFieldID(languageModelParamClass, "mShortcutTarget", "[I");
-    jfieldID shortcutProbabilityFieldId =
-            env->GetFieldID(languageModelParamClass, "mShortcutProbability", "I");
-    jfieldID isNotAWordFieldId =
-            env->GetFieldID(languageModelParamClass, "mIsNotAWord", "Z");
-    jfieldID isBlacklistedFieldId =
-            env->GetFieldID(languageModelParamClass, "mIsBlacklisted", "Z");
-    env->DeleteLocalRef(languageModelParamClass);
+    jfieldID targetWordFieldId = env->GetFieldID(wordInputEventClass, "mTargetWord", "[I");
+    jfieldID prevWordCountFieldId = env->GetFieldID(wordInputEventClass, "mPrevWordsCount", "I");
+    jfieldID prevWordArrayFieldId = env->GetFieldID(wordInputEventClass, "mPrevWordArray", "[[I");
+    jfieldID isPrevWordBoSArrayFieldId =
+            env->GetFieldID(wordInputEventClass, "mIsPrevWordBeginningOfSentenceArray", "[Z");
+    jfieldID isValidFieldId = env->GetFieldID(wordInputEventClass, "mIsValid", "Z");
+    jfieldID timestampFieldId = env->GetFieldID(wordInputEventClass, "mTimestamp", "I");
+    env->DeleteLocalRef(wordInputEventClass);
 
-    for (int i = startIndex; i < languageModelParamCount; ++i) {
-        jobject languageModelParam = env->GetObjectArrayElement(languageModelParams, i);
-        // languageModelParam is a set of params for word1; thus, word1 cannot be null. On the
-        // other hand, word0 can be null and then it means the set of params doesn't contain bigram
-        // information.
-        jintArray word0 = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, word0FieldId));
-        jsize word0Length = word0 ? env->GetArrayLength(word0) : 0;
-        int word0CodePoints[word0Length];
-        if (word0) {
-            env->GetIntArrayRegion(word0, 0, word0Length, word0CodePoints);
-        }
-        jintArray word1 = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, word1FieldId));
-        jsize word1Length = env->GetArrayLength(word1);
-        int word1CodePoints[word1Length];
-        env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints);
-        jint unigramProbability = env->GetIntField(languageModelParam, unigramProbabilityFieldId);
-        jint timestamp = env->GetIntField(languageModelParam, timestampFieldId);
-        jboolean isNotAWord = env->GetBooleanField(languageModelParam, isNotAWordFieldId);
-        jboolean isBlacklisted = env->GetBooleanField(languageModelParam, isBlacklistedFieldId);
-        jintArray shortcutTarget = static_cast<jintArray>(
-                env->GetObjectField(languageModelParam, shortcutTargetFieldId));
-        std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-        std::vector<int> shortcutTargetCodePoints;
-        JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
-        if (!shortcutTargetCodePoints.empty()) {
-            jint shortcutProbability =
-                    env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
-            shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
-        }
+    for (int i = startIndex; i < inputEventCount; ++i) {
+        jobject inputEvent = env->GetObjectArrayElement(inputEvents, i);
+        jintArray targetWord = static_cast<jintArray>(
+                env->GetObjectField(inputEvent, targetWordFieldId));
+        jsize wordLength = env->GetArrayLength(targetWord);
+        int wordCodePoints[wordLength];
+        env->GetIntArrayRegion(targetWord, 0, wordLength, wordCodePoints);
+        env->DeleteLocalRef(targetWord);
+
+        jint prevWordCount = env->GetIntField(inputEvent, prevWordCountFieldId);
+        jobjectArray prevWordArray =
+                static_cast<jobjectArray>(env->GetObjectField(inputEvent, prevWordArrayFieldId));
+        jbooleanArray isPrevWordBeginningOfSentenceArray = static_cast<jbooleanArray>(
+                env->GetObjectField(inputEvent, isPrevWordBoSArrayFieldId));
+        jboolean isValid = env->GetBooleanField(inputEvent, isValidFieldId);
+        jint timestamp = env->GetIntField(inputEvent, timestampFieldId);
+        const NgramContext ngramContext = JniDataUtils::constructNgramContext(env,
+                prevWordArray, isPrevWordBeginningOfSentenceArray, prevWordCount);
         // Use 1 for count to indicate the word has inputted.
-        const UnigramProperty unigramProperty(false /* isBeginningOfSentence */, isNotAWord,
-                isBlacklisted, unigramProbability, timestamp, 0 /* level */, 1 /* count */,
-                &shortcuts);
-        dictionary->addUnigramEntry(word1CodePoints, word1Length, &unigramProperty);
-        if (word0) {
-            jint bigramProbability = env->GetIntField(languageModelParam, bigramProbabilityFieldId);
-            const std::vector<int> bigramTargetCodePoints(
-                    word1CodePoints, word1CodePoints + word1Length);
-            // Use 1 for count to indicate the bigram has inputted.
-            const BigramProperty bigramProperty(&bigramTargetCodePoints, bigramProbability,
-                    timestamp, 0 /* level */, 1 /* count */);
-            const PrevWordsInfo prevWordsInfo(word0CodePoints, word0Length,
-                    false /* isBeginningOfSentence */);
-            dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty);
-        }
+        dictionary->updateEntriesForWordWithNgramContext(&ngramContext,
+                CodePointArrayView(wordCodePoints, wordLength), isValid,
+                HistoricalInfo(timestamp, 0 /* level */, 1 /* count */));
         if (dictionary->needsToRunGC(true /* mindsBlockByGC */)) {
             return i + 1;
         }
-        env->DeleteLocalRef(word0);
-        env->DeleteLocalRef(word1);
-        env->DeleteLocalRef(shortcutTarget);
-        env->DeleteLocalRef(languageModelParam);
+        env->DeleteLocalRef(prevWordArray);
+        env->DeleteLocalRef(isPrevWordBeginningOfSentenceArray);
+        env->DeleteLocalRef(inputEvent);
     }
-    return languageModelParamCount;
+    return inputEventCount;
 }
 
 static jstring latinime_BinaryDictionary_getProperty(JNIEnv *env, jclass clazz, jlong dict,
@@ -567,8 +569,8 @@
     // Add unigrams.
     do {
         token = dictionary->getNextWordAndNextToken(token, wordCodePoints, &wordCodePointCount);
-        const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints,
-                wordCodePointCount);
+        const WordProperty wordProperty = dictionary->getWordProperty(
+                CodePointArrayView(wordCodePoints, wordCodePointCount));
         if (wordCodePoints[0] == CODE_POINT_BEGINNING_OF_SENTENCE) {
             // Skip beginning-of-sentence unigram.
             continue;
@@ -581,18 +583,19 @@
                 return false;
             }
         }
-        if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(wordCodePoints,
-                wordCodePointCount, wordProperty.getUnigramProperty())) {
+        if (!dictionaryStructureWithBufferPolicy->addUnigramEntry(
+                CodePointArrayView(wordCodePoints, wordCodePointCount),
+                &wordProperty.getUnigramProperty())) {
             LogUtils::logToJava(env, "Cannot add unigram to the new dict.");
             return false;
         }
     } while (token != 0);
 
-    // Add bigrams.
+    // Add ngrams.
     do {
         token = dictionary->getNextWordAndNextToken(token, wordCodePoints, &wordCodePointCount);
-        const WordProperty wordProperty = dictionary->getWordProperty(wordCodePoints,
-                wordCodePointCount);
+        const WordProperty wordProperty = dictionary->getWordProperty(
+                CodePointArrayView(wordCodePoints, wordCodePointCount));
         if (dictionaryStructureWithBufferPolicy->needsToRunGC(true /* mindsBlockByGC */)) {
             dictionaryStructureWithBufferPolicy = runGCAndGetNewStructurePolicy(
                     std::move(dictionaryStructureWithBufferPolicy), dictFilePathChars);
@@ -601,12 +604,9 @@
                 return false;
             }
         }
-        const PrevWordsInfo prevWordsInfo(wordCodePoints, wordCodePointCount,
-                wordProperty.getUnigramProperty()->representsBeginningOfSentence());
-        for (const BigramProperty &bigramProperty : *wordProperty.getBigramProperties()) {
-            if (!dictionaryStructureWithBufferPolicy->addNgramEntry(&prevWordsInfo,
-                    &bigramProperty)) {
-                LogUtils::logToJava(env, "Cannot add bigram to the new dict.");
+        for (const NgramProperty &ngramProperty : wordProperty.getNgramProperties()) {
+            if (!dictionaryStructureWithBufferPolicy->addNgramEntry(&ngramProperty)) {
+                LogUtils::logToJava(env, "Cannot add ngram to the new dict.");
                 return false;
             }
         }
@@ -659,7 +659,7 @@
     },
     {
         const_cast<char *>("getSuggestionsNative"),
-        const_cast<char *>("(JJJ[I[I[I[I[II[I[[I[Z[I[I[I[I[I[I[F)V"),
+        const_cast<char *>("(JJJ[I[I[I[I[II[I[[I[ZI[I[I[I[I[I[I[F)V"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_getSuggestions)
     },
     {
@@ -680,7 +680,8 @@
     {
         const_cast<char *>("getWordPropertyNative"),
         const_cast<char *>("(J[IZ[I[Z[ILjava/util/ArrayList;Ljava/util/ArrayList;"
-                "Ljava/util/ArrayList;Ljava/util/ArrayList;)V"),
+                "Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;"
+                "Ljava/util/ArrayList;)V"),
         reinterpret_cast<void *>(latinime_BinaryDictionary_getWordProperty)
     },
     {
@@ -709,10 +710,15 @@
         reinterpret_cast<void *>(latinime_BinaryDictionary_removeNgramEntry)
     },
     {
-        const_cast<char *>("addMultipleDictionaryEntriesNative"),
+        const_cast<char *>("updateEntriesForWordWithNgramContextNative"),
+        const_cast<char *>("(J[[I[Z[IZII)Z"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_updateEntriesForWordWithNgramContext)
+    },
+    {
+        const_cast<char *>("updateEntriesForInputEventsNative"),
         const_cast<char *>(
-                "(J[Lcom/android/inputmethod/latin/utils/LanguageModelParam;I)I"),
-        reinterpret_cast<void *>(latinime_BinaryDictionary_addMultipleDictionaryEntries)
+                "(J[Lcom/android/inputmethod/latin/utils/WordInputEventForPersonalization;I)I"),
+        reinterpret_cast<void *>(latinime_BinaryDictionary_updateEntriesForInputEvents)
     },
     {
         const_cast<char *>("getPropertyNative"),
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
index 0a34b78..0885f2d 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionaryUtils.cpp
@@ -19,9 +19,9 @@
 #include "com_android_inputmethod_latin_BinaryDictionaryUtils.h"
 
 #include "defines.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
 #include "jni.h"
 #include "jni_common.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
 #include "utils/autocorrection_threshold_utils.h"
 #include "utils/char_utils.h"
 #include "utils/jni_data_utils.h"
@@ -68,18 +68,6 @@
             afterCodePoints, afterLength, score);
 }
 
-static jint latinime_BinaryDictionaryUtils_editDistance(JNIEnv *env, jclass clazz, jintArray before,
-        jintArray after) {
-    jsize beforeLength = env->GetArrayLength(before);
-    jsize afterLength = env->GetArrayLength(after);
-    int beforeCodePoints[beforeLength];
-    int afterCodePoints[afterLength];
-    env->GetIntArrayRegion(before, 0, beforeLength, beforeCodePoints);
-    env->GetIntArrayRegion(after, 0, afterLength, afterCodePoints);
-    return AutocorrectionThresholdUtils::editDistance(beforeCodePoints, beforeLength,
-            afterCodePoints, afterLength);
-}
-
 static int latinime_BinaryDictionaryUtils_setCurrentTimeForTest(JNIEnv *env, jclass clazz,
         jint currentTime) {
     if (currentTime >= 0) {
@@ -104,11 +92,6 @@
         reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_calcNormalizedScore)
     },
     {
-        const_cast<char *>("editDistanceNative"),
-        const_cast<char *>("([I[I)I"),
-        reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_editDistance)
-    },
-    {
         const_cast<char *>("setCurrentTimeForTestNative"),
         const_cast<char *>("(I)I"),
         reinterpret_cast<void *>(latinime_BinaryDictionaryUtils_setCurrentTimeForTest)
diff --git a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
index 7660641..45f5492 100644
--- a/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
+++ b/native/jni/com_android_inputmethod_latin_DicTraverseSession.cpp
@@ -19,10 +19,10 @@
 #include "com_android_inputmethod_latin_DicTraverseSession.h"
 
 #include "defines.h"
+#include "dictionary/property/ngram_context.h"
 #include "jni.h"
 #include "jni_common.h"
 #include "suggest/core/session/dic_traverse_session.h"
-#include "suggest/core/session/prev_words_info.h"
 
 namespace latinime {
 class Dictionary;
@@ -40,14 +40,14 @@
     }
     Dictionary *dict = reinterpret_cast<Dictionary *>(dictionary);
     if (!previousWord) {
-        PrevWordsInfo prevWordsInfo;
-        ts->init(dict, &prevWordsInfo, 0 /* suggestOptions */);
+        NgramContext emptyNgramContext;
+        ts->init(dict, &emptyNgramContext, 0 /* suggestOptions */);
         return;
     }
     int prevWord[previousWordLength];
     env->GetIntArrayRegion(previousWord, 0, previousWordLength, prevWord);
-    PrevWordsInfo prevWordsInfo(prevWord, previousWordLength, false /* isStartOfSentence */);
-    ts->init(dict, &prevWordsInfo, 0 /* suggestOptions */);
+    NgramContext ngramContext(prevWord, previousWordLength, false /* isStartOfSentence */);
+    ts->init(dict, &ngramContext, 0 /* suggestOptions */);
 }
 
 static void latinime_releaseDicTraverseSession(JNIEnv *env, jclass clazz, jlong traverseSession) {
diff --git a/native/jni/run-tests.sh b/native/jni/run-tests.sh
index 3da4527..a7fa82d 100755
--- a/native/jni/run-tests.sh
+++ b/native/jni/run-tests.sh
@@ -48,6 +48,13 @@
   if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
 fi
 
+# Host build is never supported in unbundled (NDK/tapas) build
+if [[ $enable_host_test == yes && -n $TARGET_BUILD_APPS ]]; then
+  echo "Host build is never supported in tapas build."  1>&2
+  echo "Use lunch command instead."  1>&2
+  if [[ ${BASH_SOURCE[0]} != $0 ]]; then return; else exit 1; fi
+fi
+
 target_test_name=liblatinime_target_unittests
 host_test_name=liblatinime_host_unittests
 
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 24d04e5..10b930e 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -23,10 +23,10 @@
 #define AK_FORCE_INLINE inline
 #endif // __GNUC__
 
-#if defined(FLAG_DO_PROFILE) || defined(FLAG_DBG)
+#if defined(FLAG_DBG)
 #undef AK_FORCE_INLINE
 #define AK_FORCE_INLINE inline
-#endif // defined(FLAG_DO_PROFILE) || defined(FLAG_DBG)
+#endif // defined(FLAG_DBG)
 
 // Must be equal to Constants.Dictionary.MAX_WORD_LENGTH in Java
 #define MAX_WORD_LENGTH 48
@@ -119,7 +119,7 @@
         const int probability) {
     static char charBuf[50];
     const int N = intArrayToCharArray(word, length, charBuf, NELEMS(charBuf));
-    if (N > 1) {
+    if (N > 0) {
         AKLOGI("%2d [ %s ] (%d)", rank, charBuf, probability);
     }
 }
@@ -172,69 +172,6 @@
 #define INTS_TO_CHARS(input, length, output)
 #endif // defined(FLAG_DO_PROFILE) || defined(FLAG_DBG)
 
-#ifdef FLAG_DO_PROFILE
-// Profiler
-#include <time.h>
-
-#define PROF_BUF_SIZE 100
-static float profile_buf[PROF_BUF_SIZE];
-static float profile_old[PROF_BUF_SIZE];
-static unsigned int profile_counter[PROF_BUF_SIZE];
-
-#define PROF_RESET               prof_reset()
-#define PROF_COUNT(prof_buf_id)  ++profile_counter[prof_buf_id]
-#define PROF_OPEN                do { PROF_RESET; PROF_START(PROF_BUF_SIZE - 1); } while (0)
-#define PROF_START(prof_buf_id)  do { \
-        PROF_COUNT(prof_buf_id); profile_old[prof_buf_id] = (clock()); } while (0)
-#define PROF_CLOSE               do { PROF_END(PROF_BUF_SIZE - 1); PROF_OUTALL; } while (0)
-#define PROF_END(prof_buf_id)    profile_buf[prof_buf_id] += ((clock()) - profile_old[prof_buf_id])
-#define PROF_CLOCKOUT(prof_buf_id) \
-        AKLOGI("%s : clock is %f", __FUNCTION__, (clock() - profile_old[prof_buf_id]))
-#define PROF_OUTALL              do { AKLOGI("--- %s ---", __FUNCTION__); prof_out(); } while (0)
-
-static inline void prof_reset(void) {
-    for (int i = 0; i < PROF_BUF_SIZE; ++i) {
-        profile_buf[i] = 0;
-        profile_old[i] = 0;
-        profile_counter[i] = 0;
-    }
-}
-
-static inline void prof_out(void) {
-    if (profile_counter[PROF_BUF_SIZE - 1] != 1) {
-        AKLOGI("Error: You must call PROF_OPEN before PROF_CLOSE.");
-    }
-    AKLOGI("Total time is %6.3f ms.",
-            profile_buf[PROF_BUF_SIZE - 1] * 1000.0f / static_cast<float>(CLOCKS_PER_SEC));
-    float all = 0.0f;
-    for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) {
-        all += profile_buf[i];
-    }
-    if (all < 1.0f) all = 1.0f;
-    for (int i = 0; i < PROF_BUF_SIZE - 1; ++i) {
-        if (profile_buf[i] > 0.0f) {
-            AKLOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.",
-                    i, (profile_buf[i] * 100.0f / all),
-                    profile_buf[i] * 1000.0f / static_cast<float>(CLOCKS_PER_SEC),
-                    profile_counter[i]);
-        }
-    }
-}
-
-#else // FLAG_DO_PROFILE
-#define PROF_BUF_SIZE 0
-#define PROF_RESET
-#define PROF_COUNT(prof_buf_id)
-#define PROF_OPEN
-#define PROF_START(prof_buf_id)
-#define PROF_CLOSE
-#define PROF_END(prof_buf_id)
-#define PROF_CLOCK_OUT(prof_buf_id)
-#define PROF_CLOCKOUT(prof_buf_id)
-#define PROF_OUTALL
-
-#endif // FLAG_DO_PROFILE
-
 #ifdef FLAG_DBG
 #define DEBUG_DICT true
 #define DEBUG_DICT_FULL false
@@ -299,8 +236,9 @@
 #define NOT_AN_INDEX (-1)
 #define NOT_A_PROBABILITY (-1)
 #define NOT_A_DICT_POS (S_INT_MIN)
+#define NOT_A_WORD_ID (S_INT_MIN)
 #define NOT_A_TIMESTAMP (-1)
-#define NOT_A_LANGUAGE_WEIGHT (-1.0f)
+#define NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL (-1.0f)
 
 // A special value to mean the first word confidence makes no sense in this case,
 // e.g. this is not a multi-word suggestion.
@@ -337,7 +275,7 @@
 #define MAX_POINTER_COUNT_G 2
 
 // (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported.
-#define MAX_PREV_WORD_COUNT_FOR_N_GRAM 1
+#define MAX_PREV_WORD_COUNT_FOR_N_GRAM 3
 
 #define DISALLOW_DEFAULT_CONSTRUCTOR(TypeName) \
   TypeName() = delete
diff --git a/native/jni/src/dictionary/header/header_policy.cpp b/native/jni/src/dictionary/header/header_policy.cpp
new file mode 100644
index 0000000..d4f84d3
--- /dev/null
+++ b/native/jni/src/dictionary/header/header_policy.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/header/header_policy.h"
+
+#include <algorithm>
+
+#include "utils/ngram_utils.h"
+
+namespace latinime {
+
+// Note that these are corresponding definitions in Java side in DictionaryHeader.
+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::DATE_KEY = "date";
+const char *const HeaderPolicy::LAST_DECAYED_TIME_KEY = "LAST_DECAYED_TIME";
+const char *const HeaderPolicy::NGRAM_COUNT_KEYS[] =
+        {"UNIGRAM_COUNT", "BIGRAM_COUNT", "TRIGRAM_COUNT", "QUADGRAM_COUNT"};
+const char *const HeaderPolicy::MAX_NGRAM_COUNT_KEYS[] =
+        {"MAX_UNIGRAM_ENTRY_COUNT", "MAX_BIGRAM_ENTRY_COUNT", "MAX_TRIGRAM_ENTRY_COUNT",
+                "MAX_QUADGRAM_ENTRY_COUNT"};
+const int HeaderPolicy::DEFAULT_MAX_NGRAM_COUNTS[] = {10000, 30000, 30000, 30000};
+const char *const HeaderPolicy::EXTENDED_REGION_SIZE_KEY = "EXTENDED_REGION_SIZE";
+// Historical info is information that is needed to support decaying such as timestamp, level and
+// count.
+const char *const HeaderPolicy::HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO";
+const char *const HeaderPolicy::LOCALE_KEY = "locale"; // match Java declaration
+const char *const HeaderPolicy::FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY =
+        "FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID";
+
+const int HeaderPolicy::DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE = 100;
+const float HeaderPolicy::MULTIPLE_WORD_COST_MULTIPLIER_SCALE = 100.0f;
+const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID = 3;
+
+// Used for logging. Question mark is used to indicate that the key is not found.
+void HeaderPolicy::readHeaderValueOrQuestionMark(const char *const key, int *outValue,
+        int outValueSize) const {
+    if (outValueSize <= 0) return;
+    if (outValueSize == 1) {
+        outValue[0] = '\0';
+        return;
+    }
+    std::vector<int> keyCodePointVector;
+    HeaderReadWriteUtils::insertCharactersIntoVector(key, &keyCodePointVector);
+    DictionaryHeaderStructurePolicy::AttributeMap::const_iterator it =
+            mAttributeMap.find(keyCodePointVector);
+    if (it == mAttributeMap.end()) {
+        // The key was not found.
+        outValue[0] = '?';
+        outValue[1] = '\0';
+        return;
+    }
+    const int terminalIndex = std::min(static_cast<int>(it->second.size()), outValueSize - 1);
+    for (int i = 0; i < terminalIndex; ++i) {
+        outValue[i] = it->second[i];
+    }
+    outValue[terminalIndex] = '\0';
+}
+
+const std::vector<int> HeaderPolicy::readLocale() const {
+    return HeaderReadWriteUtils::readCodePointVectorAttributeValue(&mAttributeMap, LOCALE_KEY);
+}
+
+float HeaderPolicy::readMultipleWordCostMultiplier() const {
+    const int demotionRate = HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+            MULTIPLE_WORDS_DEMOTION_RATE_KEY, DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE);
+    if (demotionRate <= 0) {
+        return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
+    }
+    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::fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
+        const EntryCounts &entryCounts, const int extendedRegionSize,
+        BufferWithExtendableBuffer *const outBuffer) const {
+    int writingPos = 0;
+    DictionaryHeaderStructurePolicy::AttributeMap attributeMapToWrite(mAttributeMap);
+    fillInHeader(updatesLastDecayedTime, entryCounts, extendedRegionSize, &attributeMapToWrite);
+    if (!HeaderReadWriteUtils::writeDictionaryVersion(outBuffer, mDictFormatVersion,
+            &writingPos)) {
+        return false;
+    }
+    if (!HeaderReadWriteUtils::writeDictionaryFlags(outBuffer, mDictionaryFlags,
+            &writingPos)) {
+        return false;
+    }
+    // Temporarily writes a dummy header size.
+    int headerSizeFieldPos = writingPos;
+    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(outBuffer, 0 /* size */,
+            &writingPos)) {
+        return false;
+    }
+    if (!HeaderReadWriteUtils::writeHeaderAttributes(outBuffer, &attributeMapToWrite,
+            &writingPos)) {
+        return false;
+    }
+    // Writes the actual header size.
+    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(outBuffer, writingPos,
+            &headerSizeFieldPos)) {
+        return false;
+    }
+    return true;
+}
+
+namespace {
+
+int getIndexFromNgramType(const NgramType ngramType) {
+    return static_cast<int>(ngramType);
+}
+
+} // namespace
+
+void HeaderPolicy::fillInHeader(const bool updatesLastDecayedTime,
+        const EntryCounts &entryCounts, const int extendedRegionSize,
+        DictionaryHeaderStructurePolicy::AttributeMap *outAttributeMap) const {
+    for (const auto ngramType : AllNgramTypes::ASCENDING) {
+        HeaderReadWriteUtils::setIntAttribute(outAttributeMap,
+                NGRAM_COUNT_KEYS[getIndexFromNgramType(ngramType)],
+                entryCounts.getNgramCount(ngramType));
+    }
+    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, EXTENDED_REGION_SIZE_KEY,
+            extendedRegionSize);
+    // Set the current time as the generation time.
+    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, DATE_KEY,
+            TimeKeeper::peekCurrentTime());
+    HeaderReadWriteUtils::setCodePointVectorAttribute(outAttributeMap, LOCALE_KEY, mLocale);
+    if (updatesLastDecayedTime) {
+        // Set current time as the last updated time.
+        HeaderReadWriteUtils::setIntAttribute(outAttributeMap, LAST_DECAYED_TIME_KEY,
+                TimeKeeper::peekCurrentTime());
+    }
+}
+
+/* static */ DictionaryHeaderStructurePolicy::AttributeMap
+        HeaderPolicy::createAttributeMapAndReadAllAttributes(const uint8_t *const dictBuf) {
+    DictionaryHeaderStructurePolicy::AttributeMap attributeMap;
+    HeaderReadWriteUtils::fetchAllHeaderAttributes(dictBuf, &attributeMap);
+    return attributeMap;
+}
+
+/* static */ const EntryCounts HeaderPolicy::readNgramCounts() const {
+    MutableEntryCounters entryCounters;
+    for (const auto ngramType : AllNgramTypes::ASCENDING) {
+        const int entryCount = HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                NGRAM_COUNT_KEYS[getIndexFromNgramType(ngramType)], 0 /* defaultValue */);
+        entryCounters.setNgramCount(ngramType, entryCount);
+    }
+    return entryCounters.getEntryCounts();
+}
+
+/* static */ const EntryCounts HeaderPolicy::readMaxNgramCounts() const {
+    MutableEntryCounters entryCounters;
+    for (const auto ngramType : AllNgramTypes::ASCENDING) {
+        const int index = getIndexFromNgramType(ngramType);
+        const int maxEntryCount = HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                MAX_NGRAM_COUNT_KEYS[index], DEFAULT_MAX_NGRAM_COUNTS[index]);
+        entryCounters.setNgramCount(ngramType, maxEntryCount);
+    }
+    return entryCounters.getEntryCounts();
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/header/header_policy.h b/native/jni/src/dictionary/header/header_policy.h
new file mode 100644
index 0000000..47cc919
--- /dev/null
+++ b/native/jni/src/dictionary/header/header_policy.h
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_HEADER_POLICY_H
+#define LATINIME_HEADER_POLICY_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/header/header_read_write_utils.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/utils/entry_counters.h"
+#include "dictionary/utils/format_utils.h"
+#include "utils/char_utils.h"
+#include "utils/time_keeper.h"
+
+namespace latinime {
+
+class HeaderPolicy : public DictionaryHeaderStructurePolicy {
+ public:
+    // Reads information from existing dictionary buffer.
+    HeaderPolicy(const uint8_t *const dictBuf, const FormatUtils::FORMAT_VERSION formatVersion)
+            : mDictFormatVersion(formatVersion),
+              mDictionaryFlags(HeaderReadWriteUtils::getFlags(dictBuf)),
+              mSize(HeaderReadWriteUtils::getHeaderSize(dictBuf)),
+              mAttributeMap(createAttributeMapAndReadAllAttributes(dictBuf)),
+              mLocale(readLocale()),
+              mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
+              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
+              mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
+                      IS_DECAYING_DICT_KEY, false /* defaultValue */)),
+              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      LAST_DECAYED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mNgramCounts(readNgramCounts()), mMaxNgramCounts(readMaxNgramCounts()),
+              mExtendedRegionSize(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      EXTENDED_REGION_SIZE_KEY, 0 /* defaultValue */)),
+              mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue(
+                      &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)),
+              mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue(
+                      &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY,
+                      DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)),
+              mCodePointTable(HeaderReadWriteUtils::readCodePointTable(&mAttributeMap)) {}
+
+    // Constructs header information using an attribute map.
+    HeaderPolicy(const FormatUtils::FORMAT_VERSION dictFormatVersion,
+            const std::vector<int> &locale,
+            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap)
+            : mDictFormatVersion(dictFormatVersion),
+              mDictionaryFlags(HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
+                      attributeMap)), mSize(0), mAttributeMap(*attributeMap), mLocale(locale),
+              mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
+              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
+              mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
+                      IS_DECAYING_DICT_KEY, false /* defaultValue */)),
+              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
+                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
+              mNgramCounts(readNgramCounts()), mMaxNgramCounts(readMaxNgramCounts()),
+              mExtendedRegionSize(0),
+              mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue(
+                      &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)),
+              mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue(
+                      &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY,
+                      DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)),
+              mCodePointTable(HeaderReadWriteUtils::readCodePointTable(&mAttributeMap)) {}
+
+    // Copy header information
+    HeaderPolicy(const HeaderPolicy *const headerPolicy)
+            : mDictFormatVersion(headerPolicy->mDictFormatVersion),
+              mDictionaryFlags(headerPolicy->mDictionaryFlags), mSize(headerPolicy->mSize),
+              mAttributeMap(headerPolicy->mAttributeMap), mLocale(headerPolicy->mLocale),
+              mMultiWordCostMultiplier(headerPolicy->mMultiWordCostMultiplier),
+              mRequiresGermanUmlautProcessing(headerPolicy->mRequiresGermanUmlautProcessing),
+              mIsDecayingDict(headerPolicy->mIsDecayingDict),
+              mDate(headerPolicy->mDate), mLastDecayedTime(headerPolicy->mLastDecayedTime),
+              mNgramCounts(headerPolicy->mNgramCounts),
+              mMaxNgramCounts(headerPolicy->mMaxNgramCounts),
+              mExtendedRegionSize(headerPolicy->mExtendedRegionSize),
+              mHasHistoricalInfoOfWords(headerPolicy->mHasHistoricalInfoOfWords),
+              mForgettingCurveProbabilityValuesTableId(
+                      headerPolicy->mForgettingCurveProbabilityValuesTableId),
+              mCodePointTable(headerPolicy->mCodePointTable) {}
+
+    // Temporary dummy header.
+    HeaderPolicy()
+            : mDictFormatVersion(FormatUtils::UNKNOWN_VERSION), mDictionaryFlags(0), mSize(0),
+              mAttributeMap(), mLocale(CharUtils::EMPTY_STRING), mMultiWordCostMultiplier(0.0f),
+              mRequiresGermanUmlautProcessing(false), mIsDecayingDict(false),
+              mDate(0), mLastDecayedTime(0), mNgramCounts(), mMaxNgramCounts(),
+              mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false),
+              mForgettingCurveProbabilityValuesTableId(0), mCodePointTable(nullptr) {}
+
+    ~HeaderPolicy() {}
+
+    virtual int getFormatVersionNumber() const {
+        // Conceptually this converts the symbolic value we use in the code into the
+        // hardcoded of the bytes in the file. But we want the constants to be the
+        // same so we use them for both here.
+        switch (mDictFormatVersion) {
+            case FormatUtils::VERSION_2:
+            case FormatUtils::VERSION_201:
+                AKLOGE("Dictionary versions 2 and 201 are incompatible with this version");
+                return FormatUtils::UNKNOWN_VERSION;
+            case FormatUtils::VERSION_202:
+                return FormatUtils::VERSION_202;
+            case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+                return FormatUtils::VERSION_4_ONLY_FOR_TESTING;
+            case FormatUtils::VERSION_402:
+                return FormatUtils::VERSION_402;
+            case FormatUtils::VERSION_403:
+                return FormatUtils::VERSION_403;
+            default:
+                return FormatUtils::UNKNOWN_VERSION;
+        }
+    }
+
+    AK_FORCE_INLINE bool isValid() const {
+        // Decaying dictionary must have historical information.
+        if (!mIsDecayingDict) {
+            return true;
+        }
+        if (mHasHistoricalInfoOfWords) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    AK_FORCE_INLINE int getSize() const {
+        return mSize;
+    }
+
+    AK_FORCE_INLINE float getMultiWordCostMultiplier() const {
+        return mMultiWordCostMultiplier;
+    }
+
+    AK_FORCE_INLINE bool isDecayingDict() const {
+        return mIsDecayingDict;
+    }
+
+    AK_FORCE_INLINE bool requiresGermanUmlautProcessing() const {
+        return mRequiresGermanUmlautProcessing;
+    }
+
+    AK_FORCE_INLINE int getDate() const {
+        return mDate;
+    }
+
+    AK_FORCE_INLINE int getLastDecayedTime() const {
+        return mLastDecayedTime;
+    }
+
+    AK_FORCE_INLINE const EntryCounts &getNgramCounts() const {
+        return mNgramCounts;
+    }
+
+    AK_FORCE_INLINE const EntryCounts getMaxNgramCounts() const {
+        return mMaxNgramCounts;
+    }
+
+    AK_FORCE_INLINE int getExtendedRegionSize() const {
+        return mExtendedRegionSize;
+    }
+
+    AK_FORCE_INLINE bool hasHistoricalInfoOfWords() const {
+        return mHasHistoricalInfoOfWords;
+    }
+
+    AK_FORCE_INLINE bool shouldBoostExactMatches() const {
+        // TODO: Investigate better ways to handle exact matches for personalized dictionaries.
+        return !isDecayingDict();
+    }
+
+    const DictionaryHeaderStructurePolicy::AttributeMap *getAttributeMap() const {
+        return &mAttributeMap;
+    }
+
+    AK_FORCE_INLINE int getForgettingCurveProbabilityValuesTableId() const {
+        return mForgettingCurveProbabilityValuesTableId;
+    }
+
+    void readHeaderValueOrQuestionMark(const char *const key,
+            int *outValue, int outValueSize) const;
+
+    bool fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
+            const EntryCounts &entryCounts, const int extendedRegionSize,
+            BufferWithExtendableBuffer *const outBuffer) const;
+
+    void fillInHeader(const bool updatesLastDecayedTime, const EntryCounts &entryCounts,
+            const int extendedRegionSize,
+            DictionaryHeaderStructurePolicy::AttributeMap *outAttributeMap) const;
+
+    AK_FORCE_INLINE const std::vector<int> *getLocale() const {
+        return &mLocale;
+    }
+
+    bool supportsBeginningOfSentence() const {
+        return mDictFormatVersion >= FormatUtils::VERSION_402;
+    }
+
+    const int *getCodePointTable() const {
+        return mCodePointTable;
+    }
+
+ private:
+    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 DATE_KEY;
+    static const char *const LAST_DECAYED_TIME_KEY;
+    static const char *const NGRAM_COUNT_KEYS[];
+    static const char *const MAX_NGRAM_COUNT_KEYS[];
+    static const int DEFAULT_MAX_NGRAM_COUNTS[];
+    static const char *const EXTENDED_REGION_SIZE_KEY;
+    static const char *const HAS_HISTORICAL_INFO_KEY;
+    static const char *const LOCALE_KEY;
+    static const char *const FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY;
+    static const char *const FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY;
+    static const char *const FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY;
+    static const int DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE;
+    static const float MULTIPLE_WORD_COST_MULTIPLIER_SCALE;
+    static const int DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID;
+
+    const FormatUtils::FORMAT_VERSION mDictFormatVersion;
+    const HeaderReadWriteUtils::DictionaryFlags mDictionaryFlags;
+    const int mSize;
+    DictionaryHeaderStructurePolicy::AttributeMap mAttributeMap;
+    const std::vector<int> mLocale;
+    const float mMultiWordCostMultiplier;
+    const bool mRequiresGermanUmlautProcessing;
+    const bool mIsDecayingDict;
+    const int mDate;
+    const int mLastDecayedTime;
+    const EntryCounts mNgramCounts;
+    const EntryCounts mMaxNgramCounts;
+    const int mExtendedRegionSize;
+    const bool mHasHistoricalInfoOfWords;
+    const int mForgettingCurveProbabilityValuesTableId;
+    const int *const mCodePointTable;
+
+    const std::vector<int> readLocale() const;
+    float readMultipleWordCostMultiplier() const;
+    bool readRequiresGermanUmlautProcessing() const;
+    const EntryCounts readNgramCounts() const;
+    const EntryCounts readMaxNgramCounts() const;
+    static DictionaryHeaderStructurePolicy::AttributeMap createAttributeMapAndReadAllAttributes(
+            const uint8_t *const dictBuf);
+};
+} // namespace latinime
+#endif /* LATINIME_HEADER_POLICY_H */
diff --git a/native/jni/src/dictionary/header/header_read_write_utils.cpp b/native/jni/src/dictionary/header/header_read_write_utils.cpp
new file mode 100644
index 0000000..779f8b8
--- /dev/null
+++ b/native/jni/src/dictionary/header/header_read_write_utils.cpp
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/header/header_read_write_utils.h"
+
+#include <cctype>
+#include <cstdio>
+#include <memory>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+// Number of base-10 digits in the largest integer + 1 to leave room for a zero terminator.
+// As such, this is the maximum number of characters will be needed to represent an int as a
+// string, including the terminator; this is used as the size of a string buffer large enough to
+// hold any value that is intended to fit in an integer, e.g. in the code that reads the header
+// of the binary dictionary where a {key,value} string pair scheme is used.
+const int HeaderReadWriteUtils::LARGEST_INT_DIGIT_COUNT = 11;
+
+const int HeaderReadWriteUtils::MAX_ATTRIBUTE_KEY_LENGTH = 256;
+const int HeaderReadWriteUtils::MAX_ATTRIBUTE_VALUE_LENGTH = 2048;
+
+const int HeaderReadWriteUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
+const int HeaderReadWriteUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
+const int HeaderReadWriteUtils::HEADER_FLAG_SIZE = 2;
+const int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
+const char *const HeaderReadWriteUtils::CODE_POINT_TABLE_KEY = "codePointTable";
+
+const HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
+
+typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
+
+/* static */ int HeaderReadWriteUtils::getHeaderSize(const uint8_t *const dictBuf) {
+    // See the format of the header in the comment in
+    // BinaryDictionaryFormatUtils::detectFormatVersion()
+    return ByteArrayUtils::readUint32(dictBuf, HEADER_MAGIC_NUMBER_SIZE
+            + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE);
+}
+
+/* static */ HeaderReadWriteUtils::DictionaryFlags
+        HeaderReadWriteUtils::getFlags(const uint8_t *const dictBuf) {
+    return ByteArrayUtils::readUint16(dictBuf,
+            HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
+}
+
+/* static */ HeaderReadWriteUtils::DictionaryFlags
+        HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
+                const AttributeMap *const attributeMap) {
+    return NO_FLAGS;
+}
+
+/* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(const uint8_t *const dictBuf,
+        AttributeMap *const headerAttributes) {
+    const int headerSize = getHeaderSize(dictBuf);
+    int pos = getHeaderOptionsPosition();
+    if (pos == NOT_A_DICT_POS) {
+        // The header doesn't have header options.
+        return;
+    }
+    int keyBuffer[MAX_ATTRIBUTE_KEY_LENGTH];
+    std::unique_ptr<int[]> valueBuffer(new int[MAX_ATTRIBUTE_VALUE_LENGTH]);
+    while (pos < headerSize) {
+        // The values in the header don't use the code point table for their encoding.
+        const int keyLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
+                MAX_ATTRIBUTE_KEY_LENGTH, nullptr /* codePointTable */, keyBuffer, &pos);
+        std::vector<int> key;
+        key.insert(key.end(), keyBuffer, keyBuffer + keyLength);
+        const int valueLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
+                MAX_ATTRIBUTE_VALUE_LENGTH, nullptr /* codePointTable */, valueBuffer.get(), &pos);
+        std::vector<int> value;
+        value.insert(value.end(), valueBuffer.get(), valueBuffer.get() + valueLength);
+        headerAttributes->insert(AttributeMap::value_type(key, value));
+    }
+}
+
+/* static */ const int *HeaderReadWriteUtils::readCodePointTable(
+        AttributeMap *const headerAttributes) {
+    AttributeMap::key_type keyVector;
+    insertCharactersIntoVector(CODE_POINT_TABLE_KEY, &keyVector);
+    AttributeMap::const_iterator it = headerAttributes->find(keyVector);
+    if (it == headerAttributes->end()) {
+        return nullptr;
+    }
+    return it->second.data();
+}
+
+/* static */ bool HeaderReadWriteUtils::writeDictionaryVersion(
+        BufferWithExtendableBuffer *const buffer, const FormatUtils::FORMAT_VERSION version,
+        int *const writingPos) {
+    if (!buffer->writeUintAndAdvancePosition(FormatUtils::MAGIC_NUMBER, HEADER_MAGIC_NUMBER_SIZE,
+            writingPos)) {
+        return false;
+    }
+    switch (version) {
+        case FormatUtils::VERSION_2:
+        case FormatUtils::VERSION_201:
+        case FormatUtils::VERSION_202:
+            // None of the static dictionaries (v2x) support writing
+            return false;
+        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+        case FormatUtils::VERSION_402:
+        case FormatUtils::VERSION_403:
+            return buffer->writeUintAndAdvancePosition(version /* data */,
+                    HEADER_DICTIONARY_VERSION_SIZE, writingPos);
+        default:
+            return false;
+    }
+}
+
+/* static */ bool HeaderReadWriteUtils::writeDictionaryFlags(
+        BufferWithExtendableBuffer *const buffer, const DictionaryFlags flags,
+        int *const writingPos) {
+    return buffer->writeUintAndAdvancePosition(flags, HEADER_FLAG_SIZE, writingPos);
+}
+
+/* static */ bool HeaderReadWriteUtils::writeDictionaryHeaderSize(
+        BufferWithExtendableBuffer *const buffer, const int size, int *const writingPos) {
+    return buffer->writeUintAndAdvancePosition(size, HEADER_SIZE_FIELD_SIZE, writingPos);
+}
+
+/* static */ bool HeaderReadWriteUtils::writeHeaderAttributes(
+        BufferWithExtendableBuffer *const buffer, const AttributeMap *const headerAttributes,
+        int *const writingPos) {
+    for (AttributeMap::const_iterator it = headerAttributes->begin();
+            it != headerAttributes->end(); ++it) {
+        if (it->first.empty() || it->second.empty()) {
+            continue;
+        }
+        // Write a key.
+        if (!buffer->writeCodePointsAndAdvancePosition(&(it->first.at(0)), it->first.size(),
+                true /* writesTerminator */, writingPos)) {
+            return false;
+        }
+        // Write a value.
+        if (!buffer->writeCodePointsAndAdvancePosition(&(it->second.at(0)), it->second.size(),
+                true /* writesTerminator */, writingPos)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+/* static */ void HeaderReadWriteUtils::setCodePointVectorAttribute(
+        AttributeMap *const headerAttributes, const char *const key,
+        const std::vector<int> &value) {
+    AttributeMap::key_type keyVector;
+    insertCharactersIntoVector(key, &keyVector);
+    (*headerAttributes)[keyVector] = value;
+}
+
+/* static */ void HeaderReadWriteUtils::setBoolAttribute(AttributeMap *const headerAttributes,
+        const char *const key, const bool value) {
+    setIntAttribute(headerAttributes, key, value ? 1 : 0);
+}
+
+/* static */ void HeaderReadWriteUtils::setIntAttribute(AttributeMap *const headerAttributes,
+        const char *const key, const int value) {
+    AttributeMap::key_type keyVector;
+    insertCharactersIntoVector(key, &keyVector);
+    setIntAttributeInner(headerAttributes, &keyVector, value);
+}
+
+/* static */ void HeaderReadWriteUtils::setIntAttributeInner(AttributeMap *const headerAttributes,
+        const AttributeMap::key_type *const key, const int value) {
+    AttributeMap::mapped_type valueVector;
+    char charBuf[LARGEST_INT_DIGIT_COUNT];
+    snprintf(charBuf, sizeof(charBuf), "%d", value);
+    insertCharactersIntoVector(charBuf, &valueVector);
+    (*headerAttributes)[*key] = valueVector;
+}
+
+/* static */ const std::vector<int> HeaderReadWriteUtils::readCodePointVectorAttributeValue(
+        const AttributeMap *const headerAttributes, const char *const key) {
+    AttributeMap::key_type keyVector;
+    insertCharactersIntoVector(key, &keyVector);
+    AttributeMap::const_iterator it = headerAttributes->find(keyVector);
+    if (it == headerAttributes->end()) {
+        return std::vector<int>();
+    } else {
+        return it->second;
+    }
+}
+
+/* static */ bool HeaderReadWriteUtils::readBoolAttributeValue(
+        const AttributeMap *const headerAttributes, const char *const key,
+        const bool defaultValue) {
+    const int intDefaultValue = defaultValue ? 1 : 0;
+    const int intValue = readIntAttributeValue(headerAttributes, key, intDefaultValue);
+    return intValue != 0;
+}
+
+/* static */ int HeaderReadWriteUtils::readIntAttributeValue(
+        const AttributeMap *const headerAttributes, const char *const key,
+        const int defaultValue) {
+    AttributeMap::key_type keyVector;
+    insertCharactersIntoVector(key, &keyVector);
+    return readIntAttributeValueInner(headerAttributes, &keyVector, defaultValue);
+}
+
+/* static */ int HeaderReadWriteUtils::readIntAttributeValueInner(
+        const AttributeMap *const headerAttributes, const AttributeMap::key_type *const key,
+        const int defaultValue) {
+    AttributeMap::const_iterator it = headerAttributes->find(*key);
+    if (it != headerAttributes->end()) {
+        int value = 0;
+        bool isNegative = false;
+        for (size_t i = 0; i < it->second.size(); ++i) {
+            if (i == 0 && it->second.at(i) == '-') {
+                isNegative = true;
+            } else {
+                if (!isdigit(it->second.at(i))) {
+                    // If not a number.
+                    return defaultValue;
+                }
+                value *= 10;
+                value += it->second.at(i) - '0';
+            }
+        }
+        return isNegative ? -value : value;
+    }
+    return defaultValue;
+}
+
+/* static */ void HeaderReadWriteUtils::insertCharactersIntoVector(const char *const characters,
+        std::vector<int> *const vector) {
+    for (int i = 0; characters[i]; ++i) {
+        vector->push_back(characters[i]);
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/header/header_read_write_utils.h b/native/jni/src/dictionary/header/header_read_write_utils.h
new file mode 100644
index 0000000..f67d614
--- /dev/null
+++ b/native/jni/src/dictionary/header/header_read_write_utils.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_HEADER_READ_WRITE_UTILS_H
+#define LATINIME_HEADER_READ_WRITE_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/utils/format_utils.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+
+class HeaderReadWriteUtils {
+ public:
+    typedef uint16_t DictionaryFlags;
+
+    static int getHeaderSize(const uint8_t *const dictBuf);
+
+    static DictionaryFlags getFlags(const uint8_t *const dictBuf);
+
+    static AK_FORCE_INLINE int getHeaderOptionsPosition() {
+        return HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE
+                + HEADER_SIZE_FIELD_SIZE;
+    }
+
+    static DictionaryFlags createAndGetDictionaryFlagsUsingAttributeMap(
+            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
+    static void fetchAllHeaderAttributes(const uint8_t *const dictBuf,
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes);
+
+    static const int *readCodePointTable(
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes);
+
+    static bool writeDictionaryVersion(BufferWithExtendableBuffer *const buffer,
+            const FormatUtils::FORMAT_VERSION version, int *const writingPos);
+
+    static bool writeDictionaryFlags(BufferWithExtendableBuffer *const buffer,
+            const DictionaryFlags flags, int *const writingPos);
+
+    static bool writeDictionaryHeaderSize(BufferWithExtendableBuffer *const buffer,
+            const int size, int *const writingPos);
+
+    static bool writeHeaderAttributes(BufferWithExtendableBuffer *const buffer,
+            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            int *const writingPos);
+
+    /**
+     * Methods for header attributes.
+     */
+    static void setCodePointVectorAttribute(
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key, const std::vector<int> &value);
+
+    static void setBoolAttribute(
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key, const bool value);
+
+    static void setIntAttribute(
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key, const int value);
+
+    static const std::vector<int> readCodePointVectorAttributeValue(
+            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key);
+
+    static bool readBoolAttributeValue(
+            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key, const bool defaultValue);
+
+    static int readIntAttributeValue(
+            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const char *const key, const int defaultValue);
+
+    static void insertCharactersIntoVector(const char *const characters,
+            DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderReadWriteUtils);
+
+    static const int LARGEST_INT_DIGIT_COUNT;
+    static const int MAX_ATTRIBUTE_KEY_LENGTH;
+    static const int MAX_ATTRIBUTE_VALUE_LENGTH;
+
+    static const int HEADER_MAGIC_NUMBER_SIZE;
+    static const int HEADER_DICTIONARY_VERSION_SIZE;
+    static const int HEADER_FLAG_SIZE;
+    static const int HEADER_SIZE_FIELD_SIZE;
+
+    static const char *const CODE_POINT_TABLE_KEY;
+
+    // Value for the "flags" field. It's unused at the moment.
+    static const DictionaryFlags NO_FLAGS;
+
+    static void setIntAttributeInner(
+            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key,
+            const int value);
+
+    static int readIntAttributeValueInner(
+            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
+            const DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key,
+            const int defaultValue);
+};
+}
+#endif /* LATINIME_HEADER_READ_WRITE_UTILS_H */
diff --git a/native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h b/native/jni/src/dictionary/interface/dictionary_bigrams_structure_policy.h
similarity index 100%
rename from native/jni/src/suggest/core/policy/dictionary_bigrams_structure_policy.h
rename to native/jni/src/dictionary/interface/dictionary_bigrams_structure_policy.h
diff --git a/native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h b/native/jni/src/dictionary/interface/dictionary_header_structure_policy.h
similarity index 100%
rename from native/jni/src/suggest/core/policy/dictionary_header_structure_policy.h
rename to native/jni/src/dictionary/interface/dictionary_header_structure_policy.h
diff --git a/native/jni/src/suggest/core/policy/dictionary_shortcuts_structure_policy.h b/native/jni/src/dictionary/interface/dictionary_shortcuts_structure_policy.h
similarity index 100%
rename from native/jni/src/suggest/core/policy/dictionary_shortcuts_structure_policy.h
rename to native/jni/src/dictionary/interface/dictionary_shortcuts_structure_policy.h
diff --git a/native/jni/src/dictionary/interface/dictionary_structure_with_buffer_policy.h b/native/jni/src/dictionary/interface/dictionary_structure_with_buffer_policy.h
new file mode 100644
index 0000000..ace4849
--- /dev/null
+++ b/native/jni/src/dictionary/interface/dictionary_structure_with_buffer_policy.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DICTIONARY_STRUCTURE_POLICY_H
+#define LATINIME_DICTIONARY_STRUCTURE_POLICY_H
+
+#include <memory>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/property/word_attributes.h"
+#include "dictionary/property/word_property.h"
+#include "dictionary/utils/binary_dictionary_shortcut_iterator.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class DicNode;
+class DicNodeVector;
+class DictionaryHeaderStructurePolicy;
+class MultiBigramMap;
+class NgramListener;
+class NgramContext;
+class UnigramProperty;
+
+/*
+ * This class abstracts the structure of dictionaries.
+ * Implement this policy to support additional dictionaries.
+ */
+class DictionaryStructureWithBufferPolicy {
+ public:
+    typedef std::unique_ptr<DictionaryStructureWithBufferPolicy> StructurePolicyPtr;
+
+    virtual ~DictionaryStructureWithBufferPolicy() {}
+
+    virtual int getRootPosition() const = 0;
+
+    virtual void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+            DicNodeVector *const childDicNodes) const = 0;
+
+    virtual int getCodePointsAndReturnCodePointCount(const int wordId, const int maxCodePointCount,
+            int *const outCodePoints) const = 0;
+
+    virtual int getWordId(const CodePointArrayView wordCodePoints,
+            const bool forceLowerCaseSearch) const = 0;
+
+    virtual const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const = 0;
+
+    // TODO: Remove
+    virtual int getProbability(const int unigramProbability, const int bigramProbability) const = 0;
+
+    virtual int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const = 0;
+
+    virtual void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const = 0;
+
+    virtual BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const = 0;
+
+    virtual const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const = 0;
+
+    // Returns whether the update was success or not.
+    virtual bool addUnigramEntry(const CodePointArrayView wordCodePoints,
+            const UnigramProperty *const unigramProperty) = 0;
+
+    // Returns whether the update was success or not.
+    virtual bool removeUnigramEntry(const CodePointArrayView wordCodePoints) = 0;
+
+    // Returns whether the update was success or not.
+    virtual bool addNgramEntry(const NgramProperty *const ngramProperty) = 0;
+
+    // Returns whether the update was success or not.
+    virtual bool removeNgramEntry(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints) = 0;
+
+    // Returns whether the update was success or not.
+    virtual bool updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints, const bool isValidWord,
+            const HistoricalInfo historicalInfo) = 0;
+
+    // Returns whether the flush was success or not.
+    virtual bool flush(const char *const filePath) = 0;
+
+    // Returns whether the GC and flush were success or not.
+    virtual bool flushWithGC(const char *const filePath) = 0;
+
+    virtual bool needsToRunGC(const bool mindsBlockByGC) const = 0;
+
+    // Currently, this method is used only for testing. You may want to consider creating new
+    // dedicated method instead of this if you want to use this in the production.
+    virtual void getProperty(const char *const query, const int queryLength, char *const outResult,
+            const int maxResultLength) = 0;
+
+    virtual const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const = 0;
+
+    // Method to iterate all words in the dictionary.
+    // The returned token has to be used to get the next word. If token is 0, this method newly
+    // starts iterating the dictionary.
+    virtual int getNextWordAndNextToken(const int token, int *const outCodePoints,
+            int *const outCodePointCount) = 0;
+
+    virtual bool isCorrupted() const = 0;
+
+ protected:
+    DictionaryStructureWithBufferPolicy() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DictionaryStructureWithBufferPolicy);
+};
+} // namespace latinime
+#endif /* LATINIME_DICTIONARY_STRUCTURE_POLICY_H */
diff --git a/native/jni/src/dictionary/interface/ngram_listener.h b/native/jni/src/dictionary/interface/ngram_listener.h
new file mode 100644
index 0000000..2eb5e9f
--- /dev/null
+++ b/native/jni/src/dictionary/interface/ngram_listener.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_NGRAM_LISTENER_H
+#define LATINIME_NGRAM_LISTENER_H
+
+#include "defines.h"
+
+namespace latinime {
+
+/**
+ * Interface to iterate ngram entries.
+ */
+class NgramListener {
+ public:
+    // ngramProbability is always 0 for v403 decaying dictionary.
+    // TODO: Remove ngramProbability.
+    virtual void onVisitEntry(const int ngramProbability, const int targetWordId) = 0;
+    virtual ~NgramListener() {};
+
+ protected:
+    NgramListener() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(NgramListener);
+
+};
+} // namespace latinime
+#endif /* LATINIME_NGRAM_LISTENER_H */
diff --git a/native/jni/src/dictionary/property/historical_info.h b/native/jni/src/dictionary/property/historical_info.h
new file mode 100644
index 0000000..e5ce1ea
--- /dev/null
+++ b/native/jni/src/dictionary/property/historical_info.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_HISTORICAL_INFO_H
+#define LATINIME_HISTORICAL_INFO_H
+
+#include "defines.h"
+
+namespace latinime {
+
+class HistoricalInfo {
+ public:
+    // Invalid historical info.
+    HistoricalInfo()
+            : mTimestamp(NOT_A_TIMESTAMP), mLevel(0), mCount(0) {}
+
+    HistoricalInfo(const int timestamp, const int level, const int count)
+            : mTimestamp(timestamp), mLevel(level), mCount(count) {}
+
+    bool isValid() const {
+        return mTimestamp != NOT_A_TIMESTAMP;
+    }
+
+    int getTimestamp() const {
+        return mTimestamp;
+    }
+
+    // TODO: Remove
+    int getLevel() const {
+        return mLevel;
+    }
+
+    int getCount() const {
+        return mCount;
+    }
+
+ private:
+    // Default copy constructor is used for using in std::vector.
+    DISALLOW_ASSIGNMENT_OPERATOR(HistoricalInfo);
+
+    const int mTimestamp;
+    const int mLevel;
+    const int mCount;
+};
+} // namespace latinime
+#endif /* LATINIME_HISTORICAL_INFO_H */
diff --git a/native/jni/src/dictionary/property/ngram_context.cpp b/native/jni/src/dictionary/property/ngram_context.cpp
new file mode 100644
index 0000000..7b9c3ef
--- /dev/null
+++ b/native/jni/src/dictionary/property/ngram_context.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/property/ngram_context.h"
+
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "utils/char_utils.h"
+
+namespace latinime {
+
+NgramContext::NgramContext() : mPrevWordCount(0) {}
+
+NgramContext::NgramContext(const NgramContext &ngramContext)
+        : mPrevWordCount(ngramContext.mPrevWordCount) {
+    for (size_t i = 0; i < mPrevWordCount; ++i) {
+        mPrevWordCodePointCount[i] = ngramContext.mPrevWordCodePointCount[i];
+        memmove(mPrevWordCodePoints[i], ngramContext.mPrevWordCodePoints[i],
+                sizeof(mPrevWordCodePoints[i][0]) * mPrevWordCodePointCount[i]);
+        mIsBeginningOfSentence[i] = ngramContext.mIsBeginningOfSentence[i];
+    }
+}
+
+NgramContext::NgramContext(const int prevWordCodePoints[][MAX_WORD_LENGTH],
+        const int *const prevWordCodePointCount, const bool *const isBeginningOfSentence,
+        const size_t prevWordCount)
+        : mPrevWordCount(std::min(NELEMS(mPrevWordCodePoints), prevWordCount)) {
+    clear();
+    for (size_t i = 0; i < mPrevWordCount; ++i) {
+        if (prevWordCodePointCount[i] < 0 || prevWordCodePointCount[i] > MAX_WORD_LENGTH) {
+            continue;
+        }
+        memmove(mPrevWordCodePoints[i], prevWordCodePoints[i],
+                sizeof(mPrevWordCodePoints[i][0]) * prevWordCodePointCount[i]);
+        mPrevWordCodePointCount[i] = prevWordCodePointCount[i];
+        mIsBeginningOfSentence[i] = isBeginningOfSentence[i];
+    }
+}
+
+NgramContext::NgramContext(const int *const prevWordCodePoints, const int prevWordCodePointCount,
+        const bool isBeginningOfSentence) : mPrevWordCount(1) {
+    clear();
+    if (prevWordCodePointCount > MAX_WORD_LENGTH || !prevWordCodePoints) {
+        return;
+    }
+    memmove(mPrevWordCodePoints[0], prevWordCodePoints,
+            sizeof(mPrevWordCodePoints[0][0]) * prevWordCodePointCount);
+    mPrevWordCodePointCount[0] = prevWordCodePointCount;
+    mIsBeginningOfSentence[0] = isBeginningOfSentence;
+}
+
+bool NgramContext::isValid() const {
+    if (mPrevWordCodePointCount[0] > 0) {
+        return true;
+    }
+    if (mIsBeginningOfSentence[0]) {
+        return true;
+    }
+    return false;
+}
+
+const CodePointArrayView NgramContext::getNthPrevWordCodePoints(const size_t n) const {
+    if (n <= 0 || n > mPrevWordCount) {
+        return CodePointArrayView();
+    }
+    return CodePointArrayView(mPrevWordCodePoints[n - 1], mPrevWordCodePointCount[n - 1]);
+}
+
+bool NgramContext::isNthPrevWordBeginningOfSentence(const size_t n) const {
+    if (n <= 0 || n > mPrevWordCount) {
+        return false;
+    }
+    return mIsBeginningOfSentence[n - 1];
+}
+
+/* static */ int NgramContext::getWordId(
+        const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
+        const int *const wordCodePoints, const int wordCodePointCount,
+        const bool isBeginningOfSentence, const bool tryLowerCaseSearch) {
+    if (!dictStructurePolicy || !wordCodePoints || wordCodePointCount > MAX_WORD_LENGTH) {
+        return NOT_A_WORD_ID;
+    }
+    int codePoints[MAX_WORD_LENGTH];
+    int codePointCount = wordCodePointCount;
+    memmove(codePoints, wordCodePoints, sizeof(int) * codePointCount);
+    if (isBeginningOfSentence) {
+        codePointCount = CharUtils::attachBeginningOfSentenceMarker(codePoints, codePointCount,
+                MAX_WORD_LENGTH);
+        if (codePointCount <= 0) {
+            return NOT_A_WORD_ID;
+        }
+    }
+    const CodePointArrayView codePointArrayView(codePoints, codePointCount);
+    const int wordId = dictStructurePolicy->getWordId(codePointArrayView,
+            false /* forceLowerCaseSearch */);
+    if (wordId != NOT_A_WORD_ID || !tryLowerCaseSearch) {
+        // Return the id when when the word was found or doesn't try lower case search.
+        return wordId;
+    }
+    // Check bigrams for lower-cased previous word if original was not found. Useful for
+    // auto-capitalized words like "The [current_word]".
+    return dictStructurePolicy->getWordId(codePointArrayView, true /* forceLowerCaseSearch */);
+}
+
+void NgramContext::clear() {
+    for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
+        mPrevWordCodePointCount[i] = 0;
+        mIsBeginningOfSentence[i] = false;
+    }
+}
+} // namespace latinime
diff --git a/native/jni/src/dictionary/property/ngram_context.h b/native/jni/src/dictionary/property/ngram_context.h
new file mode 100644
index 0000000..9b36199
--- /dev/null
+++ b/native/jni/src/dictionary/property/ngram_context.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_NGRAM_CONTEXT_H
+#define LATINIME_NGRAM_CONTEXT_H
+
+#include <array>
+
+#include "defines.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class DictionaryStructureWithBufferPolicy;
+
+class NgramContext {
+ public:
+    // No prev word information.
+    NgramContext();
+    // Copy constructor to use this class with std::vector and use this class as a return value.
+    NgramContext(const NgramContext &ngramContext);
+    // Construct from previous words.
+    NgramContext(const int prevWordCodePoints[][MAX_WORD_LENGTH],
+            const int *const prevWordCodePointCount, const bool *const isBeginningOfSentence,
+            const size_t prevWordCount);
+    // Construct from a previous word.
+    NgramContext(const int *const prevWordCodePoints, const int prevWordCodePointCount,
+            const bool isBeginningOfSentence);
+
+    size_t getPrevWordCount() const {
+        return mPrevWordCount;
+    }
+    bool isValid() const;
+
+    template<size_t N>
+    const WordIdArrayView getPrevWordIds(
+            const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
+            WordIdArray<N> *const prevWordIdBuffer, const bool tryLowerCaseSearch) const {
+        for (size_t i = 0; i < std::min(mPrevWordCount, N); ++i) {
+            prevWordIdBuffer->at(i) = getWordId(dictStructurePolicy, mPrevWordCodePoints[i],
+                    mPrevWordCodePointCount[i], mIsBeginningOfSentence[i], tryLowerCaseSearch);
+        }
+        return WordIdArrayView::fromArray(*prevWordIdBuffer).limit(mPrevWordCount);
+    }
+
+    // n is 1-indexed.
+    const CodePointArrayView getNthPrevWordCodePoints(const size_t n) const;
+    // n is 1-indexed.
+    bool isNthPrevWordBeginningOfSentence(const size_t n) const;
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(NgramContext);
+
+    static int getWordId(const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
+            const int *const wordCodePoints, const int wordCodePointCount,
+            const bool isBeginningOfSentence, const bool tryLowerCaseSearch);
+    void clear();
+
+    const size_t mPrevWordCount;
+    int mPrevWordCodePoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH];
+    int mPrevWordCodePointCount[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    bool mIsBeginningOfSentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+};
+} // namespace latinime
+#endif // LATINIME_NGRAM_CONTEXT_H
diff --git a/native/jni/src/dictionary/property/ngram_property.h b/native/jni/src/dictionary/property/ngram_property.h
new file mode 100644
index 0000000..5f259ec
--- /dev/null
+++ b/native/jni/src/dictionary/property/ngram_property.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_NGRAM_PROPERTY_H
+#define LATINIME_NGRAM_PROPERTY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/property/ngram_context.h"
+
+namespace latinime {
+
+class NgramProperty {
+ public:
+    NgramProperty(const NgramContext &ngramContext, const std::vector<int> &&targetCodePoints,
+            const int probability, const HistoricalInfo historicalInfo)
+            : mNgramContext(ngramContext), mTargetCodePoints(std::move(targetCodePoints)),
+              mProbability(probability), mHistoricalInfo(historicalInfo) {}
+
+    const NgramContext *getNgramContext() const {
+        return &mNgramContext;
+    }
+
+    const std::vector<int> *getTargetCodePoints() const {
+        return &mTargetCodePoints;
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    const HistoricalInfo getHistoricalInfo() const {
+        return mHistoricalInfo;
+    }
+
+ private:
+    // Default copy constructor is used for using in std::vector.
+    DISALLOW_DEFAULT_CONSTRUCTOR(NgramProperty);
+    DISALLOW_ASSIGNMENT_OPERATOR(NgramProperty);
+
+    const NgramContext mNgramContext;
+    const std::vector<int> mTargetCodePoints;
+    const int mProbability;
+    const HistoricalInfo mHistoricalInfo;
+};
+} // namespace latinime
+#endif // LATINIME_NGRAM_PROPERTY_H
diff --git a/native/jni/src/dictionary/property/unigram_property.h b/native/jni/src/dictionary/property/unigram_property.h
new file mode 100644
index 0000000..92f61b8
--- /dev/null
+++ b/native/jni/src/dictionary/property/unigram_property.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_UNIGRAM_PROPERTY_H
+#define LATINIME_UNIGRAM_PROPERTY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+
+namespace latinime {
+
+class UnigramProperty {
+ public:
+    class ShortcutProperty {
+     public:
+        ShortcutProperty(const std::vector<int> &&targetCodePoints, const int probability)
+                : mTargetCodePoints(std::move(targetCodePoints)),
+                  mProbability(probability) {}
+
+        const std::vector<int> *getTargetCodePoints() const {
+            return &mTargetCodePoints;
+        }
+
+        int getProbability() const {
+            return mProbability;
+        }
+
+     private:
+        // Default copy constructor is used for using in std::vector.
+        DISALLOW_DEFAULT_CONSTRUCTOR(ShortcutProperty);
+
+        const std::vector<int> mTargetCodePoints;
+        const int mProbability;
+    };
+
+    UnigramProperty()
+            : mRepresentsBeginningOfSentence(false), mIsNotAWord(false),
+              mIsBlacklisted(false), mIsPossiblyOffensive(false), mProbability(NOT_A_PROBABILITY),
+              mHistoricalInfo(), mShortcuts() {}
+
+    // In contexts which do not support the Blacklisted flag (v2, v4<403)
+    UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
+            const bool isPossiblyOffensive, const int probability,
+            const HistoricalInfo historicalInfo, const std::vector<ShortcutProperty> &&shortcuts)
+            : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
+              mIsNotAWord(isNotAWord), mIsBlacklisted(false),
+              mIsPossiblyOffensive(isPossiblyOffensive), mProbability(probability),
+              mHistoricalInfo(historicalInfo), mShortcuts(std::move(shortcuts)) {}
+
+    // Without shortcuts, in contexts which do not support the Blacklisted flag (v2, v4<403)
+    UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
+            const bool isPossiblyOffensive, const int probability,
+            const HistoricalInfo historicalInfo)
+            : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
+              mIsNotAWord(isNotAWord), mIsBlacklisted(false),
+              mIsPossiblyOffensive(isPossiblyOffensive), mProbability(probability),
+              mHistoricalInfo(historicalInfo), mShortcuts() {}
+
+    // In contexts which DO support the Blacklisted flag (v403)
+    UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
+            const bool isBlacklisted, const bool isPossiblyOffensive, const int probability,
+            const HistoricalInfo historicalInfo, const std::vector<ShortcutProperty> &&shortcuts)
+            : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
+              mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted),
+              mIsPossiblyOffensive(isPossiblyOffensive), mProbability(probability),
+              mHistoricalInfo(historicalInfo), mShortcuts(std::move(shortcuts)) {}
+
+    // Without shortcuts, in contexts which DO support the Blacklisted flag (v403)
+    UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
+            const bool isBlacklisted, const bool isPossiblyOffensive, const int probability,
+            const HistoricalInfo historicalInfo)
+            : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
+              mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted),
+              mIsPossiblyOffensive(isPossiblyOffensive), mProbability(probability),
+              mHistoricalInfo(historicalInfo), mShortcuts() {}
+
+    bool representsBeginningOfSentence() const {
+        return mRepresentsBeginningOfSentence;
+    }
+
+    bool isNotAWord() const {
+        return mIsNotAWord;
+    }
+
+    bool isPossiblyOffensive() const {
+        return mIsPossiblyOffensive;
+    }
+
+    bool isBlacklisted() const {
+        return mIsBlacklisted;
+    }
+
+    bool hasShortcuts() const {
+        return !mShortcuts.empty();
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    const HistoricalInfo getHistoricalInfo() const {
+        return mHistoricalInfo;
+    }
+
+    const std::vector<ShortcutProperty> &getShortcuts() const {
+        return mShortcuts;
+    }
+
+ private:
+    // Default copy constructor is used for using as a return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(UnigramProperty);
+
+    const bool mRepresentsBeginningOfSentence;
+    const bool mIsNotAWord;
+    const bool mIsBlacklisted;
+    const bool mIsPossiblyOffensive;
+    const int mProbability;
+    const HistoricalInfo mHistoricalInfo;
+    const std::vector<ShortcutProperty> mShortcuts;
+};
+} // namespace latinime
+#endif // LATINIME_UNIGRAM_PROPERTY_H
diff --git a/native/jni/src/dictionary/property/word_attributes.h b/native/jni/src/dictionary/property/word_attributes.h
new file mode 100644
index 0000000..5351e7d
--- /dev/null
+++ b/native/jni/src/dictionary/property/word_attributes.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_WORD_ATTRIBUTES_H
+#define LATINIME_WORD_ATTRIBUTES_H
+
+#include "defines.h"
+
+class WordAttributes {
+ public:
+    // Invalid word attributes.
+    WordAttributes()
+            : mProbability(NOT_A_PROBABILITY), mIsBlacklisted(false), mIsNotAWord(false),
+              mIsPossiblyOffensive(false) {}
+
+    WordAttributes(const int probability, const bool isBlacklisted, const bool isNotAWord,
+            const bool isPossiblyOffensive)
+            : mProbability(probability), mIsBlacklisted(isBlacklisted), mIsNotAWord(isNotAWord),
+              mIsPossiblyOffensive(isPossiblyOffensive) {}
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    bool isBlacklisted() const {
+        return mIsBlacklisted;
+    }
+
+    bool isNotAWord() const {
+        return mIsNotAWord;
+    }
+
+    // Whether or not a word is possibly offensive.
+    // * Static dictionaries <v202, as well as dynamic dictionaries <v403, will set this based on
+    //   whether or not the probability of the word is zero.
+    // * Static dictionaries >=v203 will set this based on the IS_POSSIBLY_OFFENSIVE PtNode flag.
+    // * Dynamic dictionaries >=v403 will set this based on the IS_POSSIBLY_OFFENSIVE language model
+    //   flag (the PtNode flag IS_BLACKLISTED is ignored and kept as zero)
+    //
+    // See the ::getWordAttributes function for each of these dictionary policies for more details.
+    bool isPossiblyOffensive() const {
+        return mIsPossiblyOffensive;
+    }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(WordAttributes);
+
+    int mProbability;
+    bool mIsBlacklisted;
+    bool mIsNotAWord;
+    bool mIsPossiblyOffensive;
+};
+
+ // namespace
+#endif /* LATINIME_WORD_ATTRIBUTES_H */
diff --git a/native/jni/src/dictionary/property/word_property.h b/native/jni/src/dictionary/property/word_property.h
new file mode 100644
index 0000000..3028e02
--- /dev/null
+++ b/native/jni/src/dictionary/property/word_property.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef LATINIME_WORD_PROPERTY_H
+#define LATINIME_WORD_PROPERTY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/property/ngram_property.h"
+#include "dictionary/property/unigram_property.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+// This class is used for returning information belonging to a word to java side.
+class WordProperty {
+ public:
+    // Default constructor is used to create an instance that indicates an invalid word.
+    WordProperty()
+            : mCodePoints(), mUnigramProperty(), mNgrams() {}
+
+    WordProperty(const std::vector<int> &&codePoints, const UnigramProperty &unigramProperty,
+            const std::vector<NgramProperty> &ngrams)
+            : mCodePoints(std::move(codePoints)), mUnigramProperty(unigramProperty),
+              mNgrams(ngrams) {}
+
+    const CodePointArrayView getCodePoints() const {
+        return CodePointArrayView(mCodePoints);
+    }
+
+    const UnigramProperty &getUnigramProperty() const {
+        return mUnigramProperty;
+    }
+
+    const std::vector<NgramProperty> &getNgramProperties() const {
+        return mNgrams;
+    }
+
+ private:
+    // Default copy constructor is used for using as a return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(WordProperty);
+
+    const std::vector<int> mCodePoints;
+    const UnigramProperty mUnigramProperty;
+    const std::vector<NgramProperty> mNgrams;
+};
+} // namespace latinime
+#endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/Readme.txt b/native/jni/src/dictionary/structure/backward/v402/Readme.txt
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/Readme.txt
rename to native/jni/src/dictionary/structure/backward/v402/Readme.txt
diff --git a/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
new file mode 100644
index 0000000..60749bc
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
+ */
+
+#include "dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/property/ngram_property.h"
+#include "dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
+#include "dictionary/structure/backward/v402/content/bigram_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability,
+        bool *const outHasNext, int *const bigramEntryPos) const {
+    const BigramEntry bigramEntry =
+            mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos);
+    if (outBigramPos) {
+        // Lookup target PtNode position.
+        *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
+                bigramEntry.getTargetTerminalId());
+    }
+    if (outProbability) {
+        if (bigramEntry.hasHistoricalInfo()) {
+            *outProbability =
+                    ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(),
+                            mHeaderPolicy);
+        } else {
+            *outProbability = bigramEntry.getProbability();
+        }
+    }
+    if (outHasNext) {
+        *outHasNext = bigramEntry.hasNext();
+    }
+}
+
+bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
+        const NgramProperty *const ngramProperty, bool *const outAddedNewEntry) {
+    // 1. The word has no bigrams yet.
+    // 2. The word has bigrams, and there is the target in the list.
+    // 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
+    // 4. The word has bigrams. We have to append new bigram entry to the list.
+    // 5. Same as 4, but the list is the last entry of the content file.
+    if (outAddedNewEntry) {
+        *outAddedNewEntry = false;
+    }
+    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+    if (bigramListPos == NOT_A_DICT_POS) {
+        // Case 1. PtNode that doesn't have a bigram list.
+        // Create new bigram list.
+        if (!mBigramDictContent->createNewBigramList(terminalId)) {
+            return false;
+        }
+        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+                newTargetTerminalId);
+        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
+                ngramProperty);
+        // Write an entry.
+        const int writingPos =  mBigramDictContent->getBigramListHeadPos(terminalId);
+        if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) {
+            return false;
+        }
+        if (outAddedNewEntry) {
+            *outAddedNewEntry = true;
+        }
+        return true;
+    }
+
+    int tailEntryPos = NOT_A_DICT_POS;
+    const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos,
+            &tailEntryPos);
+    if (tailEntryPos != NOT_A_DICT_POS || entryPosToUpdate == NOT_A_DICT_POS) {
+        // Case 4, 5.
+        // Add new entry to the bigram list.
+        if (tailEntryPos == NOT_A_DICT_POS) {
+            // Case 4. Create new bigram list.
+            if (!mBigramDictContent->createNewBigramList(terminalId)) {
+                return false;
+            }
+            const int destPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+            // Copy existing bigram list.
+            if (!mBigramDictContent->copyBigramList(bigramListPos, destPos, &tailEntryPos)) {
+                return false;
+            }
+        }
+        // Write new entry at the tail position of the bigram content.
+        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+                newTargetTerminalId);
+        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
+                &newBigramEntry, ngramProperty);
+        if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) {
+            return false;
+        }
+        // Update has next flag of the tail entry.
+        if (!updateHasNextFlag(true /* hasNext */, tailEntryPos)) {
+            return false;
+        }
+        if (outAddedNewEntry) {
+            *outAddedNewEntry = true;
+        }
+        return true;
+    }
+
+    // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry.
+    const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
+    if (!originalBigramEntry.isValid()) {
+        // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing
+        // entry is updated.
+        if (outAddedNewEntry) {
+            *outAddedNewEntry = true;
+        }
+    }
+    const BigramEntry updatedBigramEntry =
+            originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
+    const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
+            &updatedBigramEntry, ngramProperty);
+    return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
+}
+
+bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) {
+    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+    if (bigramListPos == NOT_A_DICT_POS) {
+        // Bigram list doesn't exist.
+        return false;
+    }
+    const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos,
+            nullptr /* outTailEntryPos */);
+    if (entryPosToUpdate == NOT_A_DICT_POS) {
+        // Bigram entry doesn't exist.
+        return false;
+    }
+    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
+    if (targetTerminalId != bigramEntry.getTargetTerminalId()) {
+        // Bigram entry doesn't exist.
+        return false;
+    }
+    // Remove bigram entry by marking it as invalid entry and overwriting the original entry.
+    const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate);
+}
+
+bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
+        int *const outBigramCount) {
+    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+    if (bigramListPos == NOT_A_DICT_POS) {
+        // Bigram list doesn't exist.
+        return true;
+    }
+    bool hasNext = true;
+    int readingPos = bigramListPos;
+    while (hasNext) {
+        const int entryPos = readingPos;
+        const BigramEntry bigramEntry =
+                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+        hasNext = bigramEntry.hasNext();
+        if (!bigramEntry.isValid()) {
+            continue;
+        }
+        const int targetPtNodePos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
+                bigramEntry.getTargetTerminalId());
+        if (targetPtNodePos == NOT_A_DICT_POS) {
+            // Invalidate bigram entry.
+            const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+            if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+                return false;
+            }
+        } else if (bigramEntry.hasHistoricalInfo()) {
+            const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
+                    bigramEntry.getHistoricalInfo(), mHeaderPolicy);
+            if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) {
+                const BigramEntry updatedBigramEntry =
+                        bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo);
+                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+                    return false;
+                }
+                *outBigramCount += 1;
+            } else {
+                // Remove entry.
+                const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
+                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
+                    return false;
+                }
+            }
+        } else {
+            *outBigramCount += 1;
+        }
+    }
+    return true;
+}
+
+int Ver4BigramListPolicy::getBigramEntryConut(const int terminalId) {
+    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
+    if (bigramListPos == NOT_A_DICT_POS) {
+        // Bigram list doesn't exist.
+        return 0;
+    }
+    int bigramCount = 0;
+    bool hasNext = true;
+    int readingPos = bigramListPos;
+    while (hasNext) {
+        const BigramEntry bigramEntry =
+                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+        hasNext = bigramEntry.hasNext();
+        if (bigramEntry.isValid()) {
+            bigramCount++;
+        }
+    }
+    return bigramCount;
+}
+
+int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
+        const int bigramListPos, int *const outTailEntryPos) const {
+    if (outTailEntryPos) {
+        *outTailEntryPos = NOT_A_DICT_POS;
+    }
+    bool hasNext = true;
+    int invalidEntryPos = NOT_A_DICT_POS;
+    int readingPos = bigramListPos;
+    while (hasNext) {
+        const int entryPos = readingPos;
+        const BigramEntry bigramEntry =
+                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+        hasNext = bigramEntry.hasNext();
+        if (bigramEntry.getTargetTerminalId() == targetTerminalIdToFind) {
+            // Entry with same target is found.
+            return entryPos;
+        } else if (!bigramEntry.isValid()) {
+            // Invalid entry that can be reused is found.
+            invalidEntryPos = entryPos;
+        }
+        if (!hasNext && mBigramDictContent->isContentTailPos(readingPos)) {
+            if (outTailEntryPos) {
+                *outTailEntryPos = entryPos;
+            }
+        }
+    }
+    return invalidEntryPos;
+}
+
+const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
+        const BigramEntry *const originalBigramEntry,
+        const NgramProperty *const ngramProperty) const {
+    // TODO: Consolidate historical info and probability.
+    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        const HistoricalInfo &historicalInfoForUpdate = ngramProperty->getHistoricalInfo();
+        const HistoricalInfo updatedHistoricalInfo =
+                ForgettingCurveUtils::createUpdatedHistoricalInfo(
+                        originalBigramEntry->getHistoricalInfo(), ngramProperty->getProbability(),
+                        &historicalInfoForUpdate, mHeaderPolicy);
+        return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
+    } else {
+        return originalBigramEntry->updateProbabilityAndGetEntry(ngramProperty->getProbability());
+    }
+}
+
+bool Ver4BigramListPolicy::updateHasNextFlag(const bool hasNext, const int bigramEntryPos) {
+    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(bigramEntryPos);
+    const BigramEntry updatedBigramEntry = bigramEntry.updateHasNextAndGetEntry(hasNext);
+    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, bigramEntryPos);
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h b/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
new file mode 100644
index 0000000..58c88ce
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ *   suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H
+#define LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_bigrams_structure_policy.h"
+#include "dictionary/structure/backward/v402/content/bigram_entry.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class BigramDictContent;
+} // namespace v402
+} // namespace backward
+class NgramProperty;
+namespace backward {
+namespace v402 {
+} // namespace v402
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v402 {
+class TerminalPositionLookupTable;
+
+class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
+ public:
+    Ver4BigramListPolicy(BigramDictContent *const bigramDictContent,
+            const TerminalPositionLookupTable *const terminalPositionLookupTable,
+            const HeaderPolicy *const headerPolicy)
+            : mBigramDictContent(bigramDictContent),
+              mTerminalPositionLookupTable(terminalPositionLookupTable),
+              mHeaderPolicy(headerPolicy) {}
+
+    void getNextBigram(int *const outBigramPos, int *const outProbability,
+            bool *const outHasNext, int *const bigramEntryPos) const;
+
+    bool skipAllBigrams(int *const pos) const {
+        // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
+        return true;
+    }
+
+    bool addNewEntry(const int terminalId, const int newTargetTerminalId,
+            const NgramProperty *const ngramProperty, bool *const outAddedNewEntry);
+
+    bool removeEntry(const int terminalId, const int targetTerminalId);
+
+    bool updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
+            int *const outBigramCount);
+
+    int getBigramEntryConut(const int terminalId);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy);
+
+    int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos,
+            int *const outTailEntryPos) const;
+
+    const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
+            const NgramProperty *const ngramProperty) const;
+
+    bool updateHasNextFlag(const bool hasNext, const int bigramEntryPos);
+
+    BigramDictContent *const mBigramDictContent;
+    const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
+    const HeaderPolicy *const mHeaderPolicy;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.cpp b/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
new file mode 100644
index 0000000..7fa85de
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/bigram_dict_content.cpp
+ */
+
+#include "dictionary/structure/backward/v402/content/bigram_dict_content.h"
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition(
+        int *const bigramEntryPos) const {
+    const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer();
+    const int bigramEntryTailPos = (*bigramEntryPos) + getBigramEntrySize();
+    if (*bigramEntryPos < 0 || bigramEntryTailPos > bigramListBuffer->getTailPosition()) {
+        AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bigramEntryTailPos: %d, "
+                "bufSize: %d", *bigramEntryPos, bigramEntryTailPos,
+                        bigramListBuffer->getTailPosition());
+        ASSERT(false);
+        return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
+                Ver4DictConstants::NOT_A_TERMINAL_ID);
+    }
+    const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition(
+            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
+    const bool hasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0;
+    int probability = NOT_A_PROBABILITY;
+    int timestamp = NOT_A_TIMESTAMP;
+    int level = 0;
+    int count = 0;
+    if (mHasHistoricalInfo) {
+        timestamp = bigramListBuffer->readUintAndAdvancePosition(
+                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, bigramEntryPos);
+        level = bigramListBuffer->readUintAndAdvancePosition(
+                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, bigramEntryPos);
+        count = bigramListBuffer->readUintAndAdvancePosition(
+                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, bigramEntryPos);
+    } else {
+        probability = bigramListBuffer->readUintAndAdvancePosition(
+                Ver4DictConstants::PROBABILITY_SIZE, bigramEntryPos);
+    }
+    const int encodedTargetTerminalId = bigramListBuffer->readUintAndAdvancePosition(
+            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos);
+    const int targetTerminalId =
+            (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
+                    Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
+    if (mHasHistoricalInfo) {
+        // Hack for better migration.
+        count += level;
+        const HistoricalInfo historicalInfo(timestamp, level, count);
+        return BigramEntry(hasNext, probability, &historicalInfo, targetTerminalId);
+    } else {
+        return BigramEntry(hasNext, probability, targetTerminalId);
+    }
+}
+
+bool BigramDictContent::writeBigramEntryAndAdvancePosition(
+        const BigramEntry *const bigramEntryToWrite, int *const entryWritingPos) {
+    BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer();
+    const int bigramFlags = createAndGetBigramFlags(bigramEntryToWrite->hasNext());
+    if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags,
+            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) {
+        AKLOGE("Cannot write bigram flags. pos: %d, flags: %x", *entryWritingPos, bigramFlags);
+        return false;
+    }
+    if (mHasHistoricalInfo) {
+        const HistoricalInfo *const historicalInfo = bigramEntryToWrite->getHistoricalInfo();
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimestamp(),
+                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
+            AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
+                    historicalInfo->getTimestamp());
+            return false;
+        }
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getLevel(),
+                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
+            AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
+                    historicalInfo->getLevel());
+            return false;
+        }
+        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getCount(),
+                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
+            AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
+                    historicalInfo->getCount());
+            return false;
+        }
+    } else {
+        if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getProbability(),
+                Ver4DictConstants::PROBABILITY_SIZE, entryWritingPos)) {
+            AKLOGE("Cannot write bigram probability. pos: %d, probability: %d", *entryWritingPos,
+                    bigramEntryToWrite->getProbability());
+            return false;
+        }
+    }
+    const int targetTerminalIdToWrite =
+            (bigramEntryToWrite->getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) ?
+                    Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID :
+                            bigramEntryToWrite->getTargetTerminalId();
+    if (!bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite,
+            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos)) {
+        AKLOGE("Cannot write bigram target terminal id. pos: %d, target terminal id: %d",
+                *entryWritingPos, bigramEntryToWrite->getTargetTerminalId());
+        return false;
+    }
+    return true;
+}
+
+bool BigramDictContent::copyBigramList(const int bigramListPos, const int toPos,
+        int *const outTailEntryPos) {
+    int readingPos = bigramListPos;
+    int writingPos = toPos;
+    bool hasNext = true;
+    while (hasNext) {
+        const BigramEntry bigramEntry = getBigramEntryAndAdvancePosition(&readingPos);
+        hasNext = bigramEntry.hasNext();
+        if (!hasNext) {
+            *outTailEntryPos = writingPos;
+        }
+        if (!writeBigramEntryAndAdvancePosition(&bigramEntry, &writingPos)) {
+            AKLOGE("Cannot write bigram entry to copy. pos: %d", writingPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool BigramDictContent::runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const BigramDictContent *const originalBigramDictContent,
+        int *const outBigramEntryCount) {
+    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+            it != terminalIdMap->end(); ++it) {
+        const int originalBigramListPos =
+                originalBigramDictContent->getBigramListHeadPos(it->first);
+        if (originalBigramListPos == NOT_A_DICT_POS) {
+            // This terminal does not have a bigram list.
+            continue;
+        }
+        const int bigramListPos = getContentBuffer()->getTailPosition();
+        int bigramEntryCount = 0;
+        // Copy bigram list with GC from original content.
+        if (!runGCBigramList(originalBigramListPos, originalBigramDictContent, bigramListPos,
+                terminalIdMap, &bigramEntryCount)) {
+            AKLOGE("Cannot complete GC for the bigram list. original pos: %d, pos: %d",
+                    originalBigramListPos, bigramListPos);
+            return false;
+        }
+        if (bigramEntryCount == 0) {
+            // All bigram entries are useless. This terminal does not have a bigram list.
+            continue;
+        }
+        *outBigramEntryCount += bigramEntryCount;
+        // Set bigram list position to the lookup table.
+        if (!getUpdatableAddressLookupTable()->set(it->second, bigramListPos)) {
+            AKLOGE("Cannot set bigram list position. terminal id: %d, pos: %d",
+                    it->second, bigramListPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+// Returns whether GC for the bigram list was succeeded or not.
+bool BigramDictContent::runGCBigramList(const int bigramListPos,
+        const BigramDictContent *const sourceBigramDictContent, const int toPos,
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        int *const outEntrycount) {
+    bool hasNext = true;
+    int readingPos = bigramListPos;
+    int writingPos = toPos;
+    int lastEntryPos = NOT_A_DICT_POS;
+    while (hasNext) {
+        const BigramEntry originalBigramEntry =
+                sourceBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+        hasNext = originalBigramEntry.hasNext();
+        if (originalBigramEntry.getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) {
+            continue;
+        }
+        TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
+                terminalIdMap->find(originalBigramEntry.getTargetTerminalId());
+        if (it == terminalIdMap->end()) {
+            // Target word has been removed.
+            continue;
+        }
+        lastEntryPos = hasNext ? writingPos : NOT_A_DICT_POS;
+        const BigramEntry updatedBigramEntry =
+                originalBigramEntry.updateTargetTerminalIdAndGetEntry(it->second);
+        if (!writeBigramEntryAndAdvancePosition(&updatedBigramEntry, &writingPos)) {
+            AKLOGE("Cannot write bigram entry to run GC. pos: %d", writingPos);
+            return false;
+        }
+        *outEntrycount += 1;
+    }
+    if (lastEntryPos != NOT_A_DICT_POS) {
+        // Update has next flag in the last written entry.
+        const BigramEntry bigramEntry = getBigramEntry(lastEntryPos).updateHasNextAndGetEntry(
+                false /* hasNext */);
+        if (!writeBigramEntry(&bigramEntry, lastEntryPos)) {
+            AKLOGE("Cannot write bigram entry to set hasNext flag after GC. pos: %d", writingPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.h
new file mode 100644
index 0000000..14f334a
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/bigram_dict_content.h
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/bigram_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/bigram_entry.h"
+#include "dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class BigramDictContent : public SparseTableDictContent {
+ public:
+    BigramDictContent(const char *const dictPath, const bool hasHistoricalInfo,
+            const bool isUpdatable)
+            : SparseTableDictContent(dictPath,
+                      Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
+                      Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
+                      Ver4DictConstants::BIGRAM_FILE_EXTENSION, isUpdatable,
+                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
+              mHasHistoricalInfo(hasHistoricalInfo) {}
+
+    BigramDictContent(const bool hasHistoricalInfo)
+            : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
+              mHasHistoricalInfo(hasHistoricalInfo) {}
+
+    const BigramEntry getBigramEntry(const int bigramEntryPos) const {
+        int readingPos = bigramEntryPos;
+        return getBigramEntryAndAdvancePosition(&readingPos);
+    }
+
+    const BigramEntry getBigramEntryAndAdvancePosition(int *const bigramEntryPos) const;
+
+    // Returns head position of bigram list for a PtNode specified by terminalId.
+    int getBigramListHeadPos(const int terminalId) const {
+        const SparseTable *const addressLookupTable = getAddressLookupTable();
+        if (!addressLookupTable->contains(terminalId)) {
+            return NOT_A_DICT_POS;
+        }
+        return addressLookupTable->get(terminalId);
+    }
+
+    bool writeBigramEntryAtTail(const BigramEntry *const bigramEntryToWrite) {
+        int writingPos = getContentBuffer()->getTailPosition();
+        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
+    }
+
+    bool writeBigramEntry(const BigramEntry *const bigramEntryToWrite, const int entryWritingPos) {
+        int writingPos = entryWritingPos;
+        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
+    }
+
+    bool writeBigramEntryAndAdvancePosition(const BigramEntry *const bigramEntryToWrite,
+            int *const entryWritingPos);
+
+    bool createNewBigramList(const int terminalId) {
+        const int bigramListPos = getContentBuffer()->getTailPosition();
+        return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos);
+    }
+
+    bool copyBigramList(const int bigramListPos, const int toPos, int *const outTailEntryPos);
+
+    bool flushToFile(const char *const dictPath) const {
+        return flush(dictPath, Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
+                Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
+                Ver4DictConstants::BIGRAM_FILE_EXTENSION);
+    }
+
+    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+            const BigramDictContent *const originalBigramDictContent,
+            int *const outBigramEntryCount);
+
+    bool isContentTailPos(const int pos) const {
+        return pos == getContentBuffer()->getTailPosition();
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(BigramDictContent);
+
+    int createAndGetBigramFlags(const bool hasNext) const {
+        return hasNext ? Ver4DictConstants::BIGRAM_HAS_NEXT_MASK : 0;
+    }
+
+    int getBigramEntrySize() const {
+        if (mHasHistoricalInfo) {
+            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
+                    + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
+                    + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+                    + Ver4DictConstants::WORD_COUNT_FIELD_SIZE
+                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
+        } else {
+            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
+                    + Ver4DictConstants::PROBABILITY_SIZE
+                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
+        }
+    }
+
+    bool runGCBigramList(const int bigramListPos,
+            const BigramDictContent *const sourceBigramDictContent, const int toPos,
+            const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+            int *const outEntryCount);
+
+    bool mHasHistoricalInfo;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/bigram_entry.h b/native/jni/src/dictionary/structure/backward/v402/content/bigram_entry.h
new file mode 100644
index 0000000..36ad855
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/bigram_entry.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/bigram_entry.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H
+#define LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class BigramEntry {
+ public:
+    BigramEntry(const BigramEntry& bigramEntry)
+            : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
+              mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
+
+    // Entry with historical information.
+    BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
+            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
+              mTargetTerminalId(targetTerminalId) {}
+
+    // Entry with historical information.
+    BigramEntry(const bool hasNext, const int probability,
+            const HistoricalInfo *const historicalInfo, const int targetTerminalId)
+            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
+              mTargetTerminalId(targetTerminalId) {}
+
+    const BigramEntry getInvalidatedEntry() const {
+        return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
+    }
+
+    const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
+        return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
+    }
+
+    const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
+        return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
+    }
+
+    const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
+        return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
+    }
+
+    const BigramEntry updateHistoricalInfoAndGetEntry(
+            const HistoricalInfo *const historicalInfo) const {
+        return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
+    }
+
+    bool isValid() const {
+        return mTargetTerminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
+    }
+
+    bool hasNext() const {
+        return mHasNext;
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    bool hasHistoricalInfo() const {
+        return mHistoricalInfo.isValid();
+    }
+
+    const HistoricalInfo *getHistoricalInfo() const {
+        return &mHistoricalInfo;
+    }
+
+    int getTargetTerminalId() const {
+        return mTargetTerminalId;
+    }
+
+ private:
+    // Copy constructor is public to use this class as a type of return value.
+    DISALLOW_DEFAULT_CONSTRUCTOR(BigramEntry);
+    DISALLOW_ASSIGNMENT_OPERATOR(BigramEntry);
+
+    const bool mHasNext;
+    const int mProbability;
+    const HistoricalInfo mHistoricalInfo;
+    const int mTargetTerminalId;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/dict_content.h
new file mode 100644
index 0000000..d3b84fa
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/dict_content.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_DICT_CONTENT_H
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class DictContent {
+ public:
+    virtual ~DictContent() {}
+    virtual bool isValid() const = 0;
+
+ protected:
+    DictContent() {}
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DictContent);
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.cpp b/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.cpp
new file mode 100644
index 0000000..b167f0a
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/probability_dict_content.cpp
+ */
+
+#include "dictionary/structure/backward/v402/content/probability_dict_content.h"
+
+#include "dictionary/structure/backward/v402/content/probability_entry.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+const ProbabilityEntry ProbabilityDictContent::getProbabilityEntry(const int terminalId) const {
+    if (terminalId < 0 || terminalId >= mSize) {
+        // This method can be called with invalid terminal id during GC.
+        return ProbabilityEntry(0 /* flags */, NOT_A_PROBABILITY);
+    }
+    const BufferWithExtendableBuffer *const buffer = getBuffer();
+    int entryPos = getEntryPos(terminalId);
+    const int flags = buffer->readUintAndAdvancePosition(
+            Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &entryPos);
+    const int probability = buffer->readUintAndAdvancePosition(
+            Ver4DictConstants::PROBABILITY_SIZE, &entryPos);
+    if (mHasHistoricalInfo) {
+        const int timestamp = buffer->readUintAndAdvancePosition(
+                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &entryPos);
+        const int level = buffer->readUintAndAdvancePosition(
+                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &entryPos);
+        const int count = buffer->readUintAndAdvancePosition(
+                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &entryPos);
+        // Hack for better migration.
+        const HistoricalInfo historicalInfo(timestamp, level, count + level);
+        return ProbabilityEntry(flags, probability, &historicalInfo);
+    } else {
+        return ProbabilityEntry(flags, probability);
+    }
+}
+
+bool ProbabilityDictContent::setProbabilityEntry(const int terminalId,
+        const ProbabilityEntry *const probabilityEntry) {
+    if (terminalId < 0) {
+        return false;
+    }
+    const int entryPos = getEntryPos(terminalId);
+    if (terminalId >= mSize) {
+        ProbabilityEntry dummyEntry;
+        // Write new entry.
+        int writingPos = getBuffer()->getTailPosition();
+        while (writingPos <= entryPos) {
+            // Fulfilling with dummy entries until writingPos.
+            if (!writeEntry(&dummyEntry, writingPos)) {
+                AKLOGE("Cannot write dummy entry. pos: %d, mSize: %d", writingPos, mSize);
+                return false;
+            }
+            writingPos += getEntrySize();
+        }
+        mSize = terminalId + 1;
+    }
+    return writeEntry(probabilityEntry, entryPos);
+}
+
+bool ProbabilityDictContent::flushToFile(const char *const dictPath) const {
+    if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
+        ProbabilityDictContent probabilityDictContentToWrite(mHasHistoricalInfo);
+        for (int i = 0; i < mSize; ++i) {
+            const ProbabilityEntry probabilityEntry = getProbabilityEntry(i);
+            if (!probabilityDictContentToWrite.setProbabilityEntry(i, &probabilityEntry)) {
+                AKLOGE("Cannot set probability entry in flushToFile. terminalId: %d", i);
+                return false;
+            }
+        }
+        return probabilityDictContentToWrite.flush(dictPath,
+                Ver4DictConstants::FREQ_FILE_EXTENSION);
+    } else {
+        return flush(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION);
+    }
+}
+
+bool ProbabilityDictContent::runGC(
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const ProbabilityDictContent *const originalProbabilityDictContent) {
+    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+            it != terminalIdMap->end(); ++it) {
+        const ProbabilityEntry probabilityEntry =
+                originalProbabilityDictContent->getProbabilityEntry(it->first);
+        if (!setProbabilityEntry(it->second, &probabilityEntry)) {
+            AKLOGE("Cannot set probability entry in runGC. terminalId: %d", it->second);
+            return false;
+        }
+    }
+    return true;
+}
+
+int ProbabilityDictContent::getEntrySize() const {
+    if (mHasHistoricalInfo) {
+        return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
+                + Ver4DictConstants::PROBABILITY_SIZE
+                + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
+                + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+                + Ver4DictConstants::WORD_COUNT_FIELD_SIZE;
+    } else {
+        return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
+                + Ver4DictConstants::PROBABILITY_SIZE;
+    }
+}
+
+int ProbabilityDictContent::getEntryPos(const int terminalId) const {
+    return terminalId * getEntrySize();
+}
+
+bool ProbabilityDictContent::writeEntry(const ProbabilityEntry *const probabilityEntry,
+        const int entryPos) {
+    BufferWithExtendableBuffer *const bufferToWrite = getWritableBuffer();
+    int writingPos = entryPos;
+    if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getFlags(),
+            Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &writingPos)) {
+        AKLOGE("Cannot write flags in probability dict content. pos: %d", writingPos);
+        return false;
+    }
+    if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getProbability(),
+            Ver4DictConstants::PROBABILITY_SIZE, &writingPos)) {
+        AKLOGE("Cannot write probability in probability dict content. pos: %d", writingPos);
+        return false;
+    }
+    if (mHasHistoricalInfo) {
+        const HistoricalInfo *const historicalInfo = probabilityEntry->getHistoricalInfo();
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimestamp(),
+                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &writingPos)) {
+            AKLOGE("Cannot write timestamp in probability dict content. pos: %d", writingPos);
+            return false;
+        }
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getLevel(),
+                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &writingPos)) {
+            AKLOGE("Cannot write level in probability dict content. pos: %d", writingPos);
+            return false;
+        }
+        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getCount(),
+                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &writingPos)) {
+            AKLOGE("Cannot write count in probability dict content. pos: %d", writingPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.h
new file mode 100644
index 0000000..464b29f
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/probability_dict_content.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/probability_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/single_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class ProbabilityEntry;
+
+class ProbabilityDictContent : public SingleDictContent {
+ public:
+    ProbabilityDictContent(const char *const dictPath, const bool hasHistoricalInfo,
+            const bool isUpdatable)
+            : SingleDictContent(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION, isUpdatable),
+              mHasHistoricalInfo(hasHistoricalInfo),
+              mSize(getBuffer()->getTailPosition() / getEntrySize()) {}
+
+    ProbabilityDictContent(const bool hasHistoricalInfo)
+            : mHasHistoricalInfo(hasHistoricalInfo), mSize(0) {}
+
+    const ProbabilityEntry getProbabilityEntry(const int terminalId) const;
+
+    bool setProbabilityEntry(const int terminalId, const ProbabilityEntry *const probabilityEntry);
+
+    bool flushToFile(const char *const dictPath) const;
+
+    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+            const ProbabilityDictContent *const originalProbabilityDictContent);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(ProbabilityDictContent);
+
+    int getEntrySize() const;
+
+    int getEntryPos(const int terminalId) const;
+
+    bool writeEntry(const ProbabilityEntry *const probabilityEntry, const int entryPos);
+
+    bool mHasHistoricalInfo;
+    int mSize;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/probability_entry.h b/native/jni/src/dictionary/structure/backward/v402/content/probability_entry.h
new file mode 100644
index 0000000..94e36bf
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/probability_entry.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/probability_entry.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H
+#define LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class ProbabilityEntry {
+ public:
+    ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
+            : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
+              mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
+
+    // Dummy entry
+    ProbabilityEntry()
+            : mFlags(0), mProbability(NOT_A_PROBABILITY), mHistoricalInfo() {}
+
+    // Entry without historical information
+    ProbabilityEntry(const int flags, const int probability)
+            : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
+
+    // Entry with historical information.
+    ProbabilityEntry(const int flags, const int probability,
+            const HistoricalInfo *const historicalInfo)
+            : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
+
+    const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
+        return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
+    }
+
+    const ProbabilityEntry createEntryWithUpdatedHistoricalInfo(
+            const HistoricalInfo *const historicalInfo) const {
+        return ProbabilityEntry(mFlags, mProbability, historicalInfo);
+    }
+
+    bool hasHistoricalInfo() const {
+        return mHistoricalInfo.isValid();
+    }
+
+    int getFlags() const {
+        return mFlags;
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    const HistoricalInfo *getHistoricalInfo() const {
+        return &mHistoricalInfo;
+    }
+
+ private:
+    // Copy constructor is public to use this class as a type of return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry);
+
+    const int mFlags;
+    const int mProbability;
+    const HistoricalInfo mHistoricalInfo;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp b/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp
new file mode 100644
index 0000000..e538a02
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/shortcut_dict_content.cpp
+ */
+
+#include "dictionary/structure/backward/v402/content/shortcut_dict_content.h"
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+        int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+        bool *const outhasNext, int *const shortcutEntryPos) const {
+    const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
+    if (*shortcutEntryPos < 0 || *shortcutEntryPos >=  shortcutListBuffer->getTailPosition()) {
+        AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
+                *shortcutEntryPos, shortcutListBuffer->getTailPosition());
+        ASSERT(false);
+        if (outhasNext) {
+            *outhasNext = false;
+        }
+        if (outCodePointCount) {
+            *outCodePointCount = 0;
+        }
+        return;
+    }
+
+    const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+    if (outProbability) {
+        *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
+    }
+    if (outhasNext) {
+        *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+    }
+    if (outCodePoint && outCodePointCount) {
+        shortcutListBuffer->readCodePointsAndAdvancePosition(
+                maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
+    }
+}
+
+int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
+    const SparseTable *const addressLookupTable = getAddressLookupTable();
+    if (!addressLookupTable->contains(terminalId)) {
+        return NOT_A_DICT_POS;
+    }
+    return addressLookupTable->get(terminalId);
+}
+
+bool ShortcutDictContent::flushToFile(const char *const dictPath) const {
+    return flush(dictPath, Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
+            Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
+            Ver4DictConstants::SHORTCUT_FILE_EXTENSION);
+}
+
+bool ShortcutDictContent::runGC(
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const ShortcutDictContent *const originalShortcutDictContent) {
+   for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+           it != terminalIdMap->end(); ++it) {
+       const int originalShortcutListPos =
+               originalShortcutDictContent->getShortcutListHeadPos(it->first);
+       if (originalShortcutListPos == NOT_A_DICT_POS) {
+           continue;
+       }
+       const int shortcutListPos = getContentBuffer()->getTailPosition();
+       // Copy shortcut list from original content.
+       if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
+               shortcutListPos)) {
+           AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
+                   originalShortcutListPos, shortcutListPos);
+           return false;
+       }
+       // Set shortcut list position to the lookup table.
+       if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
+           AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
+                   it->second, shortcutListPos);
+           return false;
+       }
+   }
+   return true;
+}
+
+bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
+    const int shortcutListListPos = getContentBuffer()->getTailPosition();
+    return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
+}
+
+bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
+    return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
+}
+
+bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
+        const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
+    bool hasNext = true;
+    int readingPos = shortcutListPos;
+    int writingPos = toPos;
+    int codePoints[MAX_WORD_LENGTH];
+    while (hasNext) {
+        int probability = 0;
+        int codePointCount = 0;
+        sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
+                codePoints, &codePointCount, &probability, &hasNext, &readingPos);
+        if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
+                hasNext, &writingPos)) {
+            AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
+    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+    const int shortcutFlags = shortcutListBuffer->readUint(
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+    const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+    const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
+    return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+}
+
+bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+        const int codePointCount, const int probability, const bool hasNext,
+        int *const shortcutEntryPos) {
+    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+    const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
+    if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
+        AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
+        return false;
+    }
+    if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
+            true /* writesTerminator */, shortcutEntryPos)) {
+        AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
+        return false;
+    }
+    return true;
+}
+
+// Find a shortcut entry that has specified target and return its position.
+int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
+        const int *const targetCodePointsToFind, const int codePointCount) const {
+    bool hasNext = true;
+    int readingPos = shortcutListPos;
+    int targetCodePoints[MAX_WORD_LENGTH];
+    while (hasNext) {
+        const int entryPos = readingPos;
+        int probability = 0;
+        int targetCodePointCount = 0;
+        getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
+                &probability, &hasNext, &readingPos);
+        if (targetCodePointCount != codePointCount) {
+            continue;
+        }
+        bool matched = true;
+        for (int i = 0; i < codePointCount; ++i) {
+            if (targetCodePointsToFind[i] != targetCodePoints[i]) {
+                matched = false;
+                break;
+            }
+        }
+        if (matched) {
+            return entryPos;
+        }
+    }
+    return NOT_A_DICT_POS;
+}
+
+int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
+        const bool hasNext) const {
+    return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
+            | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.h
new file mode 100644
index 0000000..3b725e8
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/shortcut_dict_content.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/shortcut_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class ShortcutDictContent : public SparseTableDictContent {
+ public:
+    ShortcutDictContent(const char *const dictPath, const bool isUpdatable)
+            : SparseTableDictContent(dictPath,
+                      Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
+                      Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
+                      Ver4DictConstants::SHORTCUT_FILE_EXTENSION, isUpdatable,
+                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+    ShortcutDictContent()
+            : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+    void getShortcutEntry(const int maxCodePointCount, int *const outCodePoint,
+            int *const outCodePointCount, int *const outProbability, bool *const outhasNext,
+            const int shortcutEntryPos) {
+        int readingPos = shortcutEntryPos;
+        return getShortcutEntryAndAdvancePosition(maxCodePointCount, outCodePoint,
+                outCodePointCount, outProbability, outhasNext, &readingPos);
+    }
+
+    void getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+            int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+            bool *const outhasNext, int *const shortcutEntryPos) const;
+
+   // Returns head position of shortcut list for a PtNode specified by terminalId.
+   int getShortcutListHeadPos(const int terminalId) const;
+
+   bool flushToFile(const char *const dictPath) const;
+
+   bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+           const ShortcutDictContent *const originalShortcutDictContent);
+
+   bool createNewShortcutList(const int terminalId);
+
+   bool copyShortcutList(const int shortcutListPos, const int toPos);
+
+   bool setProbability(const int probability, const int shortcutEntryPos);
+
+   bool writeShortcutEntry(const int *const codePoint, const int codePointCount,
+           const int probability, const bool hasNext, const int shortcutEntryPos) {
+       int writingPos = shortcutEntryPos;
+       return writeShortcutEntryAndAdvancePosition(codePoint, codePointCount, probability,
+               hasNext, &writingPos);
+   }
+
+   bool writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+           const int codePointCount, const int probability, const bool hasNext,
+           int *const shortcutEntryPos);
+
+   int findShortcutEntryAndGetPos(const int shortcutListPos,
+           const int *const targetCodePointsToFind, const int codePointCount) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent);
+
+    bool copyShortcutListFromDictContent(const int shortcutListPos,
+            const ShortcutDictContent *const sourceShortcutDictContent, const int toPos);
+
+    int createAndGetShortcutFlags(const int probability, const bool hasNext) const;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/single_dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/single_dict_content.h
new file mode 100644
index 0000000..89df2a1
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/single_dict_content.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/single_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/dict_content.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "dictionary/utils/mmapped_buffer.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class SingleDictContent : public DictContent {
+ public:
+    SingleDictContent(const char *const dictPath, const char *const contentFileName,
+            const bool isUpdatable)
+            : mMmappedBuffer(MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
+              mExpandableContentBuffer(
+                      mMmappedBuffer ? mMmappedBuffer->getReadWriteByteArrayView() :
+                              ReadWriteByteArrayView(),
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mIsValid(mMmappedBuffer) {}
+
+    SingleDictContent()
+            : mMmappedBuffer(nullptr),
+              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), mIsValid(true) {}
+
+    virtual ~SingleDictContent() {}
+
+    virtual bool isValid() const {
+        return mIsValid;
+    }
+
+    bool isNearSizeLimit() const {
+        return mExpandableContentBuffer.isNearSizeLimit();
+    }
+
+ protected:
+    BufferWithExtendableBuffer *getWritableBuffer() {
+        return &mExpandableContentBuffer;
+    }
+
+    const BufferWithExtendableBuffer *getBuffer() const {
+        return &mExpandableContentBuffer;
+    }
+
+    bool flush(const char *const dictPath, const char *const contentFileNameSuffix) const {
+        return DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+                contentFileNameSuffix, &mExpandableContentBuffer);
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(SingleDictContent);
+
+    const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
+    BufferWithExtendableBuffer mExpandableContentBuffer;
+    const bool mIsValid;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp b/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp
new file mode 100644
index 0000000..280f0f8
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/sparse_table_dict_content.cpp
+ */
+
+#include "dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+bool SparseTableDictContent::flush(const char *const dictPath,
+        const char *const lookupTableFileNameSuffix, const char *const addressTableFileNameSuffix,
+        const char *const contentFileNameSuffix) const {
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, lookupTableFileNameSuffix,
+            &mExpandableLookupTableBuffer)){
+        return false;
+    }
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, addressTableFileNameSuffix,
+            &mExpandableAddressTableBuffer)) {
+        return false;
+    }
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, contentFileNameSuffix,
+            &mExpandableContentBuffer)) {
+        return false;
+    }
+    return true;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.h b/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.h
new file mode 100644
index 0000000..4b5af87
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/sparse_table_dict_content.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/sparse_table_dict_content.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H
+#define LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/dict_content.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "dictionary/utils/mmapped_buffer.h"
+#include "dictionary/utils/sparse_table.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+// TODO: Support multiple contents.
+class SparseTableDictContent : public DictContent {
+ public:
+    AK_FORCE_INLINE SparseTableDictContent(const char *const dictPath,
+            const char *const lookupTableFileName, const char *const addressTableFileName,
+            const char *const contentFileName, const bool isUpdatable,
+            const int sparseTableBlockSize, const int sparseTableDataSize)
+            : mLookupTableBuffer(
+                      MmappedBuffer::openBuffer(dictPath, lookupTableFileName, isUpdatable)),
+              mAddressTableBuffer(
+                      MmappedBuffer::openBuffer(dictPath, addressTableFileName, isUpdatable)),
+              mContentBuffer(
+                      MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
+              mExpandableLookupTableBuffer(
+                      mLookupTableBuffer ? mLookupTableBuffer->getReadWriteByteArrayView() :
+                              ReadWriteByteArrayView(),
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mExpandableAddressTableBuffer(
+                      mAddressTableBuffer ? mAddressTableBuffer->getReadWriteByteArrayView() :
+                              ReadWriteByteArrayView(),
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mExpandableContentBuffer(
+                      mContentBuffer ? mContentBuffer->getReadWriteByteArrayView() :
+                              ReadWriteByteArrayView(),
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+                      sparseTableBlockSize, sparseTableDataSize),
+              mIsValid(mLookupTableBuffer && mAddressTableBuffer && mContentBuffer) {}
+
+    SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize)
+            : mLookupTableBuffer(), mAddressTableBuffer(), mContentBuffer(),
+              mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+                      sparseTableBlockSize, sparseTableDataSize), mIsValid(true) {}
+
+    virtual ~SparseTableDictContent() {}
+
+    virtual bool isValid() const {
+        return mIsValid;
+    }
+
+    bool isNearSizeLimit() const {
+        return mExpandableLookupTableBuffer.isNearSizeLimit()
+                || mExpandableAddressTableBuffer.isNearSizeLimit()
+                || mExpandableContentBuffer.isNearSizeLimit();
+    }
+
+ protected:
+    SparseTable *getUpdatableAddressLookupTable() {
+        return &mAddressLookupTable;
+    }
+
+    const SparseTable *getAddressLookupTable() const {
+        return &mAddressLookupTable;
+    }
+
+    BufferWithExtendableBuffer *getWritableContentBuffer() {
+        return &mExpandableContentBuffer;
+    }
+
+    const BufferWithExtendableBuffer *getContentBuffer() const {
+        return &mExpandableContentBuffer;
+    }
+
+    bool flush(const char *const dictDirPath, const char *const lookupTableFileName,
+            const char *const addressTableFileName, const char *const contentFileName) const;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
+
+    const MmappedBuffer::MmappedBufferPtr mLookupTableBuffer;
+    const MmappedBuffer::MmappedBufferPtr mAddressTableBuffer;
+    const MmappedBuffer::MmappedBufferPtr mContentBuffer;
+    BufferWithExtendableBuffer mExpandableLookupTableBuffer;
+    BufferWithExtendableBuffer mExpandableAddressTableBuffer;
+    BufferWithExtendableBuffer mExpandableContentBuffer;
+    SparseTable mAddressLookupTable;
+    const bool mIsValid;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp b/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp
new file mode 100644
index 0000000..30b72bb
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/terminal_position_lookup_table.cpp
+ */
+
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
+    if (terminalId < 0 || terminalId >= mSize) {
+        return NOT_A_DICT_POS;
+    }
+    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;
+}
+
+bool TerminalPositionLookupTable::setTerminalPtNodePosition(
+        const int terminalId, const int terminalPtNodePos) {
+    if (terminalId < 0) {
+        return NOT_A_DICT_POS;
+    }
+    while (terminalId >= mSize) {
+        // Write new entry.
+        if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
+                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
+            return false;
+        }
+        mSize++;
+    }
+    const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
+            terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
+    return getWritableBuffer()->writeUint(terminalPos,
+            Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
+}
+
+bool TerminalPositionLookupTable::flushToFile(const char *const dictPath) 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)) {
+                AKLOGE("Cannot set terminal position to lookupTableToWrite."
+                        " terminalId: %d, position: %d", i, terminalPtNodePosition);
+                return false;
+            }
+        }
+        return lookupTableToWrite.flush(dictPath,
+                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
+    } else {
+        // We can simply use this lookup table because the buffer size has not been
+        // changed.
+        return flush(dictPath, Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
+    }
+}
+
+bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
+    int removedEntryCount = 0;
+    int nextNewTerminalId = 0;
+    for (int i = 0; i < mSize; ++i) {
+        const int terminalPos = getBuffer()->readUint(
+                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
+        if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
+            // This entry is a garbage.
+            removedEntryCount++;
+        } else {
+            // Give a new terminal id to the entry.
+            if (!getWritableBuffer()->writeUint(terminalPos,
+                    Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
+                    getEntryPos(nextNewTerminalId))) {
+                return false;
+            }
+            // Memorize the mapping to the old terminal id to the new terminal id.
+            terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
+            nextNewTerminalId++;
+        }
+    }
+    mSize = nextNewTerminalId;
+    return true;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h b/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h
new file mode 100644
index 0000000..641c749
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/content/terminal_position_lookup_table.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
+#define LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
+
+#include <unordered_map>
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/content/single_dict_content.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class TerminalPositionLookupTable : public SingleDictContent {
+ public:
+    typedef std::unordered_map<int, int> TerminalIdMap;
+
+    TerminalPositionLookupTable(const char *const dictPath, const bool isUpdatable)
+            : SingleDictContent(dictPath,
+                      Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable),
+              mSize(getBuffer()->getTailPosition()
+                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
+
+    TerminalPositionLookupTable() : mSize(0) {}
+
+    int getTerminalPtNodePosition(const int terminalId) const;
+
+    bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos);
+
+    int getNextTerminalId() const {
+        return mSize;
+    }
+
+    bool flushToFile(const char *const dictPath) const;
+
+    bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable);
+
+    int getEntryPos(const int terminalId) const {
+        return terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+    }
+
+    int mSize;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h
new file mode 100644
index 0000000..8cda8c5
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
+#define LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_shortcuts_structure_policy.h"
+#include "dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
+#include "dictionary/structure/backward/v402/content/shortcut_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
+ public:
+    Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
+            const TerminalPositionLookupTable *const terminalPositionLookupTable)
+            : mShortcutDictContent(shortcutDictContent) {}
+
+    ~Ver4ShortcutListPolicy() {}
+
+    int getStartPos(const int pos) const {
+        // The first shortcut entry is located at the head position of the shortcut list.
+        return pos;
+    }
+
+    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
+            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
+            int *const pos) const {
+        int probability = 0;
+        mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount,
+                outCodePoint, outCodePointCount, &probability, outHasNext, pos);
+        if (outIsWhitelist) {
+            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(probability);
+        }
+    }
+
+    void skipAllShortcuts(int *const pos) const {
+        // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries.
+    }
+
+    bool addNewShortcut(const int terminalId, const int *const codePoints, const int codePointCount,
+            const int probability) {
+        const int shortcutListPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
+        if (shortcutListPos == NOT_A_DICT_POS) {
+            // Create shortcut list.
+            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+                return false;
+            }
+            const int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
+            return mShortcutDictContent->writeShortcutEntry(codePoints, codePointCount, probability,
+                    false /* hasNext */, writingPos);
+        }
+        const int entryPos = mShortcutDictContent->findShortcutEntryAndGetPos(shortcutListPos,
+                codePoints, codePointCount);
+        if (entryPos == NOT_A_DICT_POS) {
+            // Add new entry to the shortcut list.
+            // Create new shortcut list.
+            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+                return false;
+            }
+            int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
+            if (!mShortcutDictContent->writeShortcutEntryAndAdvancePosition(codePoints,
+                    codePointCount, probability, true /* hasNext */, &writingPos)) {
+                AKLOGE("Cannot write shortcut entry. terminal id: %d, pos: %d", terminalId,
+                        writingPos);
+                return false;
+            }
+            return mShortcutDictContent->copyShortcutList(shortcutListPos, writingPos);
+        }
+        // Overwrite existing entry.
+        bool hasNext = false;
+        mShortcutDictContent->getShortcutEntry(MAX_WORD_LENGTH, 0 /* outCodePoint */,
+                0 /* outCodePointCount */ , 0 /* probability */, &hasNext, entryPos);
+        if (!mShortcutDictContent->writeShortcutEntry(codePoints,
+                codePointCount, probability, hasNext, entryPos)) {
+            AKLOGE("Cannot overwrite shortcut entry. terminal id: %d, pos: %d", terminalId,
+                    entryPos);
+            return false;
+        }
+        return true;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
+
+    ShortcutDictContent *const mShortcutDictContent;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.cpp
new file mode 100644
index 0000000..4a9704f
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_dict_buffers.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+
+#include <cerrno>
+#include <cstring>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "dictionary/utils/file_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+/* static */ Ver4DictBuffers::Ver4DictBuffersPtr Ver4DictBuffers::openVer4DictBuffers(
+        const char *const dictPath, MmappedBuffer::MmappedBufferPtr headerBuffer,
+        const FormatUtils::FORMAT_VERSION formatVersion) {
+    if (!headerBuffer) {
+        ASSERT(false);
+        AKLOGE("The header buffer must be valid to open ver4 dict buffers.");
+        return Ver4DictBuffersPtr(nullptr);
+    }
+    // TODO: take only dictDirPath, and open both header and trie files in the constructor below
+    const bool isUpdatable = headerBuffer->isUpdatable();
+    return Ver4DictBuffersPtr(new Ver4DictBuffers(dictPath, std::move(headerBuffer), isUpdatable,
+            formatVersion));
+}
+
+bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
+        const BufferWithExtendableBuffer *const headerBuffer) const {
+    // Create temporary directory.
+    const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath,
+            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
+    char tmpDirPath[tmpDirPathBufSize];
+    FileUtils::getFilePathWithSuffix(dictDirPath,
+            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize,
+            tmpDirPath);
+    if (FileUtils::existsDir(tmpDirPath)) {
+        if (!FileUtils::removeDirAndFiles(tmpDirPath)) {
+            AKLOGE("Existing directory %s cannot be removed.", tmpDirPath);
+            ASSERT(false);
+            return false;
+        }
+    }
+    umask(S_IWGRP | S_IWOTH);
+    if (mkdir(tmpDirPath, S_IRWXU) == -1) {
+        AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
+        return false;
+    }
+    // Get dictionary base path.
+    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
+    char dictName[dictNameBufSize];
+    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
+    const int dictPathBufSize = FileUtils::getFilePathBufSize(tmpDirPath, dictName);
+    char dictPath[dictPathBufSize];
+    FileUtils::getFilePath(tmpDirPath, dictName, dictPathBufSize, dictPath);
+
+    // Write header file.
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+            Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
+        AKLOGE("Dictionary header file %s%s cannot be written.", tmpDirPath,
+                Ver4DictConstants::HEADER_FILE_EXTENSION);
+        return false;
+    }
+    // Write trie file.
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+            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(dictPath)) {
+        AKLOGE("Terminal position lookup table cannot be written. %s", tmpDirPath);
+        return false;
+    }
+    if (!mProbabilityDictContent.flushToFile(dictPath)) {
+        AKLOGE("Probability dict content cannot be written. %s", tmpDirPath);
+        return false;
+    }
+    if (!mBigramDictContent.flushToFile(dictPath)) {
+        AKLOGE("Bigram dict content cannot be written. %s", tmpDirPath);
+        return false;
+    }
+    if (!mShortcutDictContent.flushToFile(dictPath)) {
+        AKLOGE("Shortcut dict content cannot be written. %s", tmpDirPath);
+        return false;
+    }
+    // Remove existing dictionary.
+    if (!FileUtils::removeDirAndFiles(dictDirPath)) {
+        AKLOGE("Existing directory %s cannot be removed.", dictDirPath);
+        ASSERT(false);
+        return false;
+    }
+    // Rename temporary directory.
+    if (rename(tmpDirPath, dictDirPath) != 0) {
+        AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath);
+        ASSERT(false);
+        return false;
+    }
+    return true;
+}
+
+Ver4DictBuffers::Ver4DictBuffers(const char *const dictPath,
+        MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
+        const FormatUtils::FORMAT_VERSION formatVersion)
+        : mHeaderBuffer(std::move(headerBuffer)),
+          mDictBuffer(MmappedBuffer::openBuffer(dictPath,
+                  Ver4DictConstants::TRIE_FILE_EXTENSION, isUpdatable)),
+          mHeaderPolicy(mHeaderBuffer->getReadOnlyByteArrayView().data(), formatVersion),
+          mExpandableHeaderBuffer(mHeaderBuffer->getReadWriteByteArrayView(),
+                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+          mExpandableTrieBuffer(
+                  mDictBuffer ? mDictBuffer->getReadWriteByteArrayView() :
+                          ReadWriteByteArrayView(),
+                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+          mTerminalPositionLookupTable(dictPath, isUpdatable),
+          mProbabilityDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
+          mBigramDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
+          mShortcutDictContent(dictPath, isUpdatable),
+          mIsUpdatable(isUpdatable) {}
+
+Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize)
+        : mHeaderBuffer(nullptr), mDictBuffer(nullptr), mHeaderPolicy(headerPolicy),
+          mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+          mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
+          mProbabilityDictContent(headerPolicy->hasHistoricalInfoOfWords()),
+          mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
+          mIsUpdatable(true) {}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.h b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.h
new file mode 100644
index 0000000..0d09fee
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_buffers.h
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_dict_buffers.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H
+#define LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H
+
+#include <memory>
+
+#include "defines.h"
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/backward/v402/content/bigram_dict_content.h"
+#include "dictionary/structure/backward/v402/content/probability_dict_content.h"
+#include "dictionary/structure/backward/v402/content/shortcut_dict_content.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+class Ver4DictBuffers {
+ public:
+    typedef std::unique_ptr<Ver4DictBuffers> Ver4DictBuffersPtr;
+
+    static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
+            MmappedBuffer::MmappedBufferPtr headerBuffer,
+            const FormatUtils::FORMAT_VERSION formatVersion);
+
+    static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
+            const HeaderPolicy *const headerPolicy, const int maxTrieSize) {
+        return Ver4DictBuffersPtr(new Ver4DictBuffers(headerPolicy, maxTrieSize));
+    }
+
+    AK_FORCE_INLINE bool isValid() const {
+        return mHeaderBuffer && mDictBuffer && mHeaderPolicy.isValid()
+                && mProbabilityDictContent.isValid() && mTerminalPositionLookupTable.isValid()
+                && mBigramDictContent.isValid() && mShortcutDictContent.isValid();
+    }
+
+    AK_FORCE_INLINE bool isNearSizeLimit() const {
+        return mExpandableTrieBuffer.isNearSizeLimit()
+                || mTerminalPositionLookupTable.isNearSizeLimit()
+                || mProbabilityDictContent.isNearSizeLimit()
+                || mBigramDictContent.isNearSizeLimit()
+                || mShortcutDictContent.isNearSizeLimit();
+    }
+
+    AK_FORCE_INLINE const HeaderPolicy *getHeaderPolicy() const {
+        return &mHeaderPolicy;
+    }
+
+    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() {
+        return &mExpandableHeaderBuffer;
+    }
+
+    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() {
+        return &mExpandableTrieBuffer;
+    }
+
+    AK_FORCE_INLINE const BufferWithExtendableBuffer *getTrieBuffer() const {
+        return &mExpandableTrieBuffer;
+    }
+
+    AK_FORCE_INLINE TerminalPositionLookupTable *getMutableTerminalPositionLookupTable() {
+        return &mTerminalPositionLookupTable;
+    }
+
+    AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const {
+        return &mTerminalPositionLookupTable;
+    }
+
+    AK_FORCE_INLINE ProbabilityDictContent *getMutableProbabilityDictContent() {
+        return &mProbabilityDictContent;
+    }
+
+    AK_FORCE_INLINE const ProbabilityDictContent *getProbabilityDictContent() const {
+        return &mProbabilityDictContent;
+    }
+
+    AK_FORCE_INLINE BigramDictContent *getMutableBigramDictContent() {
+        return &mBigramDictContent;
+    }
+
+    AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const {
+        return &mBigramDictContent;
+    }
+
+    AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
+        return &mShortcutDictContent;
+    }
+
+    AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const {
+        return &mShortcutDictContent;
+    }
+
+    AK_FORCE_INLINE bool isUpdatable() const {
+        return mIsUpdatable;
+    }
+
+    bool flush(const char *const dictDirPath) const {
+        return flushHeaderAndDictBuffers(dictDirPath, &mExpandableHeaderBuffer);
+    }
+
+    bool flushHeaderAndDictBuffers(const char *const dictDirPath,
+            const BufferWithExtendableBuffer *const headerBuffer) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
+
+    Ver4DictBuffers(const char *const dictDirPath,
+            const MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
+            const FormatUtils::FORMAT_VERSION formatVersion);
+
+    Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize);
+
+    const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
+    const MmappedBuffer::MmappedBufferPtr mDictBuffer;
+    const HeaderPolicy mHeaderPolicy;
+    BufferWithExtendableBuffer mExpandableHeaderBuffer;
+    BufferWithExtendableBuffer mExpandableTrieBuffer;
+    TerminalPositionLookupTable mTerminalPositionLookupTable;
+    ProbabilityDictContent mProbabilityDictContent;
+    BigramDictContent mBigramDictContent;
+    ShortcutDictContent mShortcutDictContent;
+    const int mIsUpdatable;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.cpp
new file mode 100644
index 0000000..2948d07
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_dict_constants.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+// 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";
+const char *const Ver4DictConstants::BIGRAM_FILE_EXTENSION = ".bigram_freq";
+const char *const Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION = ".bigram_lookup";
+const char *const Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION = ".bigram_index_freq";
+const char *const Ver4DictConstants::SHORTCUT_FILE_EXTENSION = ".shortcut_shortcut";
+const char *const Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION = ".shortcut_lookup";
+const char *const Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION =
+        ".shortcut_index_shortcut";
+
+// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets.
+const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 8 * 1024 * 1024;
+// Extended region size, which is not GCed region size in dict file + additional buffer size, is
+// limited to 1MB to prevent from inefficient traversing.
+const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
+
+const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
+const int Ver4DictConstants::PROBABILITY_SIZE = 1;
+const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
+const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
+const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
+const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
+const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4;
+const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 1;
+const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 1;
+
+const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
+const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4;
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
+
+const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3;
+// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing
+// invalid terminal ID in bigram lists.
+const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID =
+        (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1;
+const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1;
+const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F;
+const int Ver4DictConstants::BIGRAM_HAS_NEXT_MASK = 0x80;
+const int Ver4DictConstants::BIGRAM_LARGE_PROBABILITY_FIELD_SIZE = 1;
+
+const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
+const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
+const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.h b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.h
new file mode 100644
index 0000000..15581d8
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_dict_constants.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_dict_constants.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H
+#define LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+// TODO: Create PtConstants under the pt_common and move some constant values there.
+// Note that there are corresponding definitions in FormatSpec.java.
+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;
+    static const char *const BIGRAM_LOOKUP_TABLE_FILE_EXTENSION;
+    static const char *const BIGRAM_CONTENT_TABLE_FILE_EXTENSION;
+    static const char *const SHORTCUT_FILE_EXTENSION;
+    static const char *const SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION;
+    static const char *const SHORTCUT_CONTENT_TABLE_FILE_EXTENSION;
+
+    static const int MAX_DICTIONARY_SIZE;
+    static const int MAX_DICT_EXTENDED_REGION_SIZE;
+
+    static const int NOT_A_TERMINAL_ID;
+    static const int PROBABILITY_SIZE;
+    static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
+    static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+    static const int NOT_A_TERMINAL_ADDRESS;
+    static const int TERMINAL_ID_FIELD_SIZE;
+    static const int TIME_STAMP_FIELD_SIZE;
+    static const int WORD_LEVEL_FIELD_SIZE;
+    static const int WORD_COUNT_FIELD_SIZE;
+
+    static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE;
+    static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE;
+    static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
+    static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
+
+    static const int BIGRAM_FLAGS_FIELD_SIZE;
+    static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
+    static const int INVALID_BIGRAM_TARGET_TERMINAL_ID;
+    static const int BIGRAM_PROBABILITY_MASK;
+    static const int BIGRAM_HAS_NEXT_MASK;
+    // Used when bigram list has time stamp.
+    static const int BIGRAM_LARGE_PROBABILITY_FIELD_SIZE;
+
+    static const int SHORTCUT_FLAGS_FIELD_SIZE;
+    static const int SHORTCUT_PROBABILITY_MASK;
+    static const int SHORTCUT_HAS_NEXT_MASK;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp
new file mode 100644
index 0000000..871ef7a
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/backward/v402/content/probability_dict_content.h"
+#include "dictionary/structure/backward/v402/content/probability_entry.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
+        const int ptNodePos, const int siblingNodePos) const {
+    if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
+                ptNodePos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return PtNodeParams();
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int pos = ptNodePos;
+    const int headPos = ptNodePos;
+    if (usesAdditionalBuffer) {
+        pos -= mBuffer->getOriginalBufferSize();
+    }
+    const PatriciaTrieReadingUtils::NodeFlags flags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const int parentPosOffset =
+            DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
+                    dictBuf, &pos);
+    const int parentPos =
+            DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
+    int codePoints[MAX_WORD_LENGTH];
+    const int codePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
+            dictBuf, flags, MAX_WORD_LENGTH, mHeaderPolicy->getCodePointTable(), codePoints, &pos);
+    int terminalIdFieldPos = NOT_A_DICT_POS;
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    int probability = NOT_A_PROBABILITY;
+    if (PatriciaTrieReadingUtils::isTerminal(flags)) {
+        terminalIdFieldPos = pos;
+        if (usesAdditionalBuffer) {
+            terminalIdFieldPos += mBuffer->getOriginalBufferSize();
+        }
+        terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
+        const ProbabilityEntry probabilityEntry =
+                mProbabilityDictContent->getProbabilityEntry(terminalId);
+        if (probabilityEntry.hasHistoricalInfo()) {
+            probability = ForgettingCurveUtils::decodeProbability(
+                    probabilityEntry.getHistoricalInfo(), mHeaderPolicy);
+        } else {
+            probability = probabilityEntry.getProbability();
+        }
+    }
+    int childrenPosFieldPos = pos;
+    if (usesAdditionalBuffer) {
+        childrenPosFieldPos += mBuffer->getOriginalBufferSize();
+    }
+    int childrenPos = DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
+            dictBuf, &pos);
+    if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
+        childrenPos += mBuffer->getOriginalBufferSize();
+    }
+    if (usesAdditionalBuffer) {
+        pos += mBuffer->getOriginalBufferSize();
+    }
+    // Sibling position is the tail position of original PtNode.
+    int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos;
+    // Read destination node if the read node is a moved node.
+    if (DynamicPtReadingUtils::isMoved(flags)) {
+        // The destination position is stored at the same place as the parent position.
+        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
+    } else {
+        return PtNodeParams(headPos, flags, parentPos, codePointCount, codePoints,
+                terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos,
+                newSiblingNodePos);
+    }
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
new file mode 100644
index 0000000..367d6f9
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_node_reader.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H
+#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_reader.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v402 {
+} // namespace v402
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v402 {
+class ProbabilityDictContent;
+
+/*
+ * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
+ * node and reads node attributes including probability form probabilityBuffer.
+ */
+class Ver4PatriciaTrieNodeReader : public PtNodeReader {
+ public:
+    Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
+            const ProbabilityDictContent *const probabilityDictContent,
+            const HeaderPolicy *const headerPolicy)
+            : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent),
+              mHeaderPolicy(headerPolicy) {}
+
+    ~Ver4PatriciaTrieNodeReader() {}
+
+    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
+        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
+                NOT_A_DICT_POS /* siblingNodePos */);
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
+
+    const BufferWithExtendableBuffer *const mBuffer;
+    const ProbabilityDictContent *const mProbabilityDictContent;
+    const HeaderPolicy *const mHeaderPolicy;
+
+    const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
+            const int siblingNodePos) const;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
new file mode 100644
index 0000000..e3ab5ec
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
@@ -0,0 +1,442 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
+#include "dictionary/structure/backward/v402/content/probability_entry.h"
+#include "dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3;
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted(
+        const PtNodeParams *const toBeUpdatedPtNodeParams) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+                    true /* isDeleted */, false /* willBecomeNonTerminal */);
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    // Update flags.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos)) {
+        return false;
+    }
+    if (toBeUpdatedPtNodeParams->isTerminal()) {
+        // The PtNode is a terminal. Delete entry from the terminal position lookup table.
+        return mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+                toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */);
+    } else {
+        return true;
+    }
+}
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const int movedPos, const int bigramLinkedNodePos) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
+                    false /* isDeleted */, false /* willBecomeNonTerminal */);
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    // Update flags.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos)) {
+        return false;
+    }
+    // Update moved position, which is stored in the parent offset field.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+            mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+        return false;
+    }
+    if (toBeUpdatedPtNodeParams->hasChildren()) {
+        // Update children's parent position.
+        mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
+        while (!mReadingHelper.isEnd()) {
+            const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams());
+            int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
+                    + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+            if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+                    mTrieBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
+                    &parentOffsetFieldPos)) {
+                // Parent offset cannot be written because of a bug or a broken dictionary; thus,
+                // we give up to update dictionary.
+                return false;
+            }
+            mReadingHelper.readNextSiblingNode(childPtNodeParams);
+        }
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsWillBecomeNonTerminal(
+        const PtNodeParams *const toBeUpdatedPtNodeParams) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+                    false /* isDeleted */, true /* willBecomeNonTerminal */);
+    if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+            toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */)) {
+        AKLOGE("Cannot update terminal position lookup table. terminal id: %d",
+                toBeUpdatedPtNodeParams->getTerminalId());
+        return false;
+    }
+    // Update flags.
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    return DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const UnigramProperty *const unigramProperty) {
+    // Update probability and historical information.
+    // TODO: Update other information in the unigram property.
+    if (!toBeUpdatedPtNodeParams->isTerminal()) {
+        return false;
+    }
+    const ProbabilityEntry originalProbabilityEntry =
+            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+                    toBeUpdatedPtNodeParams->getTerminalId());
+    const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
+            unigramProperty);
+    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+            toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+        const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
+    if (!toBeUpdatedPtNodeParams->isTerminal()) {
+        AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
+        return false;
+    }
+    const ProbabilityEntry originalProbabilityEntry =
+            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+                    toBeUpdatedPtNodeParams->getTerminalId());
+    if (originalProbabilityEntry.hasHistoricalInfo()) {
+        const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
+                originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy);
+        const ProbabilityEntry probabilityEntry =
+                originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo);
+        if (!mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+                toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) {
+            AKLOGE("Cannot write updated probability entry. terminalId: %d",
+                    toBeUpdatedPtNodeParams->getTerminalId());
+            return false;
+        }
+        const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy);
+        if (!isValid) {
+            if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
+                AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
+                return false;
+            }
+        }
+        *outNeedsToKeepPtNode = isValid;
+    } else {
+        // No need to update probability.
+        *outNeedsToKeepPtNode = true;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
+        const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
+    int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
+    return DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+            newChildrenPosition, &childrenPosFieldPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const int newTerminalId) {
+    return mTrieBuffer->writeUint(newTerminalId, Ver4DictConstants::TERMINAL_ID_FIELD_SIZE,
+            toBeUpdatedPtNodeParams->getTerminalIdFieldPos());
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) {
+    return writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, 0 /* outTerminalId */,
+            ptNodeWritingPos);
+}
+
+
+bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, const UnigramProperty *const unigramProperty,
+        int *const ptNodeWritingPos) {
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (!writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, &terminalId,
+            ptNodeWritingPos)) {
+        return false;
+    }
+    // Write probability.
+    ProbabilityEntry newProbabilityEntry;
+    const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
+            &newProbabilityEntry, unigramProperty);
+    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(terminalId,
+            &probabilityEntryToWrite);
+}
+
+bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
+        const NgramProperty *const ngramProperty, bool *const outAddedNewEntry) {
+    if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, ngramProperty, outAddedNewEntry)) {
+        AKLOGE("Cannot add new bigram entry. prevWordId: %d, wordId: %d",
+                prevWordIds[0], wordId);
+        return false;
+    }
+    const int ptNodePos =
+            mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(prevWordIds[0]);
+    const PtNodeParams sourcePtNodeParams =
+            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    if (!sourcePtNodeParams.hasBigrams()) {
+        // Update has bigrams flag.
+        return updatePtNodeFlags(sourcePtNodeParams.getHeadPos(),
+                sourcePtNodeParams.isPossiblyOffensive(), sourcePtNodeParams.isNotAWord(),
+                sourcePtNodeParams.isTerminal(), sourcePtNodeParams.hasShortcutTargets(),
+                true /* hasBigrams */,
+                sourcePtNodeParams.getCodePointCount() > 1 /* hasMultipleChars */);
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
+        const int wordId) {
+    return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
+            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
+    return mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(
+            sourcePtNodeParams->getTerminalId(), outBigramEntryCount);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const DictPositionRelocationMap *const dictPositionRelocationMap,
+        int *const outBigramEntryCount) {
+    int parentPos = toBeUpdatedPtNodeParams->getParentPos();
+    if (parentPos != NOT_A_DICT_POS) {
+        PtNodeWriter::PtNodePositionRelocationMap::const_iterator it =
+                dictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
+        if (it != dictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
+            parentPos = it->second;
+        }
+    }
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos()
+            + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+    // Write updated parent offset.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+            parentPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+        return false;
+    }
+
+    // Updates children position.
+    int childrenPos = toBeUpdatedPtNodeParams->getChildrenPos();
+    if (childrenPos != NOT_A_DICT_POS) {
+        PtNodeWriter::PtNodeArrayPositionRelocationMap::const_iterator it =
+                dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
+        if (it != dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
+            childrenPos = it->second;
+        }
+    }
+    if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
+        return false;
+    }
+
+    // Counts bigram entries.
+    if (outBigramEntryCount) {
+        *outBigramEntryCount = mBigramPolicy->getBigramEntryConut(
+                toBeUpdatedPtNodeParams->getTerminalId());
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptNodeParams,
+        const int *const targetCodePoints, const int targetCodePointCount,
+        const int shortcutProbability) {
+    if (!mShortcutPolicy->addNewShortcut(ptNodeParams->getTerminalId(),
+            targetCodePoints, targetCodePointCount, shortcutProbability)) {
+        AKLOGE("Cannot add new shortcut entry. terminalId: %d", ptNodeParams->getTerminalId());
+        return false;
+    }
+    if (!ptNodeParams->hasShortcutTargets()) {
+        // Update has shortcut targets flag.
+        return updatePtNodeFlags(ptNodeParams->getHeadPos(),
+                ptNodeParams->isPossiblyOffensive(), ptNodeParams->isNotAWord(),
+                ptNodeParams->isTerminal(), true /* hasShortcutTargets */,
+                ptNodeParams->hasBigrams(),
+                ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeHasBigramsAndShortcutTargetsFlags(
+        const PtNodeParams *const ptNodeParams) {
+    const bool hasBigrams = mBuffers->getBigramDictContent()->getBigramListHeadPos(
+            ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
+    const bool hasShortcutTargets = mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
+            ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
+    return updatePtNodeFlags(ptNodeParams->getHeadPos(), ptNodeParams->isPossiblyOffensive(),
+            ptNodeParams->isNotAWord(), ptNodeParams->isTerminal(), hasShortcutTargets,
+            hasBigrams, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+        int *const ptNodeWritingPos) {
+    const int nodePos = *ptNodeWritingPos;
+    // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the
+    // PtNode writing.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer,
+            0 /* nodeFlags */, ptNodeWritingPos)) {
+        return false;
+    }
+    // Calculate a parent offset and write the offset.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) {
+        return false;
+    }
+    // Write code points
+    if (!DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) {
+        return false;
+    }
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (!ptNodeParams->willBecomeNonTerminal()) {
+        if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) {
+            terminalId = ptNodeParams->getTerminalId();
+        } else if (ptNodeParams->isTerminal()) {
+            // Write terminal information using a new terminal id.
+            // Get a new unused terminal id.
+            terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId();
+        }
+    }
+    const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (isTerminal) {
+        // Update the lookup table.
+        if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+                terminalId, nodePos)) {
+            return false;
+        }
+        // Write terminal Id.
+        if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId,
+                Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) {
+            return false;
+        }
+        if (outTerminalId) {
+            *outTerminalId = terminalId;
+        }
+    }
+    // Write children position
+    if (!DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getChildrenPos(), ptNodeWritingPos)) {
+        return false;
+    }
+    return updatePtNodeFlags(nodePos, ptNodeParams->isPossiblyOffensive(),
+            ptNodeParams->isNotAWord(), isTerminal, ptNodeParams->hasShortcutTargets(),
+            ptNodeParams->hasBigrams(),
+            ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+}
+
+const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
+        const ProbabilityEntry *const originalProbabilityEntry,
+        const UnigramProperty *const unigramProperty) const {
+    // TODO: Consolidate historical info and probability.
+    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        const HistoricalInfo &historicalInfoForUpdate = unigramProperty->getHistoricalInfo();
+        const HistoricalInfo updatedHistoricalInfo =
+                ForgettingCurveUtils::createUpdatedHistoricalInfo(
+                        originalProbabilityEntry->getHistoricalInfo(),
+                        unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
+        return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
+                &updatedHistoricalInfo);
+    } else {
+        return originalProbabilityEntry->createEntryWithUpdatedProbability(
+                unigramProperty->getProbability());
+    }
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
+        const bool isBlacklisted, const bool isNotAWord, const bool isTerminal,
+        const bool hasShortcutTargets, const bool hasBigrams, const bool hasMultipleChars) {
+    // Create node flags and write them.
+    PatriciaTrieReadingUtils::NodeFlags nodeFlags =
+            PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, isTerminal,
+                    hasShortcutTargets, hasBigrams, hasMultipleChars,
+                    CHILDREN_POSITION_FIELD_SIZE);
+    if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
+        AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::suppressUnigramEntry(const PtNodeParams *const ptNodeParams) {
+    if (!mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        // Require historical info to suppress unigram entry.
+        return false;
+    }
+    const HistoricalInfo suppressedHistorycalInfo(0 /* timestamp */, 0 /* level */, 0 /* count */);
+    const ProbabilityEntry probabilityEntryToWrite =
+            ProbabilityEntry().createEntryWithUpdatedHistoricalInfo(&suppressedHistorycalInfo);
+    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+            ptNodeParams->getTerminalId(), &probabilityEntryToWrite);
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
new file mode 100644
index 0000000..db3cea1
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H
+#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_writer.h"
+#include "dictionary/structure/backward/v402/content/probability_entry.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v402 {
+} // namespace v402
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v402 {
+class Ver4BigramListPolicy;
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PtNodeArrayReader;
+class Ver4ShortcutListPolicy;
+
+/*
+ * This class is used for helping to writes nodes of ver4 patricia trie.
+ */
+class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
+ public:
+    Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer,
+            Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy,
+            const PtNodeReader *const ptNodeReader,
+            const PtNodeArrayReader *const ptNodeArrayReader,
+            Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy)
+            : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy),
+              mPtNodeReader(ptNodeReader), mReadingHelper(ptNodeReader, ptNodeArrayReader),
+              mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy) {}
+
+    virtual ~Ver4PatriciaTrieNodeWriter() {}
+
+    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int movedPos, const int bigramLinkedNodePos);
+
+    virtual bool markPtNodeAsWillBecomeNonTerminal(
+            const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const UnigramProperty *const unigramProperty);
+
+    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+            const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
+
+    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int newChildrenPosition);
+
+    bool updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int newTerminalId);
+
+    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            int *const ptNodeWritingPos);
+
+    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
+
+    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
+            const NgramProperty *const ngramProperty, bool *const outAddedNewEntry);
+
+    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId);
+
+    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
+            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount);
+
+    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const DictPositionRelocationMap *const dictPositionRelocationMap,
+            int *const outBigramEntryCount);
+
+    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
+            const int *const targetCodePoints, const int targetCodePointCount,
+            const int shortcutProbability);
+
+    bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
+
+    // Suppress unigram not to use the word for generating suggestions. So, this method can be used
+    // only for dictionaries with historical info. Also, suppressed entries are included in unigram
+    // count. They will be removed from the dictionary during GC.
+    bool suppressUnigramEntry(const PtNodeParams *const ptNodeParams);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
+
+    bool writePtNodeAndGetTerminalIdAndAdvancePosition(
+            const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+            int *const ptNodeWritingPos);
+
+    // Create updated probability entry using given unigram property. In addition to the
+    // probability, this method updates historical information if needed.
+    // TODO: Update flags belonging to the unigram property.
+    const ProbabilityEntry createUpdatedEntryFrom(
+            const ProbabilityEntry *const originalProbabilityEntry,
+            const UnigramProperty *const unigramProperty) const;
+
+    bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
+            const bool isTerminal, const bool hasShortcutTargets, const bool hasBigrams,
+            const bool hasMultipleChars);
+
+    static const int CHILDREN_POSITION_FIELD_SIZE;
+
+    BufferWithExtendableBuffer *const mTrieBuffer;
+    Ver4DictBuffers *const mBuffers;
+    const HeaderPolicy *const mHeaderPolicy;
+    const PtNodeReader *const mPtNodeReader;
+    DynamicPtReadingHelper mReadingHelper;
+    Ver4BigramListPolicy *const mBigramPolicy;
+    Ver4ShortcutListPolicy *const mShortcutPolicy;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
new file mode 100644
index 0000000..6fb9cff
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -0,0 +1,662 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_policy.h"
+
+#include <vector>
+
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "dictionary/interface/ngram_listener.h"
+#include "dictionary/property/ngram_context.h"
+#include "dictionary/property/ngram_property.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/property/word_property.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+#include "dictionary/utils/multi_bigram_map.h"
+#include "dictionary/utils/probability_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+// Note that there are corresponding definitions in Java side in BinaryDictionaryTests and
+// BinaryDictionaryDecayingTests.
+const char *const Ver4PatriciaTriePolicy::UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
+const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024;
+const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
+        Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+const int Ver4PatriciaTriePolicy::DUMMY_PROBABILITY_FOR_VALID_WORDS = 1;
+
+void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
+        DicNodeVector *const childDicNodes) const {
+    if (!dicNode->hasChildren()) {
+        return;
+    }
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
+    while (!readingHelper.isEnd()) {
+        const PtNodeParams ptNodeParams = readingHelper.getPtNodeParams();
+        if (!ptNodeParams.isValid()) {
+            break;
+        }
+        bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
+        if (isTerminal && mHeaderPolicy->isDecayingDict()) {
+            // A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
+            // probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
+            // valid terminal DicNode.
+            isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
+        }
+        readingHelper.readNextSiblingNode(ptNodeParams);
+        if (ptNodeParams.representsNonWordInfo()) {
+            // Skip PtNodes that represent non-word information.
+            continue;
+        }
+        const int wordId = isTerminal ? ptNodeParams.getHeadPos() : NOT_A_WORD_ID;
+        childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getChildrenPos(),
+                wordId, ptNodeParams.getCodePointArrayView());
+    }
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
+    }
+}
+
+int Ver4PatriciaTriePolicy::getCodePointsAndReturnCodePointCount(const int wordId,
+        const int maxCodePointCount, int *const outCodePoints) const {
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    readingHelper.initWithPtNodePos(ptNodePos);
+    const int codePointCount =  readingHelper.getCodePointsAndReturnCodePointCount(
+            maxCodePointCount, outCodePoints);
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in getCodePointsAndProbabilityAndReturnCodePointCount().");
+    }
+    return codePointCount;
+}
+
+int Ver4PatriciaTriePolicy::getWordId(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(getRootPosition());
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in getWordId().");
+    }
+    return getWordIdFromTerminalPtNodePos(ptNodePos);
+}
+
+const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext(
+        const WordIdArrayView prevWordIds, const int wordId,
+        MultiBigramMap *const multiBigramMap) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return WordAttributes();
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
+    if (multiBigramMap) {
+        const int probability = multiBigramMap->getBigramProbability(this /* structurePolicy */,
+                prevWordIds, wordId, ptNodeParams.getProbability());
+        return getWordAttributes(probability, ptNodeParams);
+    }
+    if (!prevWordIds.empty()) {
+        const int probability = getProbabilityOfWord(prevWordIds, wordId);
+        if (probability != NOT_A_PROBABILITY) {
+            return getWordAttributes(probability, ptNodeParams);
+        }
+    }
+    return getWordAttributes(getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY),
+            ptNodeParams);
+}
+
+const WordAttributes Ver4PatriciaTriePolicy::getWordAttributes(const int probability,
+        const PtNodeParams &ptNodeParams) const {
+    return WordAttributes(probability, false /* isBlacklisted */, ptNodeParams.isNotAWord(),
+            ptNodeParams.getProbability() == 0);
+}
+
+int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
+        const int bigramProbability) const {
+    // In the v4 format, bigramProbability is a conditional probability.
+    const int bigramConditionalProbability = bigramProbability;
+    if (unigramProbability == NOT_A_PROBABILITY) {
+        return NOT_A_PROBABILITY;
+    }
+    if (bigramConditionalProbability == NOT_A_PROBABILITY) {
+        return ProbabilityUtils::backoff(unigramProbability);
+    }
+    return bigramConditionalProbability;
+}
+
+int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
+        const int wordId) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return NOT_A_PROBABILITY;
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
+    if (ptNodeParams.isDeleted() || ptNodeParams.isNotAWord()) {
+        return NOT_A_PROBABILITY;
+    }
+    if (prevWordIds.empty()) {
+        return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
+    }
+    if (prevWordIds[0] == NOT_A_WORD_ID) {
+        return NOT_A_PROBABILITY;
+    }
+    const PtNodeParams prevWordPtNodeParams =
+            mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(prevWordIds[0]);
+    if (prevWordPtNodeParams.isDeleted()) {
+        return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
+    }
+    const int bigramsPosition = mBuffers->getBigramDictContent()->getBigramListHeadPos(
+            prevWordPtNodeParams.getTerminalId());
+    BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
+    while (bigramsIt.hasNext()) {
+        bigramsIt.next();
+        if (bigramsIt.getBigramPos() == ptNodePos
+                && bigramsIt.getProbability() != NOT_A_PROBABILITY) {
+            const int bigramConditionalProbability = getBigramConditionalProbability(
+                    prevWordPtNodeParams.getProbability(),
+                    prevWordPtNodeParams.representsBeginningOfSentence(),
+                    bigramsIt.getProbability());
+            return getProbability(ptNodeParams.getProbability(), bigramConditionalProbability);
+        }
+    }
+    return NOT_A_PROBABILITY;
+}
+
+void Ver4PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
+        NgramListener *const listener) const {
+    if (prevWordIds.firstOrDefault(NOT_A_DICT_POS) == NOT_A_DICT_POS) {
+        return;
+    }
+    const PtNodeParams prevWordPtNodeParams =
+            mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(prevWordIds[0]);
+    if (prevWordPtNodeParams.isDeleted()) {
+        return;
+    }
+    const int bigramsPosition = mBuffers->getBigramDictContent()->getBigramListHeadPos(
+            prevWordPtNodeParams.getTerminalId());
+    BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
+    while (bigramsIt.hasNext()) {
+        bigramsIt.next();
+        const int bigramConditionalProbability = getBigramConditionalProbability(
+                prevWordPtNodeParams.getProbability(),
+                prevWordPtNodeParams.representsBeginningOfSentence(), bigramsIt.getProbability());
+        listener->onVisitEntry(bigramConditionalProbability,
+                getWordIdFromTerminalPtNodePos(bigramsIt.getBigramPos()));
+    }
+}
+
+int Ver4PatriciaTriePolicy::getBigramConditionalProbability(const int prevWordUnigramProbability,
+        const bool isInBeginningOfSentenceContext, const int bigramProbability) const {
+    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
+        if (isInBeginningOfSentenceContext) {
+            return bigramProbability;
+        }
+        // Calculate conditional probability.
+        return std::min(MAX_PROBABILITY - prevWordUnigramProbability + bigramProbability,
+                MAX_PROBABILITY);
+    } else {
+        // bigramProbability is a conditional probability.
+        return bigramProbability;
+    }
+}
+
+BinaryDictionaryShortcutIterator Ver4PatriciaTriePolicy::getShortcutIterator(
+        const int wordId) const {
+    const int shortcutPos = getShortcutPositionOfPtNode(getTerminalPtNodePosFromWordId(wordId));
+    return BinaryDictionaryShortcutIterator(&mShortcutPolicy, shortcutPos);
+}
+
+int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return NOT_A_DICT_POS;
+    }
+    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
+    if (ptNodeParams.isDeleted()) {
+        return NOT_A_DICT_POS;
+    }
+    return mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
+            ptNodeParams.getTerminalId());
+}
+
+int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return NOT_A_DICT_POS;
+    }
+    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
+    if (ptNodeParams.isDeleted()) {
+        return NOT_A_DICT_POS;
+    }
+    return mBuffers->getBigramDictContent()->getBigramListHeadPos(
+            ptNodeParams.getTerminalId());
+}
+
+bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePoints,
+        const UnigramProperty *const unigramProperty) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert to the dictionary, length: %zd",
+                wordCodePoints.size());
+        return false;
+    }
+    for (const auto &shortcut : unigramProperty->getShortcuts()) {
+        if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
+                    shortcut.getTargetCodePoints()->size());
+            return false;
+        }
+    }
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(getRootPosition());
+    bool addedNewUnigram = false;
+    int codePointsToAdd[MAX_WORD_LENGTH];
+    int codePointCountToAdd = wordCodePoints.size();
+    memmove(codePointsToAdd, wordCodePoints.data(), sizeof(int) * codePointCountToAdd);
+    if (unigramProperty->representsBeginningOfSentence()) {
+        codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
+                codePointCountToAdd, MAX_WORD_LENGTH);
+    }
+    if (codePointCountToAdd <= 0) {
+        return false;
+    }
+    const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView, unigramProperty,
+            &addedNewUnigram)) {
+        if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
+            mEntryCounters.incrementNgramCount(NgramType::Unigram);
+        }
+        if (unigramProperty->getShortcuts().size() > 0) {
+            // Add shortcut target.
+            const int wordPos = getTerminalPtNodePosFromWordId(
+                    getWordId(codePointArrayView, false /* forceLowerCaseSearch */));
+            if (wordPos == NOT_A_DICT_POS) {
+                AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
+                return false;
+            }
+            for (const auto &shortcut : unigramProperty->getShortcuts()) {
+                if (!mUpdatingHelper.addShortcutTarget(wordPos,
+                        CodePointArrayView(*shortcut.getTargetCodePoints()),
+                        shortcut.getProbability())) {
+                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
+                            "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
+                            shortcut.getProbability());
+                    return false;
+                }
+            }
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const CodePointArrayView wordCodePoints) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(
+            getWordId(wordCodePoints, false /* forceLowerCaseSearch */));
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return false;
+    }
+    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    return mNodeWriter.suppressUnigramEntry(&ptNodeParams);
+}
+
+bool Ver4PatriciaTriePolicy::addNgramEntry(const NgramProperty *const ngramProperty) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    const NgramContext *const ngramContext = ngramProperty->getNgramContext();
+    if (!ngramContext->isValid()) {
+        AKLOGE("Ngram context is not valid for adding n-gram entry to the dictionary.");
+        return false;
+    }
+    if (ngramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert the ngram to the dictionary. "
+                "length: %zd", ngramProperty->getTargetCodePoints()->size());
+        return false;
+    }
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSearch */);
+    if (prevWordIds.empty()) {
+        return false;
+    }
+    if (prevWordIds[0] == NOT_A_WORD_ID) {
+        if (ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */)) {
+            const UnigramProperty beginningOfSentenceUnigramProperty(
+                    true /* representsBeginningOfSentence */, true /* isNotAWord */,
+                    false /* isBlacklisted */, MAX_PROBABILITY /* probability */, HistoricalInfo());
+            if (!addUnigramEntry(ngramContext->getNthPrevWordCodePoints(1 /* n */),
+                    &beginningOfSentenceUnigramProperty)) {
+                AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
+                return false;
+            }
+            // Refresh word ids.
+            ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */);
+        } else {
+            return false;
+        }
+    }
+    const int wordPos = getTerminalPtNodePosFromWordId(getWordId(
+            CodePointArrayView(*ngramProperty->getTargetCodePoints()),
+                    false /* forceLowerCaseSearch */));
+    if (wordPos == NOT_A_DICT_POS) {
+        return false;
+    }
+    bool addedNewBigram = false;
+    const int prevWordPtNodePos = getTerminalPtNodePosFromWordId(prevWordIds[0]);
+    if (mUpdatingHelper.addNgramEntry(PtNodePosArrayView::singleElementView(&prevWordPtNodePos),
+            wordPos, ngramProperty, &addedNewBigram)) {
+        if (addedNewBigram) {
+            mEntryCounters.incrementNgramCount(NgramType::Bigram);
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool Ver4PatriciaTriePolicy::removeNgramEntry(const NgramContext *const ngramContext,
+        const CodePointArrayView wordCodePoints) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    if (!ngramContext->isValid()) {
+        AKLOGE("Ngram context is not valid for removing n-gram entry form the dictionary.");
+        return false;
+    }
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
+                wordCodePoints.size());
+    }
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSerch */);
+    if (prevWordIds.firstOrDefault(NOT_A_WORD_ID) == NOT_A_WORD_ID) {
+        return false;
+    }
+    const int wordPos = getTerminalPtNodePosFromWordId(getWordId(wordCodePoints,
+            false /* forceLowerCaseSearch */));
+    if (wordPos == NOT_A_DICT_POS) {
+        return false;
+    }
+    const int prevWordPtNodePos = getTerminalPtNodePosFromWordId(prevWordIds[0]);
+    if (mUpdatingHelper.removeNgramEntry(
+            PtNodePosArrayView::singleElementView(&prevWordPtNodePos), wordPos)) {
+        mEntryCounters.decrementNgramCount(NgramType::Bigram);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+bool Ver4PatriciaTriePolicy::updateEntriesForWordWithNgramContext(
+        const NgramContext *const ngramContext, const CodePointArrayView wordCodePoints,
+        const bool isValidWord, const HistoricalInfo historicalInfo) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: updateEntriesForWordWithNgramContext() is called for non-updatable "
+                "dictionary.");
+        return false;
+    }
+    const int probability = isValidWord ? DUMMY_PROBABILITY_FOR_VALID_WORDS : NOT_A_PROBABILITY;
+    const UnigramProperty unigramProperty(false /* representsBeginningOfSentence */,
+            false /* isNotAWord */, false /*isBlacklisted*/, probability, historicalInfo);
+    if (!addUnigramEntry(wordCodePoints, &unigramProperty)) {
+        AKLOGE("Cannot update unigarm entry in updateEntriesForWordWithNgramContext().");
+        return false;
+    }
+    const int probabilityForNgram = ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */)
+            ? NOT_A_PROBABILITY : probability;
+    const NgramProperty ngramProperty(*ngramContext, wordCodePoints.toVector(), probabilityForNgram,
+            historicalInfo);
+    if (!addNgramEntry(&ngramProperty)) {
+        AKLOGE("Cannot update unigarm entry in updateEntriesForWordWithNgramContext().");
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::flush(const char *const filePath) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath);
+        return false;
+    }
+    if (!mWritingHelper.writeToDictFile(filePath, mEntryCounters.getEntryCounts())) {
+        AKLOGE("Cannot flush the dictionary to file.");
+        mIsCorrupted = true;
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) {
+        AKLOGE("Cannot flush the dictionary to file with GC.");
+        mIsCorrupted = true;
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mBuffers->isNearSizeLimit()) {
+        // Additional buffer size is near the limit.
+        return true;
+    } else if (mHeaderPolicy->getExtendedRegionSize() + mDictBuffer->getUsedAdditionalBufferSize()
+            > Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE) {
+        // Total extended region size of the trie exceeds the limit.
+        return true;
+    } else if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS
+            && mDictBuffer->getUsedAdditionalBufferSize() > 0) {
+        // Needs to reduce dictionary size.
+        return true;
+    } else if (mHeaderPolicy->isDecayingDict()) {
+        return ForgettingCurveUtils::needsToDecay(mindsBlockByGC, mEntryCounters.getEntryCounts(),
+                mHeaderPolicy);
+    }
+    return false;
+}
+
+void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength,
+        char *const outResult, const int maxResultLength) {
+    const int compareLength = queryLength + 1 /* terminator */;
+    if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mEntryCounters.getNgramCount(NgramType::Unigram));
+    } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d", mEntryCounters.getNgramCount(NgramType::Bigram));
+    } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mHeaderPolicy->isDecayingDict() ?
+                        ForgettingCurveUtils::getEntryCountHardLimit(
+                                mHeaderPolicy->getMaxNgramCounts().getNgramCount(
+                                        NgramType::Unigram)) :
+                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mHeaderPolicy->isDecayingDict() ?
+                        ForgettingCurveUtils::getEntryCountHardLimit(
+                                mHeaderPolicy->getMaxNgramCounts().getNgramCount(
+                                        NgramType::Bigram)) :
+                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    }
+}
+
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int ptNodePos = getTerminalPtNodePosFromWordId(
+            getWordId(wordCodePoints, false /* forceLowerCaseSearch */));
+    if (ptNodePos == NOT_A_DICT_POS) {
+        AKLOGE("getWordProperty is called for invalid word.");
+        return WordProperty();
+    }
+    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    const ProbabilityEntry probabilityEntry =
+            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+                    ptNodeParams.getTerminalId());
+    const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+    // Fetch bigram information.
+    std::vector<NgramProperty> ngrams;
+    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
+    if (bigramListPos != NOT_A_DICT_POS) {
+        int bigramWord1CodePoints[MAX_WORD_LENGTH];
+        const BigramDictContent *const bigramDictContent = mBuffers->getBigramDictContent();
+        const TerminalPositionLookupTable *const terminalPositionLookupTable =
+                mBuffers->getTerminalPositionLookupTable();
+        bool hasNext = true;
+        int readingPos = bigramListPos;
+        while (hasNext) {
+            const BigramEntry bigramEntry =
+                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+            hasNext = bigramEntry.hasNext();
+            const int word1TerminalId = bigramEntry.getTargetTerminalId();
+            const int word1TerminalPtNodePos =
+                    terminalPositionLookupTable->getTerminalPtNodePosition(word1TerminalId);
+            if (word1TerminalPtNodePos == NOT_A_DICT_POS) {
+                continue;
+            }
+            const int codePointCount = getCodePointsAndReturnCodePointCount(
+                    getWordIdFromTerminalPtNodePos(word1TerminalPtNodePos), MAX_WORD_LENGTH,
+                    bigramWord1CodePoints);
+            const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
+            const int rawBigramProbability = bigramEntry.hasHistoricalInfo()
+                    ? ForgettingCurveUtils::decodeProbability(
+                            bigramEntry.getHistoricalInfo(), mHeaderPolicy)
+                    : bigramEntry.getProbability();
+            const int probability = getBigramConditionalProbability(ptNodeParams.getProbability(),
+                    ptNodeParams.representsBeginningOfSentence(), rawBigramProbability);
+            ngrams.emplace_back(
+                    NgramContext(wordCodePoints.data(), wordCodePoints.size(),
+                            ptNodeParams.representsBeginningOfSentence()),
+                    CodePointArrayView(bigramWord1CodePoints, codePointCount).toVector(),
+                    probability, *historicalInfo);
+        }
+    }
+    // Fetch shortcut information.
+    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
+    int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
+    if (shortcutPos != NOT_A_DICT_POS) {
+        int shortcutTarget[MAX_WORD_LENGTH];
+        const ShortcutDictContent *const shortcutDictContent =
+                mBuffers->getShortcutDictContent();
+        bool hasNext = true;
+        while (hasNext) {
+            int shortcutTargetLength = 0;
+            int shortcutProbability = NOT_A_PROBABILITY;
+            shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
+                    &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTarget, shortcutTargetLength).toVector(),
+                    shortcutProbability);
+        }
+    }
+    const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
+            ptNodeParams.isNotAWord(), ptNodeParams.isPossiblyOffensive(),
+            ptNodeParams.getProbability(), *historicalInfo, std::move(shortcuts));
+    return WordProperty(wordCodePoints.toVector(), unigramProperty, ngrams);
+}
+
+int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+        int *const outCodePointCount) {
+    *outCodePointCount = 0;
+    if (token == 0) {
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
+                &mTerminalPtNodePositionsForIteratingWords);
+        DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+        readingHelper.initWithPtNodeArrayPos(getRootPosition());
+        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
+    }
+    const int terminalPtNodePositionsVectorSize =
+            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
+    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
+        AKLOGE("Given token %d is invalid.", token);
+        return 0;
+    }
+    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
+    *outCodePointCount = getCodePointsAndReturnCodePointCount(
+            getWordIdFromTerminalPtNodePos(terminalPtNodePos), MAX_WORD_LENGTH, outCodePoints);
+    const int nextToken = token + 1;
+    if (nextToken >= terminalPtNodePositionsVectorSize) {
+        // All words have been iterated.
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        return 0;
+    }
+    return nextToken;
+}
+
+int Ver4PatriciaTriePolicy::getWordIdFromTerminalPtNodePos(const int ptNodePos) const {
+    return ptNodePos == NOT_A_DICT_POS ? NOT_A_WORD_ID : ptNodePos;
+}
+
+int Ver4PatriciaTriePolicy::getTerminalPtNodePosFromWordId(const int wordId) const {
+    return wordId == NOT_A_WORD_ID ? NOT_A_DICT_POS : wordId;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
new file mode 100644
index 0000000..bce5f6b
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
+ * Do not edit this file other than updating policy's interface.
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_policy.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
+#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/header/header_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
+#include "dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
+#include "dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h"
+#include "dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
+#include "dictionary/utils/binary_dictionary_bigrams_iterator.h"
+#include "dictionary/utils/binary_dictionary_shortcut_iterator.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/entry_counters.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class DicNode;
+namespace backward {
+namespace v402 {
+} // namespace v402
+} // namespace backward
+class DicNodeVector;
+namespace backward {
+namespace v402 {
+
+// Word id = Position of a PtNode that represents the word.
+// Max supported n-gram is bigram.
+class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
+ public:
+    Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
+            : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
+              mDictBuffer(mBuffers->getWritableTrieBuffer()),
+              mBigramPolicy(mBuffers->getMutableBigramDictContent(),
+                      mBuffers->getTerminalPositionLookupTable(), mHeaderPolicy),
+              mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+                      mBuffers->getTerminalPositionLookupTable()),
+              mNodeReader(mDictBuffer, mBuffers->getProbabilityDictContent(), mHeaderPolicy),
+              mPtNodeArrayReader(mDictBuffer),
+              mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
+                      &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy),
+              mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
+              mWritingHelper(mBuffers.get()),
+              mEntryCounters(mHeaderPolicy->getNgramCounts().getCountArray()),
+              mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
+
+    virtual int getRootPosition() const {
+        return 0;
+    }
+
+    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+            DicNodeVector *const childDicNodes) const;
+
+    int getCodePointsAndReturnCodePointCount(const int wordId, const int maxCodePointCount,
+            int *const outCodePoints) const;
+
+    int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
+
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
+
+    int getProbability(const int unigramProbability, const int bigramProbability) const;
+
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
+
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
+
+    BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
+
+    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+        return mHeaderPolicy;
+    }
+
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
+            const UnigramProperty *const unigramProperty);
+
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints);
+
+    bool addNgramEntry(const NgramProperty *const ngramProperty);
+
+    bool removeNgramEntry(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints);
+
+    bool updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints, const bool isValidWord,
+            const HistoricalInfo historicalInfo);
+
+    bool flush(const char *const filePath);
+
+    bool flushWithGC(const char *const filePath);
+
+    bool needsToRunGC(const bool mindsBlockByGC) const;
+
+    void getProperty(const char *const query, const int queryLength, char *const outResult,
+            const int maxResultLength);
+
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
+
+    int getNextWordAndNextToken(const int token, int *const outCodePoints,
+            int *const outCodePointCount);
+
+    bool isCorrupted() const {
+        return mIsCorrupted;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
+
+    static const char *const UNIGRAM_COUNT_QUERY;
+    static const char *const BIGRAM_COUNT_QUERY;
+    static const char *const MAX_UNIGRAM_COUNT_QUERY;
+    static const char *const MAX_BIGRAM_COUNT_QUERY;
+    // When the dictionary size is near the maximum size, we have to refuse dynamic operations to
+    // prevent the dictionary from overflowing.
+    static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+    static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
+    static const int DUMMY_PROBABILITY_FOR_VALID_WORDS;
+
+    const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
+    const HeaderPolicy *const mHeaderPolicy;
+    BufferWithExtendableBuffer *const mDictBuffer;
+    Ver4BigramListPolicy mBigramPolicy;
+    Ver4ShortcutListPolicy mShortcutPolicy;
+    Ver4PatriciaTrieNodeReader mNodeReader;
+    Ver4PtNodeArrayReader mPtNodeArrayReader;
+    Ver4PatriciaTrieNodeWriter mNodeWriter;
+    DynamicPtUpdatingHelper mUpdatingHelper;
+    Ver4PatriciaTrieWritingHelper mWritingHelper;
+    MutableEntryCounters mEntryCounters;
+    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
+    mutable bool mIsCorrupted;
+
+    int getBigramsPositionOfPtNode(const int ptNodePos) const;
+    int getShortcutPositionOfPtNode(const int ptNodePos) const;
+    int getWordIdFromTerminalPtNodePos(const int ptNodePos) const;
+    int getTerminalPtNodePosFromWordId(const int wordId) const;
+    const WordAttributes getWordAttributes(const int probability,
+            const PtNodeParams &ptNodeParams) const;
+    int getBigramConditionalProbability(const int prevWordUnigramProbability,
+            const bool isInBeginningOfSentenceContext, const int bigramProbability) const;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif // LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp
new file mode 100644
index 0000000..b8a4cf8
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
+
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(
+        const uint8_t *const buffer, int *pos) {
+    return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos);
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h
new file mode 100644
index 0000000..c3e736b
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H
+#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v402 {
+
+class Ver4PatriciaTrieReadingUtils {
+ public:
+    static int getTerminalIdAndAdvancePosition(const uint8_t *const buffer,
+            int *const pos);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieReadingUtils);
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
new file mode 100644
index 0000000..c0af9ea
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
@@ -0,0 +1,307 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h"
+
+#include <cstring>
+#include <queue>
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
+#include "dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
+#include "dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/file_utils.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFile(const char *const dictDirPath,
+        const EntryCounts &entryCounts) const {
+    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+    BufferWithExtendableBuffer headerBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
+            + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
+            entryCounts, extendedRegionSize, &headerBuffer)) {
+        AKLOGE("Cannot write header structure to buffer. "
+                "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, "
+                "extendedRegionSize: %d", false, entryCounts.getNgramCount(NgramType::Unigram),
+                entryCounts.getNgramCount(NgramType::Bigram), extendedRegionSize);
+        return false;
+    }
+    return mBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
+        const char *const dictDirPath) {
+    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+    Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
+            Ver4DictBuffers::createVer4DictBuffers(headerPolicy,
+                    Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    int unigramCount = 0;
+    int bigramCount = 0;
+    if (!runGC(rootPtNodeArrayPos, headerPolicy, dictBuffers.get(), &unigramCount, &bigramCount)) {
+        return false;
+    }
+    BufferWithExtendableBuffer headerBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    MutableEntryCounters entryCounters;
+    entryCounters.setNgramCount(NgramType::Unigram, unigramCount);
+    entryCounters.setNgramCount(NgramType::Bigram, bigramCount);
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+            entryCounters.getEntryCounts(), 0 /* extendedRegionSize */, &headerBuffer)) {
+        return false;
+    }
+    return dictBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
+        const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
+        int *const outUnigramCount, int *const outBigramCount) {
+    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
+            mBuffers->getProbabilityDictContent(), headerPolicy);
+    Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
+    Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(),
+            mBuffers->getTerminalPositionLookupTable(), headerPolicy);
+    Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+            mBuffers->getTerminalPositionLookupTable());
+    Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
+            mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
+            &shortcutPolicy);
+
+    DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    DynamicPtGcEventListeners
+            ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+                    traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
+                            &ptNodeWriter);
+    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+            &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
+        return false;
+    }
+    const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+            .getValidUnigramCount();
+    const int maxUnigramCount = headerPolicy->getMaxNgramCounts().getNgramCount(NgramType::Unigram);
+    if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) {
+        if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) {
+            AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount,
+                    maxUnigramCount);
+            return false;
+        }
+    }
+
+    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
+            traversePolicyToUpdateBigramProbability(&ptNodeWriter);
+    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+            &traversePolicyToUpdateBigramProbability)) {
+        return false;
+    }
+    const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount();
+    const int maxBigramCount = headerPolicy->getMaxNgramCounts().getNgramCount(NgramType::Bigram);
+    if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) {
+        if (!truncateBigrams(maxBigramCount)) {
+            AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount);
+            return false;
+        }
+    }
+
+    // Mapping from positions in mBuffer to positions in bufferToWrite.
+    PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
+    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
+            buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
+            &shortcutPolicy);
+    DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+            traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
+                    buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
+    if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+            &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
+        return false;
+    }
+
+    // Create policy instances for the GCed dictionary.
+    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
+            buffersToWrite->getProbabilityDictContent(), headerPolicy);
+    Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
+    Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(),
+            buffersToWrite->getTerminalPositionLookupTable(), headerPolicy);
+    Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
+            buffersToWrite->getTerminalPositionLookupTable());
+    Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
+            buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy,
+            &newShortcutPolicy);
+    // Re-assign terminal IDs for valid terminal PtNodes.
+    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
+    if(!buffersToWrite->getMutableTerminalPositionLookupTable()->runGCTerminalIds(
+            &terminalIdMap)) {
+        return false;
+    }
+    // Run GC for probability dict content.
+    if (!buffersToWrite->getMutableProbabilityDictContent()->runGC(&terminalIdMap,
+            mBuffers->getProbabilityDictContent())) {
+        return false;
+    }
+    // Run GC for bigram dict content.
+    if(!buffersToWrite->getMutableBigramDictContent()->runGC(&terminalIdMap,
+            mBuffers->getBigramDictContent(), outBigramCount)) {
+        return false;
+    }
+    // Run GC for shortcut dict content.
+    if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
+            mBuffers->getShortcutDictContent())) {
+        return false;
+    }
+    DynamicPtReadingHelper newDictReadingHelper(&newPtNodeReader, &newPtNodeArrayreader);
+    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
+            traversePolicyToUpdateAllPositionFields(&newPtNodeWriter, &dictPositionRelocationMap);
+    if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+            &traversePolicyToUpdateAllPositionFields)) {
+        return false;
+    }
+    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+            traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(&newPtNodeWriter, &terminalIdMap);
+    if (!newDictReadingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+            &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
+        return false;
+    }
+    *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount();
+    return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
+        const Ver4PatriciaTrieNodeReader *const ptNodeReader,
+        Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount) {
+    const TerminalPositionLookupTable *const terminalPosLookupTable =
+            mBuffers->getTerminalPositionLookupTable();
+    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
+    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
+            priorityQueue;
+    for (int i = 0; i < nextTerminalId; ++i) {
+        const int terminalPos = terminalPosLookupTable->getTerminalPtNodePosition(i);
+        if (terminalPos == NOT_A_DICT_POS) {
+            continue;
+        }
+        const ProbabilityEntry probabilityEntry =
+                mBuffers->getProbabilityDictContent()->getProbabilityEntry(i);
+        const int probability = probabilityEntry.hasHistoricalInfo() ?
+                ForgettingCurveUtils::decodeProbability(
+                        probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
+                probabilityEntry.getProbability();
+        priorityQueue.push(DictProbability(terminalPos, probability,
+                probabilityEntry.getHistoricalInfo()->getTimestamp()));
+    }
+
+    // Delete unigrams.
+    while (static_cast<int>(priorityQueue.size()) > maxUnigramCount) {
+        const int ptNodePos = priorityQueue.top().getDictPos();
+        priorityQueue.pop();
+        const PtNodeParams ptNodeParams =
+                ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+        if (ptNodeParams.representsNonWordInfo()) {
+            continue;
+        }
+        if (!ptNodeWriter->markPtNodeAsWillBecomeNonTerminal(&ptNodeParams)) {
+            AKLOGE("Cannot mark PtNode as willBecomeNonterminal. PtNode pos: %d", ptNodePos);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) {
+    const TerminalPositionLookupTable *const terminalPosLookupTable =
+            mBuffers->getTerminalPositionLookupTable();
+    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
+    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
+            priorityQueue;
+    BigramDictContent *const bigramDictContent = mBuffers->getMutableBigramDictContent();
+    for (int i = 0; i < nextTerminalId; ++i) {
+        const int bigramListPos = bigramDictContent->getBigramListHeadPos(i);
+        if (bigramListPos == NOT_A_DICT_POS) {
+            continue;
+        }
+        bool hasNext = true;
+        int readingPos = bigramListPos;
+        while (hasNext) {
+            const int entryPos = readingPos;
+            const BigramEntry bigramEntry =
+                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
+            hasNext = bigramEntry.hasNext();
+            if (!bigramEntry.isValid()) {
+                continue;
+            }
+            const int probability = bigramEntry.hasHistoricalInfo() ?
+                    ForgettingCurveUtils::decodeProbability(
+                            bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
+                    bigramEntry.getProbability();
+            priorityQueue.push(DictProbability(entryPos, probability,
+                    bigramEntry.getHistoricalInfo()->getTimestamp()));
+        }
+    }
+
+    // Delete bigrams.
+    while (static_cast<int>(priorityQueue.size()) > maxBigramCount) {
+        const int entryPos = priorityQueue.top().getDictPos();
+        const BigramEntry bigramEntry = bigramDictContent->getBigramEntry(entryPos);
+        const BigramEntry invalidatedBigramEntry = bigramEntry.getInvalidatedEntry();
+        if (!bigramDictContent->writeBigramEntry(&invalidatedBigramEntry, entryPos)) {
+            AKLOGE("Cannot write bigram entry to remove. pos: %d", entryPos);
+            return false;
+        }
+        priorityQueue.pop();
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    if (!ptNodeParams->isTerminal()) {
+        return true;
+    }
+    TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
+            mTerminalIdMap->find(ptNodeParams->getTerminalId());
+    if (it == mTerminalIdMap->end()) {
+        AKLOGE("terminal Id %d is not in the terminal position map. map size: %zd",
+                ptNodeParams->getTerminalId(), mTerminalIdMap->size());
+        return false;
+    }
+    if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
+        AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
+    }
+    return mPtNodeWriter->updatePtNodeHasBigramsAndShortcutTargetsFlags(ptNodeParams);
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h
new file mode 100644
index 0000000..f2b8738
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
+#include "dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
+#include "dictionary/utils/entry_counters.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class HeaderPolicy;
+namespace backward {
+namespace v402 {
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PatriciaTrieNodeWriter;
+
+class Ver4PatriciaTrieWritingHelper {
+ public:
+    Ver4PatriciaTrieWritingHelper(Ver4DictBuffers *const buffers)
+            : mBuffers(buffers) {}
+
+    bool writeToDictFile(const char *const dictDirPath, const EntryCounts &entryCounts) const;
+
+    // This method cannot be const because the original dictionary buffer will be updated to detect
+    // useless PtNodes during GC.
+    bool writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const dictDirPath);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieWritingHelper);
+
+    class TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+            : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(
+                Ver4PatriciaTrieNodeWriter *const ptNodeWriter,
+                const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap)
+                : mPtNodeWriter(ptNodeWriter), mTerminalIdMap(terminalIdMap) {}
+
+        bool onAscend() { return true; }
+
+        bool onDescend(const int ptNodeArrayPos) { return true; }
+
+        bool onReadingPtNodeArrayTail() { return true; }
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds);
+
+        Ver4PatriciaTrieNodeWriter *const mPtNodeWriter;
+        const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
+    };
+
+    // For truncateUnigrams() and truncateBigrams().
+    class DictProbability {
+     public:
+        DictProbability(const int dictPos, const int probability, const int timestamp)
+                : mDictPos(dictPos), mProbability(probability), mTimestamp(timestamp) {}
+
+        int getDictPos() const {
+            return mDictPos;
+        }
+
+        int getProbability() const {
+            return mProbability;
+        }
+
+        int getTimestamp() const {
+            return mTimestamp;
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(DictProbability);
+
+        int mDictPos;
+        int mProbability;
+        int mTimestamp;
+    };
+
+    // For truncateUnigrams() and truncateBigrams().
+    class DictProbabilityComparator {
+     public:
+        bool operator()(const DictProbability &left, const DictProbability &right) {
+            if (left.getProbability() != right.getProbability()) {
+                return left.getProbability() > right.getProbability();
+            }
+            if (left.getTimestamp() != right.getTimestamp()) {
+                return left.getTimestamp() < right.getTimestamp();
+            }
+            return left.getDictPos() > right.getDictPos();
+        }
+
+     private:
+        DISALLOW_ASSIGNMENT_OPERATOR(DictProbabilityComparator);
+    };
+
+    bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
+            Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount,
+            int *const outBigramCount);
+
+    bool truncateUnigrams(const Ver4PatriciaTrieNodeReader *const ptNodeReader,
+            Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount);
+
+    bool truncateBigrams(const int maxBigramCount);
+
+    Ver4DictBuffers *const mBuffers;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+
+#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H */
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp b/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp
new file mode 100644
index 0000000..d27d708
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_pt_node_array_reader.cpp
+ */
+
+#include "dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
+
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
+    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of a bug or a broken dictionary.
+        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
+                ptNodeArrayPos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return false;
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int readingPos = ptNodeArrayPos;
+    if (usesAdditionalBuffer) {
+        readingPos -= mBuffer->getOriginalBufferSize();
+    }
+    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+            dictBuf, &readingPos);
+    if (usesAdditionalBuffer) {
+        readingPos += mBuffer->getOriginalBufferSize();
+    }
+    if (ptNodeCountInArray < 0) {
+        AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
+        return false;
+    }
+    *outPtNodeCount = ptNodeCountInArray;
+    *outFirstPtNodePos = readingPos;
+    return true;
+}
+
+bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+        int *const outNextPtNodeArrayPos) const {
+    if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
+                forwordLinkPos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return false;
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int readingPos = forwordLinkPos;
+    if (usesAdditionalBuffer) {
+        readingPos -= mBuffer->getOriginalBufferSize();
+    }
+    const int nextPtNodeArrayOffset =
+            DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
+    if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
+        *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
+    } else {
+        *outNextPtNodeArrayPos = NOT_A_DICT_POS;
+    }
+    return true;
+}
+
+} // namespace v402
+} // namespace backward
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h b/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h
new file mode 100644
index 0000000..0039bf8
--- /dev/null
+++ b/native/jni/src/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+/*
+ * !!!!! DO NOT EDIT THIS FILE !!!!!
+ *
+ * This file was generated from
+ *   dictionary/structure/v4/ver4_pt_node_array_reader.h
+ */
+
+#ifndef LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H
+#define LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_array_reader.h"
+
+namespace latinime {
+namespace backward {
+namespace v402 {
+
+} // namespace v402
+} // namespace backward
+class BufferWithExtendableBuffer;
+namespace backward {
+namespace v402 {
+
+class Ver4PtNodeArrayReader : public PtNodeArrayReader {
+ public:
+    Ver4PtNodeArrayReader(const BufferWithExtendableBuffer *const buffer) : mBuffer(buffer) {};
+
+    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
+    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+            int *const outNextPtNodeArrayPos) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PtNodeArrayReader);
+
+    const BufferWithExtendableBuffer *const mBuffer;
+};
+} // namespace v402
+} // namespace backward
+} // namespace latinime
+#endif /* LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp b/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
new file mode 100644
index 0000000..4470e85
--- /dev/null
+++ b/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
+
+#include <climits>
+
+#include "defines.h"
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+#include "dictionary/structure/backward/v402/ver4_dict_constants.h"
+#include "dictionary/structure/backward/v402/ver4_patricia_trie_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/v2/patricia_trie_policy.h"
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_policy.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "dictionary/utils/file_utils.h"
+#include "dictionary/utils/format_utils.h"
+#include "dictionary/utils/mmapped_buffer.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
+                const char *const path, const int bufOffset, const int size,
+                const bool isUpdatable) {
+    if (FileUtils::existsDir(path)) {
+        // Given path represents a directory.
+        return newPolicyForDirectoryDict(path, isUpdatable);
+    } else {
+        if (isUpdatable) {
+            AKLOGE("One file dictionaries don't support updating. path: %s", path);
+            ASSERT(false);
+            return nullptr;
+        }
+        return newPolicyForFileDict(path, bufOffset, size);
+    }
+}
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory:: newPolicyForOnMemoryDict(
+                const int formatVersion, const std::vector<int> &locale,
+                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
+    FormatUtils::FORMAT_VERSION dictFormatVersion = FormatUtils::getFormatVersion(formatVersion);
+    switch (dictFormatVersion) {
+        case FormatUtils::VERSION_402: {
+            return newPolicyForOnMemoryV4Dict<backward::v402::Ver4DictConstants,
+                    backward::v402::Ver4DictBuffers,
+                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
+                    backward::v402::Ver4PatriciaTriePolicy>(
+                            dictFormatVersion, locale, attributeMap);
+        }
+        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+        case FormatUtils::VERSION_403: {
+            return newPolicyForOnMemoryV4Dict<Ver4DictConstants, Ver4DictBuffers,
+                    Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
+                            dictFormatVersion, locale, attributeMap);
+        }
+        default:
+            AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
+                    formatVersion);
+            break;
+    }
+    return nullptr;
+}
+
+template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForOnMemoryV4Dict(
+                const FormatUtils::FORMAT_VERSION formatVersion,
+                const std::vector<int> &locale,
+                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
+    HeaderPolicy headerPolicy(formatVersion, locale, attributeMap);
+    DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
+            DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
+    if (!DynamicPtWritingUtils::writeEmptyDictionary(
+            dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
+        AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
+        return nullptr;
+    }
+    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+            new StructurePolicy(std::move(dictBuffers)));
+}
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForDirectoryDict(
+                const char *const path, const bool isUpdatable) {
+    const int headerFilePathBufSize = PATH_MAX + 1 /* terminator */;
+    char headerFilePath[headerFilePathBufSize];
+    getHeaderFilePathInDictDir(path, headerFilePathBufSize, headerFilePath);
+    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
+    // MmappedBufferPtr if the instance has the responsibility.
+    MmappedBuffer::MmappedBufferPtr mmappedBuffer =
+            MmappedBuffer::openBuffer(headerFilePath, isUpdatable);
+    if (!mmappedBuffer) {
+        return nullptr;
+    }
+    const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
+            mmappedBuffer->getReadOnlyByteArrayView());
+    switch (formatVersion) {
+        case FormatUtils::VERSION_2:
+        case FormatUtils::VERSION_201:
+        case FormatUtils::VERSION_202:
+            AKLOGE("Given path is a directory but the format is version 2xx. path: %s", path);
+            break;
+        case FormatUtils::VERSION_402: {
+            return newPolicyForV4Dict<backward::v402::Ver4DictConstants,
+                    backward::v402::Ver4DictBuffers,
+                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
+                    backward::v402::Ver4PatriciaTriePolicy>(
+                            headerFilePath, formatVersion, std::move(mmappedBuffer));
+        }
+        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+        case FormatUtils::VERSION_403: {
+            return newPolicyForV4Dict<Ver4DictConstants, Ver4DictBuffers,
+                    Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
+                            headerFilePath, formatVersion, std::move(mmappedBuffer));
+        }
+        default:
+            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
+            break;
+    }
+    ASSERT(false);
+    return nullptr;
+}
+
+template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForV4Dict(
+                const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
+                MmappedBuffer::MmappedBufferPtr &&mmappedBuffer) {
+    const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
+    char dictPath[dictDirPathBufSize];
+    if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
+            DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
+        AKLOGE("Dictionary file name is not valid as a ver4 dictionary. header path: %s",
+                headerFilePath);
+        ASSERT(false);
+        return nullptr;
+    }
+    DictBuffersPtr dictBuffers =
+            DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer), formatVersion);
+    if (!dictBuffers || !dictBuffers->isValid()) {
+        AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
+                dictPath);
+        ASSERT(false);
+        return nullptr;
+    }
+    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+            new StructurePolicy(std::move(dictBuffers)));
+}
+
+/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+        DictionaryStructureWithBufferPolicyFactory::newPolicyForFileDict(
+                const char *const path, const int bufOffset, const int size) {
+    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
+    // MmappedBufferPtr if the instance has the responsibility.
+    MmappedBuffer::MmappedBufferPtr mmappedBuffer(
+            MmappedBuffer::openBuffer(path, bufOffset, size, false /* isUpdatable */));
+    if (!mmappedBuffer) {
+        return nullptr;
+    }
+    switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView())) {
+        case FormatUtils::VERSION_2:
+        case FormatUtils::VERSION_201:
+            AKLOGE("Dictionary versions 2 and 201 are incompatible with this version");
+            break;
+        case FormatUtils::VERSION_202:
+            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
+                    new PatriciaTriePolicy(std::move(mmappedBuffer)));
+        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+        case FormatUtils::VERSION_402:
+        case FormatUtils::VERSION_403:
+            AKLOGE("Given path is a file but the format is version 4. path: %s", path);
+            break;
+        default:
+            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
+            break;
+    }
+    ASSERT(false);
+    return nullptr;
+}
+
+/* static */ void DictionaryStructureWithBufferPolicyFactory::getHeaderFilePathInDictDir(
+        const char *const dictDirPath, const int outHeaderFileBufSize,
+        char *const outHeaderFilePath) {
+    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
+    char dictName[dictNameBufSize];
+    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
+    snprintf(outHeaderFilePath, outHeaderFileBufSize, "%s/%s%s", dictDirPath,
+            dictName, Ver4DictConstants::HEADER_FILE_EXTENSION);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h b/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
new file mode 100644
index 0000000..b0c04c0
--- /dev/null
+++ b/native/jni/src/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
+#define LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/utils/format_utils.h"
+#include "dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+class DictionaryStructureWithBufferPolicyFactory {
+ public:
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForExistingDictFile(const char *const path, const int bufOffset,
+                    const int size, const bool isUpdatable);
+
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForOnMemoryDict(const int formatVersion, const std::vector<int> &locale,
+                    const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
+
+    template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForOnMemoryV4Dict(const FormatUtils::FORMAT_VERSION formatVersion,
+                    const std::vector<int> &locale,
+                    const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForDirectoryDict(const char *const path, const bool isUpdatable);
+
+    template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr newPolicyForV4Dict(
+            const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
+                    MmappedBuffer::MmappedBufferPtr &&mmappedBuffer);
+
+    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
+            newPolicyForFileDict(const char *const path, const int bufOffset, const int size);
+
+    static void getHeaderFilePathInDictDir(const char *const dirPath,
+            const int outHeaderFileBufSize, char *const outHeaderFilePath);
+};
+} // namespace latinime
+#endif // LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
diff --git a/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp b/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
new file mode 100644
index 0000000..64f9b66
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
+
+#include "dictionary/utils/byte_array_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+const BigramListReadWriteUtils::BigramFlags BigramListReadWriteUtils::MASK_ATTRIBUTE_ADDRESS_TYPE =
+        0x30;
+const BigramListReadWriteUtils::BigramFlags
+        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
+const BigramListReadWriteUtils::BigramFlags
+        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
+const BigramListReadWriteUtils::BigramFlags
+        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
+const BigramListReadWriteUtils::BigramFlags
+        BigramListReadWriteUtils::FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40;
+// Flag for presence of more attributes
+const BigramListReadWriteUtils::BigramFlags BigramListReadWriteUtils::FLAG_ATTRIBUTE_HAS_NEXT =
+        0x80;
+// Mask for attribute probability, stored on 4 bits inside the flags byte.
+const BigramListReadWriteUtils::BigramFlags
+        BigramListReadWriteUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
+
+/* static */ bool BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(
+        const ReadOnlyByteArrayView buffer, BigramFlags *const outBigramFlags,
+        int *const outTargetPtNodePos, int *const bigramEntryPos) {
+    if (static_cast<int>(buffer.size()) <= *bigramEntryPos) {
+        AKLOGE("Read invalid pos in getBigramEntryPropertiesAndAdvancePosition(). bufSize: %zd, "
+                "bigramEntryPos: %d.", buffer.size(), *bigramEntryPos);
+        return false;
+    }
+    const BigramFlags bigramFlags = ByteArrayUtils::readUint8AndAdvancePosition(buffer.data(),
+            bigramEntryPos);
+    if (outBigramFlags) {
+        *outBigramFlags = bigramFlags;
+    }
+    const int targetPos = getBigramAddressAndAdvancePosition(buffer, bigramFlags, bigramEntryPos);
+    if (outTargetPtNodePos) {
+        *outTargetPtNodePos = targetPos;
+    }
+    return true;
+}
+
+/* static */ bool BigramListReadWriteUtils::skipExistingBigrams(const ReadOnlyByteArrayView buffer,
+        int *const bigramListPos) {
+    BigramFlags flags;
+    do {
+        if (!getBigramEntryPropertiesAndAdvancePosition(buffer, &flags, 0 /* outTargetPtNodePos */,
+                bigramListPos)) {
+            return false;
+        }
+    } while(hasNext(flags));
+    return true;
+}
+
+/* static */ int BigramListReadWriteUtils::getBigramAddressAndAdvancePosition(
+        const ReadOnlyByteArrayView buffer, const BigramFlags flags, int *const pos) {
+    int offset = 0;
+    const int origin = *pos;
+    switch (MASK_ATTRIBUTE_ADDRESS_TYPE & flags) {
+        case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE:
+            offset = ByteArrayUtils::readUint8AndAdvancePosition(buffer.data(), pos);
+            break;
+        case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES:
+            offset = ByteArrayUtils::readUint16AndAdvancePosition(buffer.data(), pos);
+            break;
+        case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES:
+            offset = ByteArrayUtils::readUint24AndAdvancePosition(buffer.data(), pos);
+            break;
+    }
+    if (isOffsetNegative(flags)) {
+        return origin - offset;
+    } else {
+        return origin + offset;
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h b/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
new file mode 100644
index 0000000..a0f7d5e
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
+#define LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
+
+#include <cstdint>
+#include <cstdlib>
+
+#include "defines.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+
+class BigramListReadWriteUtils {
+public:
+   typedef uint8_t BigramFlags;
+
+   static bool getBigramEntryPropertiesAndAdvancePosition(const ReadOnlyByteArrayView buffer,
+           BigramFlags *const outBigramFlags, int *const outTargetPtNodePos,
+           int *const bigramEntryPos);
+
+   static AK_FORCE_INLINE int getProbabilityFromFlags(const BigramFlags flags) {
+       return flags & MASK_ATTRIBUTE_PROBABILITY;
+   }
+
+   static AK_FORCE_INLINE bool hasNext(const BigramFlags flags) {
+       return (flags & FLAG_ATTRIBUTE_HAS_NEXT) != 0;
+   }
+
+   // Bigrams reading methods
+   static bool skipExistingBigrams(const ReadOnlyByteArrayView buffer, int *const bigramListPos);
+
+private:
+   DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListReadWriteUtils);
+
+   static const BigramFlags MASK_ATTRIBUTE_ADDRESS_TYPE;
+   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE;
+   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES;
+   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES;
+   static const BigramFlags FLAG_ATTRIBUTE_OFFSET_NEGATIVE;
+   static const BigramFlags FLAG_ATTRIBUTE_HAS_NEXT;
+   static const BigramFlags MASK_ATTRIBUTE_PROBABILITY;
+
+   static AK_FORCE_INLINE bool isOffsetNegative(const BigramFlags flags) {
+       return (flags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) != 0;
+   }
+
+   static int getBigramAddressAndAdvancePosition(const ReadOnlyByteArrayView buffer,
+           const BigramFlags flags, int *const pos);
+};
+} // namespace latinime
+#endif // LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
new file mode 100644
index 0000000..b5e2e9d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
+
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_writer.h"
+
+namespace latinime {
+
+bool DynamicPtGcEventListeners
+        ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+                ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    // PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
+    // children.
+    bool isUselessPtNode = !ptNodeParams->isTerminal();
+    if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
+        bool needsToKeepPtNode = true;
+        if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+                ptNodeParams, &needsToKeepPtNode)) {
+            AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC.");
+            return false;
+        }
+        if (!needsToKeepPtNode) {
+            isUselessPtNode = true;
+        }
+    }
+    if (mChildrenValue > 0) {
+        isUselessPtNode = false;
+    } else if (ptNodeParams->isTerminal()) {
+        // Remove children as all children are useless.
+        if (!mPtNodeWriter->updateChildrenPosition(ptNodeParams,
+                NOT_A_DICT_POS /* newChildrenPosition */)) {
+            return false;
+        }
+    }
+    if (isUselessPtNode) {
+        // Current PtNode is no longer needed. Mark it as deleted.
+        if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) {
+            return false;
+        }
+    } else {
+        mValueStack.back() += 1;
+        if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
+            mValidUnigramCount += 1;
+        }
+    }
+    return true;
+}
+
+bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
+        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    if (!ptNodeParams->isDeleted()) {
+        int bigramEntryCount = 0;
+        if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams,
+                &bigramEntryCount)) {
+            return false;
+        }
+        mValidBigramEntryCount += bigramEntryCount;
+    }
+    return true;
+}
+
+// Writes dummy PtNode array size when the head of PtNode array is read.
+bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+        ::onDescend(const int ptNodeArrayPos) {
+    mValidPtNodeCount = 0;
+    int writingPos = mBufferToWrite->getTailPosition();
+    mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert(
+            PtNodeWriter::PtNodeArrayPositionRelocationMap::value_type(ptNodeArrayPos, writingPos));
+    // Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes.
+    // This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count.
+    mPtNodeArraySizeFieldPos = writingPos;
+    return DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
+            mBufferToWrite, 0 /* arraySize */, &writingPos);
+}
+
+// Write PtNode array terminal and actual PtNode array size.
+bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+        ::onReadingPtNodeArrayTail() {
+    int writingPos = mBufferToWrite->getTailPosition();
+    // Write PtNode array terminal.
+    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
+            mBufferToWrite, NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
+        return false;
+    }
+    // Write actual PtNode array size.
+    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
+            mBufferToWrite, mValidPtNodeCount, &mPtNodeArraySizeFieldPos)) {
+        return false;
+    }
+    return true;
+}
+
+// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
+bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    if (ptNodeParams->isDeleted()) {
+        // Current PtNode is not written in new buffer because it has been deleted.
+        mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
+                PtNodeWriter::PtNodePositionRelocationMap::value_type(
+                        ptNodeParams->getHeadPos(), NOT_A_DICT_POS));
+        return true;
+    }
+    int writingPos = mBufferToWrite->getTailPosition();
+    mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
+            PtNodeWriter::PtNodePositionRelocationMap::value_type(
+                    ptNodeParams->getHeadPos(), writingPos));
+    mValidPtNodeCount++;
+    // Writes current PtNode.
+    return mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &writingPos);
+}
+
+bool DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
+        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    // Updates parent position.
+    int bigramCount = 0;
+    if (!mPtNodeWriter->updateAllPositionFields(ptNodeParams, mDictPositionRelocationMap,
+            &bigramCount)) {
+        return false;
+    }
+    mBigramCount += bigramCount;
+    if (ptNodeParams->isTerminal()) {
+        mUnigramCount++;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h
new file mode 100644
index 0000000..8c7ad96
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H
+#define LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/pt_common/pt_node_writer.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+class PtNodeParams;
+
+class DynamicPtGcEventListeners {
+ public:
+    // Updates all PtNodes that can be reached from the root. Checks if each PtNode is useless or
+    // not and marks useless PtNodes as deleted. Such deleted PtNodes will be discarded in the GC.
+    // TODO: Concatenate non-terminal PtNodes.
+    class TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+        : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
+                PtNodeWriter *const ptNodeWriter)
+                : mPtNodeWriter(ptNodeWriter), mValueStack(), mChildrenValue(0),
+                  mValidUnigramCount(0) {}
+
+        ~TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted() {};
+
+        bool onAscend() {
+            if (mValueStack.empty()) {
+                return false;
+            }
+            mChildrenValue = mValueStack.back();
+            mValueStack.pop_back();
+            return true;
+        }
+
+        bool onDescend(const int ptNodeArrayPos) {
+            mValueStack.push_back(0);
+            mChildrenValue = 0;
+            return true;
+        }
+
+        bool onReadingPtNodeArrayTail() { return true; }
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+        int getValidUnigramCount() const {
+            return mValidUnigramCount;
+        }
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(
+                TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted);
+
+        PtNodeWriter *const mPtNodeWriter;
+        std::vector<int> mValueStack;
+        int mChildrenValue;
+        int mValidUnigramCount;
+    };
+
+    // TODO: Remove when we stop supporting v402 format.
+    // Updates all bigram entries that are held by valid PtNodes. This removes useless bigram
+    // entries.
+    class TraversePolicyToUpdateBigramProbability
+            : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToUpdateBigramProbability(PtNodeWriter *const ptNodeWriter)
+                : mPtNodeWriter(ptNodeWriter), mValidBigramEntryCount(0) {}
+
+        bool onAscend() { return true; }
+
+        bool onDescend(const int ptNodeArrayPos) { return true; }
+
+        bool onReadingPtNodeArrayTail() { return true; }
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+        int getValidBigramEntryCount() const {
+            return mValidBigramEntryCount;
+        }
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateBigramProbability);
+
+        PtNodeWriter *const mPtNodeWriter;
+        int mValidBigramEntryCount;
+    };
+
+    class TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+            : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToPlaceAndWriteValidPtNodesToBuffer(
+                PtNodeWriter *const ptNodeWriter, BufferWithExtendableBuffer *const bufferToWrite,
+                PtNodeWriter::DictPositionRelocationMap *const dictPositionRelocationMap)
+                : mPtNodeWriter(ptNodeWriter), mBufferToWrite(bufferToWrite),
+                  mDictPositionRelocationMap(dictPositionRelocationMap), mValidPtNodeCount(0),
+                  mPtNodeArraySizeFieldPos(NOT_A_DICT_POS) {};
+
+        bool onAscend() { return true; }
+
+        bool onDescend(const int ptNodeArrayPos);
+
+        bool onReadingPtNodeArrayTail();
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToPlaceAndWriteValidPtNodesToBuffer);
+
+        PtNodeWriter *const mPtNodeWriter;
+        BufferWithExtendableBuffer *const mBufferToWrite;
+        PtNodeWriter::DictPositionRelocationMap *const mDictPositionRelocationMap;
+        int mValidPtNodeCount;
+        int mPtNodeArraySizeFieldPos;
+    };
+
+    class TraversePolicyToUpdateAllPositionFields
+            : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToUpdateAllPositionFields(PtNodeWriter *const ptNodeWriter,
+                const PtNodeWriter::DictPositionRelocationMap *const dictPositionRelocationMap)
+                : mPtNodeWriter(ptNodeWriter),
+                  mDictPositionRelocationMap(dictPositionRelocationMap), mUnigramCount(0),
+                  mBigramCount(0) {};
+
+        bool onAscend() { return true; }
+
+        bool onDescend(const int ptNodeArrayPos) { return true; }
+
+        bool onReadingPtNodeArrayTail() { return true; }
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+        int getUnigramCount() const {
+            return mUnigramCount;
+        }
+
+        int getBigramCount() const {
+            return mBigramCount;
+        }
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPositionFields);
+
+        PtNodeWriter *const mPtNodeWriter;
+        const PtNodeWriter::DictPositionRelocationMap *const mDictPositionRelocationMap;
+        int mUnigramCount;
+        int mBigramCount;
+    };
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtGcEventListeners);
+};
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
new file mode 100644
index 0000000..294bc6e
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+
+#include "dictionary/structure/pt_common/pt_node_array_reader.h"
+#include "utils/char_utils.h"
+
+namespace latinime {
+
+// To avoid infinite loop caused by invalid or malicious forward links.
+const int DynamicPtReadingHelper::MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
+const int DynamicPtReadingHelper::MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
+const size_t DynamicPtReadingHelper::MAX_READING_STATE_STACK_SIZE = MAX_WORD_LENGTH;
+
+bool DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions::onVisitingPtNode(
+        const PtNodeParams *const ptNodeParams) {
+    if (ptNodeParams->isTerminal() && !ptNodeParams->isDeleted()) {
+        mTerminalPositions->push_back(ptNodeParams->getHeadPos());
+    }
+    return true;
+}
+
+// Visits all PtNodes in post-order depth first manner.
+// For example, visits c -> b -> y -> x -> a for the following dictionary:
+// a _ b _ c
+//   \ x _ y
+bool DynamicPtReadingHelper::traverseAllPtNodesInPostorderDepthFirstManner(
+        TraversingEventListener *const listener) {
+    bool alreadyVisitedChildren = false;
+    // Descend from the root to the root PtNode array.
+    if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) {
+        return false;
+    }
+    while (!isEnd()) {
+        const PtNodeParams ptNodeParams(getPtNodeParams());
+        if (!ptNodeParams.isValid()) {
+            break;
+        }
+        if (!alreadyVisitedChildren) {
+            if (ptNodeParams.hasChildren()) {
+                // Move to the first child.
+                if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
+                    return false;
+                }
+                pushReadingStateToStack();
+                readChildNode(ptNodeParams);
+            } else {
+                alreadyVisitedChildren = true;
+            }
+        } else {
+            if (!listener->onVisitingPtNode(&ptNodeParams)) {
+                return false;
+            }
+            readNextSiblingNode(ptNodeParams);
+            if (isEnd()) {
+                // All PtNodes in current linked PtNode arrays have been visited.
+                // Return to the parent.
+                if (!listener->onReadingPtNodeArrayTail()) {
+                    return false;
+                }
+                if (mReadingStateStack.size() <= 0) {
+                    break;
+                }
+                if (!listener->onAscend()) {
+                    return false;
+                }
+                popReadingStateFromStack();
+                alreadyVisitedChildren = true;
+            } else {
+                // Process sibling PtNode.
+                alreadyVisitedChildren = false;
+            }
+        }
+    }
+    // Ascend from the root PtNode array to the root.
+    if (!listener->onAscend()) {
+        return false;
+    }
+    return !isError();
+}
+
+// Visits all PtNodes in PtNode array level pre-order depth first manner, which is the same order
+// that PtNodes are written in the dictionary buffer.
+// For example, visits a -> b -> x -> c -> y for the following dictionary:
+// a _ b _ c
+//   \ x _ y
+bool DynamicPtReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+        TraversingEventListener *const listener) {
+    bool alreadyVisitedAllPtNodesInArray = false;
+    bool alreadyVisitedChildren = false;
+    // Descend from the root to the root PtNode array.
+    if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) {
+        return false;
+    }
+    if (isEnd()) {
+        // Empty dictionary. Needs to notify the listener of the tail of empty PtNode array.
+        if (!listener->onReadingPtNodeArrayTail()) {
+            return false;
+        }
+    }
+    pushReadingStateToStack();
+    while (!isEnd()) {
+        const PtNodeParams ptNodeParams(getPtNodeParams());
+        if (!ptNodeParams.isValid()) {
+            break;
+        }
+        if (alreadyVisitedAllPtNodesInArray) {
+            if (alreadyVisitedChildren) {
+                // Move to next sibling PtNode's children.
+                readNextSiblingNode(ptNodeParams);
+                if (isEnd()) {
+                    // Return to the parent PTNode.
+                    if (!listener->onAscend()) {
+                        return false;
+                    }
+                    if (mReadingStateStack.size() <= 0) {
+                        break;
+                    }
+                    popReadingStateFromStack();
+                    alreadyVisitedChildren = true;
+                    alreadyVisitedAllPtNodesInArray = true;
+                } else {
+                    alreadyVisitedChildren = false;
+                }
+            } else {
+                if (ptNodeParams.hasChildren()) {
+                    // Move to the first child.
+                    if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
+                        return false;
+                    }
+                    pushReadingStateToStack();
+                    readChildNode(ptNodeParams);
+                    // Push state to return the head of PtNode array.
+                    pushReadingStateToStack();
+                    alreadyVisitedAllPtNodesInArray = false;
+                    alreadyVisitedChildren = false;
+                } else {
+                    alreadyVisitedChildren = true;
+                }
+            }
+        } else {
+            if (!listener->onVisitingPtNode(&ptNodeParams)) {
+                return false;
+            }
+            readNextSiblingNode(ptNodeParams);
+            if (isEnd()) {
+                if (!listener->onReadingPtNodeArrayTail()) {
+                    return false;
+                }
+                // Return to the head of current PtNode array.
+                popReadingStateFromStack();
+                alreadyVisitedAllPtNodesInArray = true;
+            }
+        }
+    }
+    popReadingStateFromStack();
+    // Ascend from the root PtNode array to the root.
+    if (!listener->onAscend()) {
+        return false;
+    }
+    return !isError();
+}
+
+int DynamicPtReadingHelper::getCodePointsAndReturnCodePointCount(const int maxCodePointCount,
+        int *const outCodePoints) {
+    // This method traverses parent nodes from the terminal by following parent pointers; thus,
+    // node code points are stored in the buffer in the reverse order.
+    int reverseCodePoints[maxCodePointCount];
+    const PtNodeParams terminalPtNodeParams(getPtNodeParams());
+    // First, read the terminal node and get its probability.
+    if (!isValidTerminalNode(terminalPtNodeParams)) {
+        // Node at the ptNodePos is not a valid terminal node.
+        return 0;
+    }
+    // Then, following parent node link to the dictionary root and fetch node code points.
+    int totalCodePointCount = 0;
+    while (!isEnd()) {
+        const PtNodeParams ptNodeParams(getPtNodeParams());
+        totalCodePointCount = getTotalCodePointCount(ptNodeParams);
+        if (!ptNodeParams.isValid() || totalCodePointCount > maxCodePointCount) {
+            // The ptNodePos is not a valid terminal node position in the dictionary.
+            return 0;
+        }
+        // Store node code points to buffer in the reverse order.
+        fetchMergedNodeCodePointsInReverseOrder(ptNodeParams, getPrevTotalCodePointCount(),
+                reverseCodePoints);
+        // Follow parent node toward the root node.
+        readParentNode(ptNodeParams);
+    }
+    if (isError()) {
+        // The node position or the dictionary is invalid.
+        return 0;
+    }
+    // Reverse the stored code points to output them.
+    for (int i = 0; i < totalCodePointCount; ++i) {
+        outCodePoints[i] = reverseCodePoints[totalCodePointCount - i - 1];
+    }
+    return totalCodePointCount;
+}
+
+int DynamicPtReadingHelper::getTerminalPtNodePositionOfWord(const int *const inWord,
+        const size_t length, const bool forceLowerCaseSearch) {
+    int searchCodePoints[length];
+    for (size_t i = 0; i < length; ++i) {
+        searchCodePoints[i] = forceLowerCaseSearch ? CharUtils::toLowerCase(inWord[i]) : inWord[i];
+    }
+    while (!isEnd()) {
+        const PtNodeParams ptNodeParams(getPtNodeParams());
+        const int matchedCodePointCount = getPrevTotalCodePointCount();
+        if (getTotalCodePointCount(ptNodeParams) > length
+                || !isMatchedCodePoint(ptNodeParams, 0 /* index */,
+                        searchCodePoints[matchedCodePointCount])) {
+            // Current node has too many code points or its first code point is different from
+            // target code point. Skip this node and read the next sibling node.
+            readNextSiblingNode(ptNodeParams);
+            continue;
+        }
+        // Check following merged node code points.
+        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
+        for (int j = 1; j < nodeCodePointCount; ++j) {
+            if (!isMatchedCodePoint(ptNodeParams, j, searchCodePoints[matchedCodePointCount + j])) {
+                // Different code point is found. The given word is not included in the dictionary.
+                return NOT_A_DICT_POS;
+            }
+        }
+        // All characters are matched.
+        if (length == getTotalCodePointCount(ptNodeParams)) {
+            if (!ptNodeParams.isTerminal()) {
+                return NOT_A_DICT_POS;
+            }
+            // Terminal position is found.
+            return ptNodeParams.getHeadPos();
+        }
+        if (!ptNodeParams.hasChildren()) {
+            return NOT_A_DICT_POS;
+        }
+        // Advance to the children nodes.
+        readChildNode(ptNodeParams);
+    }
+    // If we already traversed the tree further than the word is long, there means
+    // there was no match (or we would have found it).
+    return NOT_A_DICT_POS;
+}
+
+// Read node array size and process empty node arrays. Nodes and arrays are counted up in this
+// method to avoid an infinite loop.
+void DynamicPtReadingHelper::nextPtNodeArray() {
+    int ptNodeCountInArray = 0;
+    int firstPtNodePos = NOT_A_DICT_POS;
+    if (!mPtNodeArrayReader->readPtNodeArrayInfoAndReturnIfValid(
+            mReadingState.mPos, &ptNodeCountInArray, &firstPtNodePos)) {
+        mIsError = true;
+        mReadingState.mPos = NOT_A_DICT_POS;
+        return;
+    }
+    mReadingState.mPosOfThisPtNodeArrayHead = mReadingState.mPos;
+    mReadingState.mRemainingPtNodeCountInThisArray = ptNodeCountInArray;
+    mReadingState.mPos = firstPtNodePos;
+    // Count up nodes and node arrays to avoid infinite loop.
+    mReadingState.mTotalPtNodeIndexInThisArrayChain +=
+            mReadingState.mRemainingPtNodeCountInThisArray;
+    mReadingState.mPtNodeArrayIndexInThisArrayChain++;
+    if (mReadingState.mRemainingPtNodeCountInThisArray < 0
+            || mReadingState.mTotalPtNodeIndexInThisArrayChain
+                    > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP
+            || mReadingState.mPtNodeArrayIndexInThisArrayChain
+                    > MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP) {
+        // Invalid dictionary.
+        AKLOGI("Invalid dictionary. nodeCount: %d, totalNodeCount: %d, MAX_CHILD_COUNT: %d"
+                "nodeArrayCount: %d, MAX_NODE_ARRAY_COUNT: %d",
+                mReadingState.mRemainingPtNodeCountInThisArray,
+                mReadingState.mTotalPtNodeIndexInThisArrayChain,
+                MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP,
+                mReadingState.mPtNodeArrayIndexInThisArrayChain,
+                MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP);
+        ASSERT(false);
+        mIsError = true;
+        mReadingState.mPos = NOT_A_DICT_POS;
+        return;
+    }
+    if (mReadingState.mRemainingPtNodeCountInThisArray == 0) {
+        // Empty node array. Try following forward link.
+        followForwardLink();
+    }
+}
+
+// Follow the forward link and read the next node array if exists.
+void DynamicPtReadingHelper::followForwardLink() {
+    int nextPtNodeArrayPos = NOT_A_DICT_POS;
+    if (!mPtNodeArrayReader->readForwardLinkAndReturnIfValid(
+            mReadingState.mPos, &nextPtNodeArrayPos)) {
+        mIsError = true;
+        mReadingState.mPos = NOT_A_DICT_POS;
+        return;
+    }
+    mReadingState.mPosOfLastForwardLinkField = mReadingState.mPos;
+    if (nextPtNodeArrayPos != NOT_A_DICT_POS) {
+        // Follow the forward link.
+        mReadingState.mPos = nextPtNodeArrayPos;
+        nextPtNodeArray();
+    } else {
+        // All node arrays have been read.
+        mReadingState.mPos = NOT_A_DICT_POS;
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.h b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
new file mode 100644
index 0000000..d8ddc7c
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_PT_READING_HELPER_H
+#define LATINIME_DYNAMIC_PT_READING_HELPER_H
+
+#include <cstddef>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_reader.h"
+
+namespace latinime {
+
+class DictionaryShortcutsStructurePolicy;
+class PtNodeArrayReader;
+
+/*
+ * This class is used for traversing dynamic patricia trie. This class supports iterating nodes and
+ * dealing with additional buffer. This class counts nodes and node arrays to avoid infinite loop.
+ */
+class DynamicPtReadingHelper {
+ public:
+    class TraversingEventListener {
+     public:
+        virtual ~TraversingEventListener() {};
+
+        // Returns whether the event handling was succeeded or not.
+        virtual bool onAscend() = 0;
+
+        // Returns whether the event handling was succeeded or not.
+        virtual bool onDescend(const int ptNodeArrayPos) = 0;
+
+        // Returns whether the event handling was succeeded or not.
+        virtual bool onReadingPtNodeArrayTail() = 0;
+
+        // Returns whether the event handling was succeeded or not.
+        virtual bool onVisitingPtNode(const PtNodeParams *const node) = 0;
+
+     protected:
+        TraversingEventListener() {};
+
+     private:
+        DISALLOW_COPY_AND_ASSIGN(TraversingEventListener);
+    };
+
+    class TraversePolicyToGetAllTerminalPtNodePositions : public TraversingEventListener {
+     public:
+        TraversePolicyToGetAllTerminalPtNodePositions(std::vector<int> *const terminalPositions)
+                : mTerminalPositions(terminalPositions) {}
+        bool onAscend() { return true; }
+        bool onDescend(const int ptNodeArrayPos) { return true; }
+        bool onReadingPtNodeArrayTail() { return true; }
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToGetAllTerminalPtNodePositions);
+
+        std::vector<int> *const mTerminalPositions;
+    };
+
+    DynamicPtReadingHelper(const PtNodeReader *const ptNodeReader,
+            const PtNodeArrayReader *const ptNodeArrayReader)
+            : mIsError(false), mReadingState(), mPtNodeReader(ptNodeReader),
+              mPtNodeArrayReader(ptNodeArrayReader), mReadingStateStack() {}
+
+    ~DynamicPtReadingHelper() {}
+
+    AK_FORCE_INLINE bool isError() const {
+        return mIsError;
+    }
+
+    AK_FORCE_INLINE bool isEnd() const {
+        return mReadingState.mPos == NOT_A_DICT_POS;
+    }
+
+    // Initialize reading state with the head position of a PtNode array.
+    AK_FORCE_INLINE void initWithPtNodeArrayPos(const int ptNodeArrayPos) {
+        if (ptNodeArrayPos == NOT_A_DICT_POS) {
+            mReadingState.mPos = NOT_A_DICT_POS;
+        } else {
+            mIsError = false;
+            mReadingState.mPos = ptNodeArrayPos;
+            mReadingState.mTotalCodePointCountSinceInitialization = 0;
+            mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
+            mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
+            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
+            mReadingStateStack.clear();
+            nextPtNodeArray();
+        }
+    }
+
+    // Initialize reading state with the head position of a node.
+    AK_FORCE_INLINE void initWithPtNodePos(const int ptNodePos) {
+        if (ptNodePos == NOT_A_DICT_POS) {
+            mReadingState.mPos = NOT_A_DICT_POS;
+        } else {
+            mIsError = false;
+            mReadingState.mPos = ptNodePos;
+            mReadingState.mRemainingPtNodeCountInThisArray = 1;
+            mReadingState.mTotalCodePointCountSinceInitialization = 0;
+            mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
+            mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
+            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
+            mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
+            mReadingStateStack.clear();
+        }
+    }
+
+    AK_FORCE_INLINE const PtNodeParams getPtNodeParams() const {
+        if (isEnd()) {
+            return PtNodeParams();
+        }
+        return mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(mReadingState.mPos);
+    }
+
+    AK_FORCE_INLINE bool isValidTerminalNode(const PtNodeParams &ptNodeParams) const {
+        return !isEnd() && !ptNodeParams.isDeleted() && ptNodeParams.isTerminal();
+    }
+
+    AK_FORCE_INLINE bool isMatchedCodePoint(const PtNodeParams &ptNodeParams, const int index,
+            const int codePoint) const {
+        return ptNodeParams.getCodePoints()[index] == codePoint;
+    }
+
+    // Return code point count exclude the last read node's code points.
+    AK_FORCE_INLINE size_t getPrevTotalCodePointCount() const {
+        return mReadingState.mTotalCodePointCountSinceInitialization;
+    }
+
+    // Return code point count include the last read node's code points.
+    AK_FORCE_INLINE size_t getTotalCodePointCount(const PtNodeParams &ptNodeParams) const {
+        return mReadingState.mTotalCodePointCountSinceInitialization
+                + ptNodeParams.getCodePointCount();
+    }
+
+    AK_FORCE_INLINE void fetchMergedNodeCodePointsInReverseOrder(const PtNodeParams &ptNodeParams,
+            const int index, int *const outCodePoints) const {
+        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
+        const int *const nodeCodePoints = ptNodeParams.getCodePoints();
+        for (int i =  0; i < nodeCodePointCount; ++i) {
+            outCodePoints[index + i] = nodeCodePoints[nodeCodePointCount - 1 - i];
+        }
+    }
+
+    AK_FORCE_INLINE void readNextSiblingNode(const PtNodeParams &ptNodeParams) {
+        mReadingState.mRemainingPtNodeCountInThisArray -= 1;
+        mReadingState.mPos = ptNodeParams.getSiblingNodePos();
+        if (mReadingState.mRemainingPtNodeCountInThisArray <= 0) {
+            // All nodes in the current node array have been read.
+            followForwardLink();
+        }
+    }
+
+    // Read the first child node of the current node.
+    AK_FORCE_INLINE void readChildNode(const PtNodeParams &ptNodeParams) {
+        if (ptNodeParams.hasChildren()) {
+            mReadingState.mTotalCodePointCountSinceInitialization +=
+                    ptNodeParams.getCodePointCount();
+            mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
+            mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
+            mReadingState.mPos = ptNodeParams.getChildrenPos();
+            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
+            // Read children node array.
+            nextPtNodeArray();
+        } else {
+            mReadingState.mPos = NOT_A_DICT_POS;
+        }
+    }
+
+    // Read the parent node of the current node.
+    AK_FORCE_INLINE void readParentNode(const PtNodeParams &ptNodeParams) {
+        if (ptNodeParams.getParentPos() != NOT_A_DICT_POS) {
+            mReadingState.mTotalCodePointCountSinceInitialization +=
+                    ptNodeParams.getCodePointCount();
+            mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
+            mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
+            mReadingState.mRemainingPtNodeCountInThisArray = 1;
+            mReadingState.mPos = ptNodeParams.getParentPos();
+            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
+            mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
+        } else {
+            mReadingState.mPos = NOT_A_DICT_POS;
+        }
+    }
+
+    AK_FORCE_INLINE int getPosOfLastForwardLinkField() const {
+        return mReadingState.mPosOfLastForwardLinkField;
+    }
+
+    AK_FORCE_INLINE int getPosOfLastPtNodeArrayHead() const {
+        return mReadingState.mPosOfThisPtNodeArrayHead;
+    }
+
+    bool traverseAllPtNodesInPostorderDepthFirstManner(TraversingEventListener *const listener);
+
+    bool traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+            TraversingEventListener *const listener);
+
+    int getCodePointsAndReturnCodePointCount(const int maxCodePointCount, int *const outCodePoints);
+
+    int getTerminalPtNodePositionOfWord(const int *const inWord, const size_t length,
+            const bool forceLowerCaseSearch);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(DynamicPtReadingHelper);
+
+    // This class encapsulates the reading state of a position in the dictionary. It points at a
+    // specific PtNode in the dictionary.
+    class PtNodeReadingState {
+     public:
+        // Note that copy constructor and assignment operator are used for this class to use
+        // std::vector.
+        PtNodeReadingState() : mPos(NOT_A_DICT_POS), mRemainingPtNodeCountInThisArray(0),
+                mTotalCodePointCountSinceInitialization(0), mTotalPtNodeIndexInThisArrayChain(0),
+                mPtNodeArrayIndexInThisArrayChain(0), mPosOfLastForwardLinkField(NOT_A_DICT_POS),
+                mPosOfThisPtNodeArrayHead(NOT_A_DICT_POS) {}
+
+        int mPos;
+        // Remaining node count in the current array.
+        int mRemainingPtNodeCountInThisArray;
+        size_t mTotalCodePointCountSinceInitialization;
+        // Counter of PtNodes used to avoid infinite loops caused by broken or malicious links.
+        int mTotalPtNodeIndexInThisArrayChain;
+        // Counter of PtNode arrays used to avoid infinite loops caused by cyclic links of empty
+        // PtNode arrays.
+        int mPtNodeArrayIndexInThisArrayChain;
+        int mPosOfLastForwardLinkField;
+        int mPosOfThisPtNodeArrayHead;
+    };
+
+    static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP;
+    static const int MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP;
+    static const size_t MAX_READING_STATE_STACK_SIZE;
+
+    // TODO: Introduce error code to track what caused the error.
+    bool mIsError;
+    PtNodeReadingState mReadingState;
+    const PtNodeReader *const mPtNodeReader;
+    const PtNodeArrayReader *const mPtNodeArrayReader;
+    std::vector<PtNodeReadingState> mReadingStateStack;
+
+    void nextPtNodeArray();
+
+    void followForwardLink();
+
+    AK_FORCE_INLINE void pushReadingStateToStack() {
+        if (mReadingStateStack.size() > MAX_READING_STATE_STACK_SIZE) {
+            AKLOGI("Reading state stack overflow. Max size: %zd", MAX_READING_STATE_STACK_SIZE);
+            ASSERT(false);
+            mIsError = true;
+            mReadingState.mPos = NOT_A_DICT_POS;
+        } else {
+            mReadingStateStack.push_back(mReadingState);
+        }
+    }
+
+    AK_FORCE_INLINE void popReadingStateFromStack() {
+        if (mReadingStateStack.empty()) {
+            mReadingState.mPos = NOT_A_DICT_POS;
+        } else {
+            mReadingState = mReadingStateStack.back();
+            mReadingStateStack.pop_back();
+        }
+    }
+};
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_PT_READING_HELPER_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp
new file mode 100644
index 0000000..3eb55ed
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+
+#include "defines.h"
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::MASK_MOVED = 0xC0;
+const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_NOT_MOVED = 0xC0;
+const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_MOVED = 0x40;
+const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_DELETED = 0x80;
+const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_WILL_BECOME_NON_TERMINAL = 0x00;
+
+// TODO: Make DICT_OFFSET_ZERO_OFFSET = 0.
+// Currently, DICT_OFFSET_INVALID is 0 in Java side but offset can be 0 during GC. So, the maximum
+// value of offsets, which is 0x7FFFFF is used to represent 0 offset.
+const int DynamicPtReadingUtils::DICT_OFFSET_INVALID = 0;
+const int DynamicPtReadingUtils::DICT_OFFSET_ZERO_OFFSET = 0x7FFFFF;
+
+/* static */ int DynamicPtReadingUtils::getForwardLinkPosition(const uint8_t *const buffer,
+        const int pos) {
+    int linkAddressPos = pos;
+    return ByteArrayUtils::readSint24AndAdvancePosition(buffer, &linkAddressPos);
+}
+
+/* static */ int DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
+        const uint8_t *const buffer, int *const pos) {
+    return ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
+}
+
+/* static */ int DynamicPtReadingUtils::getParentPtNodePos(const int parentOffset,
+        const int ptNodePos) {
+    if (parentOffset == DICT_OFFSET_INVALID) {
+        return NOT_A_DICT_POS;
+    } else if (parentOffset == DICT_OFFSET_ZERO_OFFSET) {
+        return ptNodePos;
+    } else {
+        return parentOffset + ptNodePos;
+    }
+}
+
+/* static */ int DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
+        const uint8_t *const buffer, int *const pos) {
+    const int base = *pos;
+    const int offset = ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
+    if (offset == DICT_OFFSET_INVALID) {
+        // The PtNode does not have children.
+        return NOT_A_DICT_POS;
+    } else if (offset == DICT_OFFSET_ZERO_OFFSET) {
+        return base;
+    } else {
+        return base + offset;
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_utils.h
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h
rename to native/jni/src/dictionary/structure/pt_common/dynamic_pt_reading_utils.h
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
new file mode 100644
index 0000000..ccad345
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
@@ -0,0 +1,299 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
+
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/pt_common/pt_node_reader.h"
+#include "dictionary/structure/pt_common/pt_node_writer.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+const int DynamicPtUpdatingHelper::CHILDREN_POSITION_FIELD_SIZE = 3;
+
+bool DynamicPtUpdatingHelper::addUnigramWord(DynamicPtReadingHelper *const readingHelper,
+        const CodePointArrayView wordCodePoints, const UnigramProperty *const unigramProperty,
+        bool *const outAddedNewUnigram) {
+    int parentPos = NOT_A_DICT_POS;
+    while (!readingHelper->isEnd()) {
+        const PtNodeParams ptNodeParams(readingHelper->getPtNodeParams());
+        if (!ptNodeParams.isValid()) {
+            break;
+        }
+        const size_t matchedCodePointCount = readingHelper->getPrevTotalCodePointCount();
+        if (!readingHelper->isMatchedCodePoint(ptNodeParams, 0 /* index */,
+                wordCodePoints[matchedCodePointCount])) {
+            // The first code point is different from target code point. Skip this node and read
+            // the next sibling node.
+            readingHelper->readNextSiblingNode(ptNodeParams);
+            continue;
+        }
+        // Check following merged node code points.
+        const size_t nodeCodePointCount = ptNodeParams.getCodePointArrayView().size();
+        for (size_t j = 1; j < nodeCodePointCount; ++j) {
+            const size_t nextIndex = matchedCodePointCount + j;
+            if (nextIndex >= wordCodePoints.size()
+                    || !readingHelper->isMatchedCodePoint(ptNodeParams, j,
+                            wordCodePoints[matchedCodePointCount + j])) {
+                *outAddedNewUnigram = true;
+                return reallocatePtNodeAndAddNewPtNodes(&ptNodeParams, j, unigramProperty,
+                        wordCodePoints.skip(matchedCodePointCount));
+            }
+        }
+        // All characters are matched.
+        if (wordCodePoints.size() == readingHelper->getTotalCodePointCount(ptNodeParams)) {
+            return setPtNodeProbability(&ptNodeParams, unigramProperty, outAddedNewUnigram);
+        }
+        if (!ptNodeParams.hasChildren()) {
+            *outAddedNewUnigram = true;
+            return createChildrenPtNodeArrayAndAChildPtNode(&ptNodeParams, unigramProperty,
+                    wordCodePoints.skip(readingHelper->getTotalCodePointCount(ptNodeParams)));
+        }
+        // Advance to the children nodes.
+        parentPos = ptNodeParams.getHeadPos();
+        readingHelper->readChildNode(ptNodeParams);
+    }
+    if (readingHelper->isError()) {
+        // The dictionary is invalid.
+        return false;
+    }
+    int pos = readingHelper->getPosOfLastForwardLinkField();
+    *outAddedNewUnigram = true;
+    return createAndInsertNodeIntoPtNodeArray(parentPos,
+            wordCodePoints.skip(readingHelper->getPrevTotalCodePointCount()), unigramProperty,
+            &pos);
+}
+
+bool DynamicPtUpdatingHelper::addNgramEntry(const PtNodePosArrayView prevWordsPtNodePos,
+        const int wordPos, const NgramProperty *const ngramProperty,
+        bool *const outAddedNewEntry) {
+    if (prevWordsPtNodePos.empty()) {
+        return false;
+    }
+    ASSERT(prevWordsPtNodePos.size() <= MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+    int prevWordTerminalIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
+        prevWordTerminalIds[i] = mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(
+                prevWordsPtNodePos[i]).getTerminalId();
+    }
+    const WordIdArrayView prevWordIds(prevWordTerminalIds, prevWordsPtNodePos.size());
+    const int wordId =
+            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos).getTerminalId();
+    return mPtNodeWriter->addNgramEntry(prevWordIds, wordId, ngramProperty, outAddedNewEntry);
+}
+
+bool DynamicPtUpdatingHelper::removeNgramEntry(const PtNodePosArrayView prevWordsPtNodePos,
+        const int wordPos) {
+    if (prevWordsPtNodePos.empty()) {
+        return false;
+    }
+    ASSERT(prevWordsPtNodePos.size() <= MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+    int prevWordTerminalIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
+        prevWordTerminalIds[i] = mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(
+                prevWordsPtNodePos[i]).getTerminalId();
+    }
+    const WordIdArrayView prevWordIds(prevWordTerminalIds, prevWordsPtNodePos.size());
+    const int wordId =
+            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos).getTerminalId();
+    return mPtNodeWriter->removeNgramEntry(prevWordIds, wordId);
+}
+
+bool DynamicPtUpdatingHelper::addShortcutTarget(const int wordPos,
+        const CodePointArrayView targetCodePoints, const int shortcutProbability) {
+    const PtNodeParams ptNodeParams(mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos));
+    return mPtNodeWriter->addShortcutTarget(&ptNodeParams, targetCodePoints.data(),
+            targetCodePoints.size(), shortcutProbability);
+}
+
+bool DynamicPtUpdatingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos,
+        const CodePointArrayView ptNodeCodePoints, const UnigramProperty *const unigramProperty,
+        int *const forwardLinkFieldPos) {
+    const int newPtNodeArrayPos = mBuffer->getTailPosition();
+    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
+            newPtNodeArrayPos, forwardLinkFieldPos)) {
+        return false;
+    }
+    return createNewPtNodeArrayWithAChildPtNode(parentPos, ptNodeCodePoints, unigramProperty);
+}
+
+bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
+        const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram) {
+    if (originalPtNodeParams->isTerminal() && !originalPtNodeParams->isDeleted()) {
+        // Overwrites the probability.
+        *outAddedNewUnigram = false;
+        return mPtNodeWriter->updatePtNodeUnigramProperty(originalPtNodeParams, unigramProperty);
+    } else {
+        // Make the node terminal and write the probability.
+        *outAddedNewUnigram = true;
+        const int movedPos = mBuffer->getTailPosition();
+        int writingPos = movedPos;
+        const PtNodeParams ptNodeParamsToWrite(getUpdatedPtNodeParams(originalPtNodeParams,
+                unigramProperty->isNotAWord(), unigramProperty->isPossiblyOffensive(),
+                true /* isTerminal */, originalPtNodeParams->getParentPos(),
+                originalPtNodeParams->getCodePointArrayView(), unigramProperty->getProbability()));
+        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
+                unigramProperty, &writingPos)) {
+            return false;
+        }
+        if (!mPtNodeWriter->markPtNodeAsMoved(originalPtNodeParams, movedPos, movedPos)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool DynamicPtUpdatingHelper::createChildrenPtNodeArrayAndAChildPtNode(
+        const PtNodeParams *const parentPtNodeParams, const UnigramProperty *const unigramProperty,
+        const CodePointArrayView codePoints) {
+    const int newPtNodeArrayPos = mBuffer->getTailPosition();
+    if (!mPtNodeWriter->updateChildrenPosition(parentPtNodeParams, newPtNodeArrayPos)) {
+        return false;
+    }
+    return createNewPtNodeArrayWithAChildPtNode(parentPtNodeParams->getHeadPos(), codePoints,
+            unigramProperty);
+}
+
+bool DynamicPtUpdatingHelper::createNewPtNodeArrayWithAChildPtNode(
+        const int parentPtNodePos, const CodePointArrayView ptNodeCodePoints,
+        const UnigramProperty *const unigramProperty) {
+    int writingPos = mBuffer->getTailPosition();
+    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer,
+            1 /* arraySize */, &writingPos)) {
+        return false;
+    }
+    const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
+            unigramProperty->isNotAWord(), unigramProperty->isPossiblyOffensive(),
+            true /* isTerminal */, parentPtNodePos, ptNodeCodePoints,
+            unigramProperty->getProbability()));
+    if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
+            unigramProperty, &writingPos)) {
+        return false;
+    }
+    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
+            NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
+        return false;
+    }
+    return true;
+}
+
+// Returns whether the dictionary updating was succeeded or not.
+bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
+        const PtNodeParams *const reallocatingPtNodeParams, const size_t overlappingCodePointCount,
+        const UnigramProperty *const unigramProperty,
+        const CodePointArrayView newPtNodeCodePoints) {
+    // When addsExtraChild is true, split the reallocating PtNode and add new child.
+    // Reallocating PtNode: abcde, newNode: abcxy.
+    // abc (1st, not terminal) __ de (2nd)
+    //                         \_ xy (extra child, terminal)
+    // Otherwise, this method makes 1st part terminal and write information in unigramProperty.
+    // Reallocating PtNode: abcde, newNode: abc.
+    // abc (1st, terminal) __ de (2nd)
+    const bool addsExtraChild = newPtNodeCodePoints.size() > overlappingCodePointCount;
+    const int firstPartOfReallocatedPtNodePos = mBuffer->getTailPosition();
+    int writingPos = firstPartOfReallocatedPtNodePos;
+    // Write the 1st part of the reallocating node. The children position will be updated later
+    // with actual children position.
+    const CodePointArrayView firstPtNodeCodePoints =
+            reallocatingPtNodeParams->getCodePointArrayView().limit(overlappingCodePointCount);
+    if (addsExtraChild) {
+        const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
+                false /* isNotAWord */, false /* isPossiblyOffensive */, false /* isTerminal */,
+                reallocatingPtNodeParams->getParentPos(), firstPtNodeCodePoints,
+                NOT_A_PROBABILITY));
+        if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) {
+            return false;
+        }
+    } else {
+        const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
+                unigramProperty->isNotAWord(), unigramProperty->isPossiblyOffensive(),
+                true /* isTerminal */, reallocatingPtNodeParams->getParentPos(),
+                firstPtNodeCodePoints, unigramProperty->getProbability()));
+        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
+                unigramProperty, &writingPos)) {
+            return false;
+        }
+    }
+    const int actualChildrenPos = writingPos;
+    // Create new children PtNode array.
+    const size_t newPtNodeCount = addsExtraChild ? 2 : 1;
+    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer,
+            newPtNodeCount, &writingPos)) {
+        return false;
+    }
+    // Write the 2nd part of the reallocating node.
+    const int secondPartOfReallocatedPtNodePos = writingPos;
+    const PtNodeParams childPartPtNodeParams(getUpdatedPtNodeParams(reallocatingPtNodeParams,
+            reallocatingPtNodeParams->isNotAWord(), reallocatingPtNodeParams->isPossiblyOffensive(),
+            reallocatingPtNodeParams->isTerminal(), firstPartOfReallocatedPtNodePos,
+            reallocatingPtNodeParams->getCodePointArrayView().skip(overlappingCodePointCount),
+            reallocatingPtNodeParams->getProbability()));
+    if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&childPartPtNodeParams, &writingPos)) {
+        return false;
+    }
+    if (addsExtraChild) {
+        const PtNodeParams extraChildPtNodeParams(getPtNodeParamsForNewPtNode(
+                unigramProperty->isNotAWord(), unigramProperty->isPossiblyOffensive(),
+                true /* isTerminal */, firstPartOfReallocatedPtNodePos,
+                newPtNodeCodePoints.skip(overlappingCodePointCount),
+                unigramProperty->getProbability()));
+        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&extraChildPtNodeParams,
+                unigramProperty, &writingPos)) {
+            return false;
+        }
+    }
+    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
+            NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
+        return false;
+    }
+    // Update original reallocating PtNode as moved.
+    if (!mPtNodeWriter->markPtNodeAsMoved(reallocatingPtNodeParams, firstPartOfReallocatedPtNodePos,
+            secondPartOfReallocatedPtNodePos)) {
+        return false;
+    }
+    // Load node info. Information of the 1st part will be fetched.
+    const PtNodeParams ptNodeParams(
+            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos));
+    // Update children position.
+    return mPtNodeWriter->updateChildrenPosition(&ptNodeParams, actualChildrenPos);
+}
+
+const PtNodeParams DynamicPtUpdatingHelper::getUpdatedPtNodeParams(
+        const PtNodeParams *const originalPtNodeParams, const bool isNotAWord,
+        const bool isPossiblyOffensive, const bool isTerminal, const int parentPos,
+        const CodePointArrayView codePoints, const int probability) const {
+    const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
+            isPossiblyOffensive, isNotAWord, isTerminal, false /* hasShortcutTargets */,
+            false /* hasBigrams */, codePoints.size() > 1u /* hasMultipleChars */,
+            CHILDREN_POSITION_FIELD_SIZE);
+    return PtNodeParams(originalPtNodeParams, flags, parentPos, codePoints, probability);
+}
+
+const PtNodeParams DynamicPtUpdatingHelper::getPtNodeParamsForNewPtNode(const bool isNotAWord,
+        const bool isPossiblyOffensive, const bool isTerminal, const int parentPos,
+        const CodePointArrayView codePoints, const int probability) const {
+    const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
+            isPossiblyOffensive, isNotAWord, isTerminal, false /* hasShortcutTargets */,
+            false /* hasBigrams */, codePoints.size() > 1u /* hasMultipleChars */,
+            CHILDREN_POSITION_FIELD_SIZE);
+    return PtNodeParams(flags, parentPos, codePoints, probability);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.h b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
new file mode 100644
index 0000000..e8cf98c
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_PT_UPDATING_HELPER_H
+#define LATINIME_DYNAMIC_PT_UPDATING_HELPER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class NgramProperty;
+class BufferWithExtendableBuffer;
+class DynamicPtReadingHelper;
+class PtNodeReader;
+class PtNodeWriter;
+class UnigramProperty;
+
+class DynamicPtUpdatingHelper {
+ public:
+    DynamicPtUpdatingHelper(BufferWithExtendableBuffer *const buffer,
+            const PtNodeReader *const ptNodeReader, PtNodeWriter *const ptNodeWriter)
+            : mBuffer(buffer), mPtNodeReader(ptNodeReader), mPtNodeWriter(ptNodeWriter) {}
+
+    ~DynamicPtUpdatingHelper() {}
+
+    // Add a word to the dictionary. If the word already exists, update the probability.
+    bool addUnigramWord(DynamicPtReadingHelper *const readingHelper,
+            const CodePointArrayView wordCodePoints, const UnigramProperty *const unigramProperty,
+            bool *const outAddedNewUnigram);
+
+    // TODO: Remove after stopping supporting v402.
+    // Add an n-gram entry.
+    bool addNgramEntry(const PtNodePosArrayView prevWordsPtNodePos, const int wordPos,
+            const NgramProperty *const ngramProperty, bool *const outAddedNewEntry);
+
+    // TODO: Remove after stopping supporting v402.
+    // Remove an n-gram entry.
+    bool removeNgramEntry(const PtNodePosArrayView prevWordsPtNodePos, const int wordPos);
+
+    // Add a shortcut target.
+    bool addShortcutTarget(const int wordPos, const CodePointArrayView targetCodePoints,
+            const int shortcutProbability);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtUpdatingHelper);
+
+    static const int CHILDREN_POSITION_FIELD_SIZE;
+
+    BufferWithExtendableBuffer *const mBuffer;
+    const PtNodeReader *const mPtNodeReader;
+    PtNodeWriter *const mPtNodeWriter;
+
+    bool createAndInsertNodeIntoPtNodeArray(const int parentPos,
+            const CodePointArrayView ptNodeCodePoints, const UnigramProperty *const unigramProperty,
+            int *const forwardLinkFieldPos);
+
+    bool setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
+            const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
+
+    bool createChildrenPtNodeArrayAndAChildPtNode(const PtNodeParams *const parentPtNodeParams,
+            const UnigramProperty *const unigramProperty,
+            const CodePointArrayView remainingCodePoints);
+
+    bool createNewPtNodeArrayWithAChildPtNode(const int parentPos,
+            const CodePointArrayView ptNodeCodePoints,
+            const UnigramProperty *const unigramProperty);
+
+    bool reallocatePtNodeAndAddNewPtNodes(const PtNodeParams *const reallocatingPtNodeParams,
+            const size_t overlappingCodePointCount, const UnigramProperty *const unigramProperty,
+            const CodePointArrayView newPtNodeCodePoints);
+
+    const PtNodeParams getUpdatedPtNodeParams(const PtNodeParams *const originalPtNodeParams,
+            const bool isNotAWord, const bool isPossiblyOffensive, const bool isTerminal,
+            const int parentPos, const CodePointArrayView codePoints, const int probability) const;
+
+    const PtNodeParams getPtNodeParamsForNewPtNode(const bool isNotAWord,
+            const bool isPossiblyOffensive, const bool isTerminal, const int parentPos,
+            const CodePointArrayView codePoints, const int probability) const;
+};
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp
new file mode 100644
index 0000000..ea760a5
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+const size_t DynamicPtWritingUtils::MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD = 0x7F;
+const size_t DynamicPtWritingUtils::MAX_PTNODE_ARRAY_SIZE = 0x7FFF;
+const int DynamicPtWritingUtils::SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE = 1;
+const int DynamicPtWritingUtils::LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE = 2;
+const int DynamicPtWritingUtils::LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG = 0x8000;
+const int DynamicPtWritingUtils::DICT_OFFSET_FIELD_SIZE = 3;
+const int DynamicPtWritingUtils::MAX_DICT_OFFSET_VALUE = 0x7FFFFF;
+const int DynamicPtWritingUtils::MIN_DICT_OFFSET_VALUE = -0x7FFFFF;
+const int DynamicPtWritingUtils::DICT_OFFSET_NEGATIVE_FLAG = 0x800000;
+const int DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE = 1;
+
+/* static */ bool DynamicPtWritingUtils::writeEmptyDictionary(
+        BufferWithExtendableBuffer *const buffer, const int rootPos) {
+    int writingPos = rootPos;
+    if (!writePtNodeArraySizeAndAdvancePosition(buffer, 0 /* arraySize */, &writingPos)) {
+        return false;
+    }
+    return writeForwardLinkPositionAndAdvancePosition(buffer, NOT_A_DICT_POS /* forwardLinkPos */,
+            &writingPos);
+}
+
+/* static */ bool DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
+        int *const forwardLinkFieldPos) {
+    return writeDictOffset(buffer, forwardLinkPos, (*forwardLinkFieldPos), forwardLinkFieldPos);
+}
+
+/* static */ bool DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer, const size_t arraySize,
+        int *const arraySizeFieldPos) {
+    // Currently, all array size field to be created has LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE to
+    // simplify updating process.
+    // TODO: Use SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE for small arrays.
+    /*if (arraySize <= MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD) {
+        return buffer->writeUintAndAdvancePosition(arraySize, SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE,
+                arraySizeFieldPos);
+    } else */
+    if (arraySize <= MAX_PTNODE_ARRAY_SIZE) {
+        uint32_t data = arraySize | LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG;
+        return buffer->writeUintAndAdvancePosition(data, LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE,
+                arraySizeFieldPos);
+    } else {
+        AKLOGI("PtNode array size cannot be written because arraySize is too large: %zd",
+                arraySize);
+        ASSERT(false);
+        return false;
+    }
+}
+
+/* static */ bool DynamicPtWritingUtils::writeFlagsAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer,
+        const DynamicPtReadingUtils::NodeFlags nodeFlags, int *const nodeFlagsFieldPos) {
+    return buffer->writeUintAndAdvancePosition(nodeFlags, NODE_FLAG_FIELD_SIZE, nodeFlagsFieldPos);
+}
+
+// Note that parentOffset is offset from node's head position.
+/* static */ bool DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer, const int parentPos, const int basePos,
+        int *const parentPosFieldPos) {
+    return writeDictOffset(buffer, parentPos, basePos, parentPosFieldPos);
+}
+
+/* static */ bool DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer, const int *const codePoints,
+        const int codePointCount, int *const codePointFieldPos) {
+    if (codePointCount <= 0) {
+        AKLOGI("code points cannot be written because codePointCount is invalid: %d",
+                codePointCount);
+        ASSERT(false);
+        return false;
+    }
+    const bool hasMultipleCodePoints = codePointCount > 1;
+    return buffer->writeCodePointsAndAdvancePosition(codePoints, codePointCount,
+            hasMultipleCodePoints, codePointFieldPos);
+}
+
+/* static */ bool DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(
+        BufferWithExtendableBuffer *const buffer, const int childrenPosition,
+        int *const childrenPositionFieldPos) {
+    return writeDictOffset(buffer, childrenPosition, (*childrenPositionFieldPos),
+            childrenPositionFieldPos);
+}
+
+/* static */ bool DynamicPtWritingUtils::writeDictOffset(BufferWithExtendableBuffer *const buffer,
+        const int targetPos, const int basePos, int *const offsetFieldPos) {
+    int offset = targetPos - basePos;
+    if (targetPos == NOT_A_DICT_POS) {
+        offset = DynamicPtReadingUtils::DICT_OFFSET_INVALID;
+    } else if (offset == 0) {
+        offset = DynamicPtReadingUtils::DICT_OFFSET_ZERO_OFFSET;
+    }
+    if (offset > MAX_DICT_OFFSET_VALUE || offset < MIN_DICT_OFFSET_VALUE) {
+        AKLOGI("offset cannot be written because the offset is too large or too small: %d",
+                offset);
+        ASSERT(false);
+        return false;
+    }
+    uint32_t data = 0;
+    if (offset >= 0) {
+        data = offset;
+    } else {
+        data = abs(offset) | DICT_OFFSET_NEGATIVE_FLAG;
+    }
+    return buffer->writeUintAndAdvancePosition(data, DICT_OFFSET_FIELD_SIZE, offsetFieldPos);
+}
+}
diff --git a/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.h b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.h
new file mode 100644
index 0000000..b4817af
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/dynamic_pt_writing_utils.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_PT_WRITING_UTILS_H
+#define LATINIME_DYNAMIC_PT_WRITING_UTILS_H
+
+#include <cstddef>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+
+class DynamicPtWritingUtils {
+ public:
+    static const int NODE_FLAG_FIELD_SIZE;
+
+    static bool writeEmptyDictionary(BufferWithExtendableBuffer *const buffer, const int rootPos);
+
+    static bool writeForwardLinkPositionAndAdvancePosition(
+            BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
+            int *const forwardLinkFieldPos);
+
+    static bool writePtNodeArraySizeAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
+            const size_t arraySize, int *const arraySizeFieldPos);
+
+    static bool writeFlags(BufferWithExtendableBuffer *const buffer,
+            const DynamicPtReadingUtils::NodeFlags nodeFlags,
+            const int nodeFlagsFieldPos) {
+        int writingPos = nodeFlagsFieldPos;
+        return writeFlagsAndAdvancePosition(buffer, nodeFlags, &writingPos);
+    }
+
+    static bool writeFlagsAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
+            const DynamicPtReadingUtils::NodeFlags nodeFlags,
+            int *const nodeFlagsFieldPos);
+
+    static bool writeParentPosOffsetAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
+            const int parentPosition, const int basePos, int *const parentPosFieldPos);
+
+    static bool writeCodePointsAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
+            const int *const codePoints, const int codePointCount, int *const codePointFieldPos);
+
+    static bool writeChildrenPositionAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
+            const int childrenPosition, int *const childrenPositionFieldPos);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtWritingUtils);
+
+    static const size_t MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD;
+    static const size_t MAX_PTNODE_ARRAY_SIZE;
+    static const int SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE;
+    static const int LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE;
+    static const int LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG;
+    static const int DICT_OFFSET_FIELD_SIZE;
+    static const int MAX_DICT_OFFSET_VALUE;
+    static const int MIN_DICT_OFFSET_VALUE;
+    static const int DICT_OFFSET_NEGATIVE_FLAG;
+
+    static bool writeDictOffset(BufferWithExtendableBuffer *const buffer, const int targetPos,
+            const int basePos, int *const offsetFieldPos);
+};
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_PT_WRITING_UTILS_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp b/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp
new file mode 100644
index 0000000..e2807c4
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_bigrams_structure_policy.h"
+#include "dictionary/interface/dictionary_shortcuts_structure_policy.h"
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+typedef PatriciaTrieReadingUtils PtReadingUtils;
+
+const PtReadingUtils::NodeFlags PtReadingUtils::MASK_CHILDREN_POSITION_TYPE = 0xC0;
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_NOPOSITION = 0x00;
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_ONEBYTE = 0x40;
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_TWOBYTES = 0x80;
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_THREEBYTES = 0xC0;
+
+// Flag for single/multiple char group
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_MULTIPLE_CHARS = 0x20;
+// Flag for terminal PtNodes
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_TERMINAL = 0x10;
+// Flag for shortcut targets presence
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_SHORTCUT_TARGETS = 0x08;
+// Flag for bigram presence
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_BIGRAMS = 0x04;
+// Flag for non-words (typically, shortcut only entries)
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_NOT_A_WORD = 0x02;
+// Flag for possibly offensive words
+const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_POSSIBLY_OFFENSIVE = 0x01;
+
+/* static */ int PtReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+        const uint8_t *const buffer, int *const pos) {
+    const uint8_t firstByte = ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
+    if (firstByte < 0x80) {
+        return firstByte;
+    } else {
+        return ((firstByte & 0x7F) << 8) ^ ByteArrayUtils::readUint8AndAdvancePosition(
+                buffer, pos);
+    }
+}
+
+/* static */ PtReadingUtils::NodeFlags PtReadingUtils::getFlagsAndAdvancePosition(
+        const uint8_t *const buffer, int *const pos) {
+    return ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
+}
+
+/* static */ int PtReadingUtils::getCodePointAndAdvancePosition(const uint8_t *const buffer,
+        const int *const codePointTable, int *const pos) {
+    return ByteArrayUtils::readCodePointAndAdvancePosition(buffer, codePointTable, pos);
+}
+
+// Returns the number of read characters.
+/* static */ int PtReadingUtils::getCharsAndAdvancePosition(const uint8_t *const buffer,
+        const NodeFlags flags, const int maxLength, const int *const codePointTable,
+        int *const outBuffer, int *const pos) {
+    int length = 0;
+    if (hasMultipleChars(flags)) {
+        length = ByteArrayUtils::readStringAndAdvancePosition(buffer, maxLength, codePointTable,
+                outBuffer, pos);
+    } else {
+        const int codePoint = getCodePointAndAdvancePosition(buffer, codePointTable, pos);
+        if (codePoint == NOT_A_CODE_POINT) {
+            // CAVEAT: codePoint == NOT_A_CODE_POINT means the code point is
+            // CHARACTER_ARRAY_TERMINATOR. The code point must not be CHARACTER_ARRAY_TERMINATOR
+            // when the PtNode has a single code point.
+            length = 0;
+            AKLOGE("codePoint is NOT_A_CODE_POINT. pos: %d, codePoint: 0x%x, buffer[pos - 1]: 0x%x",
+                    *pos - 1, codePoint, buffer[*pos - 1]);
+            ASSERT(false);
+        } else if (maxLength > 0) {
+            outBuffer[0] = codePoint;
+            length = 1;
+        }
+    }
+    return length;
+}
+
+// Returns the number of skipped characters.
+/* static */ int PtReadingUtils::skipCharacters(const uint8_t *const buffer, const NodeFlags flags,
+        const int maxLength, const int *const codePointTable, int *const pos) {
+    if (hasMultipleChars(flags)) {
+        return ByteArrayUtils::advancePositionToBehindString(buffer, maxLength, pos);
+    } else {
+        if (maxLength > 0) {
+            getCodePointAndAdvancePosition(buffer, codePointTable, pos);
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
+
+/* static */ int PtReadingUtils::readProbabilityAndAdvancePosition(const uint8_t *const buffer,
+        int *const pos) {
+    return ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
+}
+
+/* static */ int PtReadingUtils::readChildrenPositionAndAdvancePosition(
+        const uint8_t *const buffer, const NodeFlags flags, int *const pos) {
+    const int base = *pos;
+    int offset = 0;
+    switch (MASK_CHILDREN_POSITION_TYPE & flags) {
+        case FLAG_CHILDREN_POSITION_TYPE_ONEBYTE:
+            offset = ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
+            break;
+        case FLAG_CHILDREN_POSITION_TYPE_TWOBYTES:
+            offset = ByteArrayUtils::readUint16AndAdvancePosition(buffer, pos);
+            break;
+        case FLAG_CHILDREN_POSITION_TYPE_THREEBYTES:
+            offset = ByteArrayUtils::readUint24AndAdvancePosition(buffer, pos);
+            break;
+        default:
+            // If we come here, it means we asked for the children of a word with
+            // no children.
+            return NOT_A_DICT_POS;
+    }
+    return base + offset;
+}
+
+/* static */ void PtReadingUtils::readPtNodeInfo(const uint8_t *const dictBuf, const int ptNodePos,
+        const DictionaryShortcutsStructurePolicy *const shortcutPolicy,
+        const DictionaryBigramsStructurePolicy *const bigramPolicy, const int *const codePointTable,
+        NodeFlags *const outFlags, int *const outCodePointCount, int *const outCodePoint,
+        int *const outProbability, int *const outChildrenPos, int *const outShortcutPos,
+        int *const outBigramPos, int *const outSiblingPos) {
+    int readingPos = ptNodePos;
+    const NodeFlags flags = getFlagsAndAdvancePosition(dictBuf, &readingPos);
+    *outFlags = flags;
+    *outCodePointCount = getCharsAndAdvancePosition(
+            dictBuf, flags, MAX_WORD_LENGTH, codePointTable, outCodePoint, &readingPos);
+    *outProbability = isTerminal(flags) ?
+            readProbabilityAndAdvancePosition(dictBuf, &readingPos) : NOT_A_PROBABILITY;
+    *outChildrenPos = hasChildrenInFlags(flags) ?
+            readChildrenPositionAndAdvancePosition(dictBuf, flags, &readingPos) : NOT_A_DICT_POS;
+    *outShortcutPos = NOT_A_DICT_POS;
+    if (hasShortcutTargets(flags)) {
+        *outShortcutPos = readingPos;
+        shortcutPolicy->skipAllShortcuts(&readingPos);
+    }
+    *outBigramPos = NOT_A_DICT_POS;
+    if (hasBigrams(flags)) {
+        *outBigramPos = readingPos;
+        bigramPolicy->skipAllBigrams(&readingPos);
+    }
+    *outSiblingPos = readingPos;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.h b/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.h
new file mode 100644
index 0000000..6a2bf5d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/patricia_trie_reading_utils.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PATRICIA_TRIE_READING_UTILS_H
+#define LATINIME_PATRICIA_TRIE_READING_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+
+namespace latinime {
+
+class DictionaryShortcutsStructurePolicy;
+class DictionaryBigramsStructurePolicy;
+
+class PatriciaTrieReadingUtils {
+ public:
+    typedef uint8_t NodeFlags;
+
+    static int getPtNodeArraySizeAndAdvancePosition(const uint8_t *const buffer, int *const pos);
+
+    static NodeFlags getFlagsAndAdvancePosition(const uint8_t *const buffer, int *const pos);
+
+    static int getCodePointAndAdvancePosition(const uint8_t *const buffer,
+            const int *const codePointTable, int *const pos);
+
+    // Returns the number of read characters.
+    static int getCharsAndAdvancePosition(const uint8_t *const buffer, const NodeFlags flags,
+            const int maxLength, const int *const codePointTable, int *const outBuffer,
+            int *const pos);
+
+    // Returns the number of skipped characters.
+    static int skipCharacters(const uint8_t *const buffer, const NodeFlags flags,
+            const int maxLength, const int *const codePointTable, int *const pos);
+
+    static int readProbabilityAndAdvancePosition(const uint8_t *const buffer, int *const pos);
+
+    static int readChildrenPositionAndAdvancePosition(const uint8_t *const buffer,
+            const NodeFlags flags, int *const pos);
+
+    /**
+     * Node Flags
+     */
+    static AK_FORCE_INLINE bool isPossiblyOffensive(const NodeFlags flags) {
+        return (flags & FLAG_IS_POSSIBLY_OFFENSIVE) != 0;
+    }
+
+    static AK_FORCE_INLINE bool isNotAWord(const NodeFlags flags) {
+        return (flags & FLAG_IS_NOT_A_WORD) != 0;
+    }
+
+    static AK_FORCE_INLINE bool isTerminal(const NodeFlags flags) {
+        return (flags & FLAG_IS_TERMINAL) != 0;
+    }
+
+    static AK_FORCE_INLINE bool hasShortcutTargets(const NodeFlags flags) {
+        return (flags & FLAG_HAS_SHORTCUT_TARGETS) != 0;
+    }
+
+    static AK_FORCE_INLINE bool hasBigrams(const NodeFlags flags) {
+        return (flags & FLAG_HAS_BIGRAMS) != 0;
+    }
+
+    static AK_FORCE_INLINE bool hasMultipleChars(const NodeFlags flags) {
+        return (flags & FLAG_HAS_MULTIPLE_CHARS) != 0;
+    }
+
+    static AK_FORCE_INLINE bool hasChildrenInFlags(const NodeFlags flags) {
+        return FLAG_CHILDREN_POSITION_TYPE_NOPOSITION != (MASK_CHILDREN_POSITION_TYPE & flags);
+    }
+
+    static AK_FORCE_INLINE NodeFlags createAndGetFlags(const bool isPossiblyOffensive,
+            const bool isNotAWord, const bool isTerminal, const bool hasShortcutTargets,
+            const bool hasBigrams, const bool hasMultipleChars,
+            const int childrenPositionFieldSize) {
+        NodeFlags nodeFlags = 0;
+        nodeFlags = isPossiblyOffensive ? (nodeFlags | FLAG_IS_POSSIBLY_OFFENSIVE) : nodeFlags;
+        nodeFlags = isNotAWord ? (nodeFlags | FLAG_IS_NOT_A_WORD) : nodeFlags;
+        nodeFlags = isTerminal ? (nodeFlags | FLAG_IS_TERMINAL) : nodeFlags;
+        nodeFlags = hasShortcutTargets ? (nodeFlags | FLAG_HAS_SHORTCUT_TARGETS) : nodeFlags;
+        nodeFlags = hasBigrams ? (nodeFlags | FLAG_HAS_BIGRAMS) : nodeFlags;
+        nodeFlags = hasMultipleChars ? (nodeFlags | FLAG_HAS_MULTIPLE_CHARS) : nodeFlags;
+        if (childrenPositionFieldSize == 1) {
+            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_ONEBYTE;
+        } else if (childrenPositionFieldSize == 2) {
+            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_TWOBYTES;
+        } else if (childrenPositionFieldSize == 3) {
+            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_THREEBYTES;
+        } else {
+            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_NOPOSITION;
+        }
+        return nodeFlags;
+    }
+
+    static void readPtNodeInfo(const uint8_t *const dictBuf, const int ptNodePos,
+            const DictionaryShortcutsStructurePolicy *const shortcutPolicy,
+            const DictionaryBigramsStructurePolicy *const bigramPolicy,
+            const int *const codePointTable, NodeFlags *const outFlags,
+            int *const outCodePointCount, int *const outCodePoint, int *const outProbability,
+            int *const outChildrenPos, int *const outShortcutPos, int *const outBigramPos,
+            int *const outSiblingPos);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTrieReadingUtils);
+
+    static const NodeFlags MASK_CHILDREN_POSITION_TYPE;
+    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_NOPOSITION;
+    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_ONEBYTE;
+    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_TWOBYTES;
+    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_THREEBYTES;
+
+    static const NodeFlags FLAG_HAS_MULTIPLE_CHARS;
+    static const NodeFlags FLAG_IS_TERMINAL;
+    static const NodeFlags FLAG_HAS_SHORTCUT_TARGETS;
+    static const NodeFlags FLAG_HAS_BIGRAMS;
+    static const NodeFlags FLAG_IS_NOT_A_WORD;
+    static const NodeFlags FLAG_IS_POSSIBLY_OFFENSIVE;
+};
+} // namespace latinime
+#endif /* LATINIME_PATRICIA_TRIE_NODE_READING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h b/native/jni/src/dictionary/structure/pt_common/pt_node_array_reader.h
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h
rename to native/jni/src/dictionary/structure/pt_common/pt_node_array_reader.h
diff --git a/native/jni/src/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/dictionary/structure/pt_common/pt_node_params.h
new file mode 100644
index 0000000..905deb1
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/pt_node_params.h
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PT_NODE_PARAMS_H
+#define LATINIME_PT_NODE_PARAMS_H
+
+#include <cstring>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "utils/char_utils.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+// This class has information of a PtNode. This class is immutable.
+class PtNodeParams {
+ public:
+    // Invalid PtNode.
+    PtNodeParams() : mHeadPos(NOT_A_DICT_POS), mFlags(0), mHasMovedFlag(false),
+            mParentPos(NOT_A_DICT_POS), mCodePointCount(0), mCodePoints(),
+            mTerminalIdFieldPos(NOT_A_DICT_POS), mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
+            mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY),
+            mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
+            mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS),
+            mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_DICT_POS) {}
+
+    PtNodeParams(const PtNodeParams& ptNodeParams)
+            : mHeadPos(ptNodeParams.mHeadPos), mFlags(ptNodeParams.mFlags),
+              mHasMovedFlag(ptNodeParams.mHasMovedFlag), mParentPos(ptNodeParams.mParentPos),
+              mCodePointCount(ptNodeParams.mCodePointCount), mCodePoints(),
+              mTerminalIdFieldPos(ptNodeParams.mTerminalIdFieldPos),
+              mTerminalId(ptNodeParams.mTerminalId),
+              mProbabilityFieldPos(ptNodeParams.mProbabilityFieldPos),
+              mProbability(ptNodeParams.mProbability),
+              mChildrenPosFieldPos(ptNodeParams.mChildrenPosFieldPos),
+              mChildrenPos(ptNodeParams.mChildrenPos),
+              mBigramLinkedNodePos(ptNodeParams.mBigramLinkedNodePos),
+              mShortcutPos(ptNodeParams.mShortcutPos), mBigramPos(ptNodeParams.mBigramPos),
+              mSiblingPos(ptNodeParams.mSiblingPos) {
+        memcpy(mCodePoints, ptNodeParams.getCodePoints(), sizeof(int) * mCodePointCount);
+    }
+
+    // PtNode read from version 2 dictionary.
+    PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags,
+            const int codePointCount, const int *const codePoints, const int probability,
+            const int childrenPos, const int shortcutPos, const int bigramPos,
+            const int siblingPos)
+            : mHeadPos(headPos), mFlags(flags), mHasMovedFlag(false), mParentPos(NOT_A_DICT_POS),
+              mCodePointCount(codePointCount), mCodePoints(), mTerminalIdFieldPos(NOT_A_DICT_POS),
+              mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
+              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
+              mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(childrenPos),
+              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(shortcutPos),
+              mBigramPos(bigramPos), mSiblingPos(siblingPos) {
+        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
+    }
+
+    // PtNode with a terminal id.
+    PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags,
+            const int parentPos, const int codePointCount, const int *const codePoints,
+            const int terminalIdFieldPos, const int terminalId, const int probability,
+            const int childrenPosFieldPos, const int childrenPos, const int siblingPos)
+            : mHeadPos(headPos), mFlags(flags), mHasMovedFlag(true), mParentPos(parentPos),
+              mCodePointCount(codePointCount), mCodePoints(),
+              mTerminalIdFieldPos(terminalIdFieldPos), mTerminalId(terminalId),
+              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
+              mChildrenPosFieldPos(childrenPosFieldPos), mChildrenPos(childrenPos),
+              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(terminalId),
+              mBigramPos(terminalId), mSiblingPos(siblingPos) {
+        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
+    }
+
+    // Construct new params by updating existing PtNode params.
+    PtNodeParams(const PtNodeParams *const ptNodeParams,
+            const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
+            const CodePointArrayView codePoints, const int probability)
+            : mHeadPos(ptNodeParams->getHeadPos()), mFlags(flags), mHasMovedFlag(true),
+              mParentPos(parentPos), mCodePointCount(codePoints.size()), mCodePoints(),
+              mTerminalIdFieldPos(ptNodeParams->getTerminalIdFieldPos()),
+              mTerminalId(ptNodeParams->getTerminalId()),
+              mProbabilityFieldPos(ptNodeParams->getProbabilityFieldPos()),
+              mProbability(probability),
+              mChildrenPosFieldPos(ptNodeParams->getChildrenPosFieldPos()),
+              mChildrenPos(ptNodeParams->getChildrenPos()),
+              mBigramLinkedNodePos(ptNodeParams->getBigramLinkedNodePos()),
+              mShortcutPos(ptNodeParams->getShortcutPos()),
+              mBigramPos(ptNodeParams->getBigramsPos()),
+              mSiblingPos(ptNodeParams->getSiblingNodePos()) {
+        memcpy(mCodePoints, codePoints.data(), sizeof(int) * mCodePointCount);
+    }
+
+    PtNodeParams(const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
+            const CodePointArrayView codePoints, const int probability)
+            : mHeadPos(NOT_A_DICT_POS), mFlags(flags), mHasMovedFlag(true), mParentPos(parentPos),
+              mCodePointCount(codePoints.size()), mCodePoints(),
+              mTerminalIdFieldPos(NOT_A_DICT_POS),
+              mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
+              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
+              mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
+              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS),
+              mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_DICT_POS) {
+        memcpy(mCodePoints, codePoints.data(), sizeof(int) * mCodePointCount);
+    }
+
+    AK_FORCE_INLINE bool isValid() const {
+        return mCodePointCount > 0;
+    }
+
+    // Head position of the PtNode
+    AK_FORCE_INLINE int getHeadPos() const {
+        return mHeadPos;
+    }
+
+    // Flags
+    AK_FORCE_INLINE bool isDeleted() const {
+        return mHasMovedFlag && DynamicPtReadingUtils::isDeleted(mFlags);
+    }
+
+    AK_FORCE_INLINE bool willBecomeNonTerminal() const {
+        return mHasMovedFlag && DynamicPtReadingUtils::willBecomeNonTerminal(mFlags);
+    }
+
+    AK_FORCE_INLINE bool hasChildren() const {
+        return mChildrenPos != NOT_A_DICT_POS;
+    }
+
+    AK_FORCE_INLINE bool isTerminal() const {
+        return PatriciaTrieReadingUtils::isTerminal(mFlags);
+    }
+
+    AK_FORCE_INLINE bool isPossiblyOffensive() const {
+        return PatriciaTrieReadingUtils::isPossiblyOffensive(mFlags);
+    }
+
+    AK_FORCE_INLINE bool isNotAWord() const {
+        return PatriciaTrieReadingUtils::isNotAWord(mFlags);
+    }
+
+    AK_FORCE_INLINE bool hasBigrams() const {
+        return PatriciaTrieReadingUtils::hasBigrams(mFlags);
+    }
+
+    AK_FORCE_INLINE bool hasShortcutTargets() const {
+        return PatriciaTrieReadingUtils::hasShortcutTargets(mFlags);
+    }
+
+    AK_FORCE_INLINE bool representsNonWordInfo() const {
+        return getCodePointCount() > 0 && !CharUtils::isInUnicodeSpace(getCodePoints()[0])
+                && isNotAWord();
+    }
+
+    AK_FORCE_INLINE int representsBeginningOfSentence() const {
+        return getCodePointCount() > 0 && getCodePoints()[0] == CODE_POINT_BEGINNING_OF_SENTENCE
+                && isNotAWord();
+    }
+
+    // Parent node position
+    AK_FORCE_INLINE int getParentPos() const {
+        return mParentPos;
+    }
+
+    AK_FORCE_INLINE const CodePointArrayView getCodePointArrayView() const {
+        return CodePointArrayView(mCodePoints, mCodePointCount);
+    }
+
+    // TODO: Remove
+    // Number of code points
+    AK_FORCE_INLINE uint8_t getCodePointCount() const {
+        return mCodePointCount;
+    }
+
+    // TODO: Remove
+    AK_FORCE_INLINE const int *getCodePoints() const {
+        return mCodePoints;
+    }
+
+    // Probability
+    AK_FORCE_INLINE int getTerminalIdFieldPos() const {
+        return mTerminalIdFieldPos;
+    }
+
+    AK_FORCE_INLINE int getTerminalId() const {
+        return mTerminalId;
+    }
+
+    // Probability
+    AK_FORCE_INLINE int getProbabilityFieldPos() const {
+        return mProbabilityFieldPos;
+    }
+
+    AK_FORCE_INLINE int getProbability() const {
+        return mProbability;
+    }
+
+    // Children PtNode array position
+    AK_FORCE_INLINE int getChildrenPosFieldPos() const {
+        return mChildrenPosFieldPos;
+    }
+
+    AK_FORCE_INLINE int getChildrenPos() const {
+        return mChildrenPos;
+    }
+
+    // Bigram linked node position.
+    AK_FORCE_INLINE int getBigramLinkedNodePos() const {
+        return mBigramLinkedNodePos;
+    }
+
+    // Shortcutlist position
+    AK_FORCE_INLINE int getShortcutPos() const {
+        return mShortcutPos;
+    }
+
+    // Bigrams position
+    AK_FORCE_INLINE int getBigramsPos() const {
+        return mBigramPos;
+    }
+
+    // Sibling node position
+    AK_FORCE_INLINE int getSiblingNodePos() const {
+        return mSiblingPos;
+    }
+
+ private:
+    // This class have a public copy constructor to be used as a return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(PtNodeParams);
+
+    const int mHeadPos;
+    const PatriciaTrieReadingUtils::NodeFlags mFlags;
+    const bool mHasMovedFlag;
+    const int mParentPos;
+    const uint8_t mCodePointCount;
+    int mCodePoints[MAX_WORD_LENGTH];
+    const int mTerminalIdFieldPos;
+    const int mTerminalId;
+    const int mProbabilityFieldPos;
+    const int mProbability;
+    const int mChildrenPosFieldPos;
+    const int mChildrenPos;
+    const int mBigramLinkedNodePos;
+    const int mShortcutPos;
+    const int mBigramPos;
+    const int mSiblingPos;
+};
+} // namespace latinime
+#endif /* LATINIME_PT_NODE_PARAMS_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/pt_node_reader.h b/native/jni/src/dictionary/structure/pt_common/pt_node_reader.h
new file mode 100644
index 0000000..15da19e
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/pt_node_reader.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PT_NODE_READER_H
+#define LATINIME_PT_NODE_READER_H
+
+#include "defines.h"
+
+#include "dictionary/structure/pt_common/pt_node_params.h"
+
+namespace latinime {
+
+// Interface class used to read PtNode information.
+class PtNodeReader {
+ public:
+    virtual ~PtNodeReader() {}
+    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(
+            const int ptNodePos) const = 0;
+
+ protected:
+    PtNodeReader() {};
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(PtNodeReader);
+};
+} // namespace latinime
+#endif /* LATINIME_PT_NODE_READER_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/pt_node_writer.h b/native/jni/src/dictionary/structure/pt_common/pt_node_writer.h
new file mode 100644
index 0000000..e6cad25
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/pt_node_writer.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PT_NODE_WRITER_H
+#define LATINIME_PT_NODE_WRITER_H
+
+#include <unordered_map>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class NgramProperty;
+class UnigramProperty;
+
+// Interface class used to write PtNode information.
+class PtNodeWriter {
+ public:
+    typedef std::unordered_map<int, int> PtNodeArrayPositionRelocationMap;
+    typedef std::unordered_map<int, int> PtNodePositionRelocationMap;
+    struct DictPositionRelocationMap {
+     public:
+        DictPositionRelocationMap()
+                : mPtNodeArrayPositionRelocationMap(), mPtNodePositionRelocationMap() {}
+
+        PtNodeArrayPositionRelocationMap mPtNodeArrayPositionRelocationMap;
+        PtNodePositionRelocationMap mPtNodePositionRelocationMap;
+
+     private:
+        DISALLOW_COPY_AND_ASSIGN(DictPositionRelocationMap);
+    };
+
+    virtual ~PtNodeWriter() {}
+
+    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams) = 0;
+
+    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int movedPos, const int bigramLinkedNodePos) = 0;
+
+    virtual bool markPtNodeAsWillBecomeNonTerminal(
+            const PtNodeParams *const toBeUpdatedPtNodeParams) = 0;
+
+    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const UnigramProperty *const unigramProperty) = 0;
+
+    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+            const PtNodeParams *const toBeUpdatedPtNodeParams,
+            bool *const outNeedsToKeepPtNode) = 0;
+
+    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
+                const int newChildrenPosition) = 0;
+
+    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            int *const ptNodeWritingPos) = 0;
+
+    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos) = 0;
+
+    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
+            const NgramProperty *const ngramProperty, bool *const outAddedNewEntry) = 0;
+
+    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId) = 0;
+
+    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
+            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) = 0;
+
+    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const DictPositionRelocationMap *const dictPositionRelocationMap,
+            int *const outBigramEntryCount) = 0;
+
+    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
+            const int *const targetCodePoints, const int targetCodePointCount,
+            const int shortcutProbability) = 0;
+
+ protected:
+    PtNodeWriter() {};
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(PtNodeWriter);
+};
+} // namespace latinime
+#endif /* LATINIME_PT_NODE_WRITER_H */
diff --git a/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp b/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
new file mode 100644
index 0000000..14428ed
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
+
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+// Flag for presence of more attributes
+const ShortcutListReadingUtils::ShortcutFlags
+        ShortcutListReadingUtils::FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
+// Mask for attribute probability, stored on 4 bits inside the flags byte.
+const ShortcutListReadingUtils::ShortcutFlags
+        ShortcutListReadingUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
+const int ShortcutListReadingUtils::SHORTCUT_LIST_SIZE_FIELD_SIZE = 2;
+// The numeric value of the shortcut probability that means 'whitelist'.
+const int ShortcutListReadingUtils::WHITELIST_SHORTCUT_PROBABILITY = 15;
+
+/* static */ ShortcutListReadingUtils::ShortcutFlags
+        ShortcutListReadingUtils::getFlagsAndForwardPointer(const ReadOnlyByteArrayView buffer,
+                int *const pos) {
+    return ByteArrayUtils::readUint8AndAdvancePosition(buffer.data(), pos);
+}
+
+/* static */ int ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(
+        const ReadOnlyByteArrayView buffer, int *const pos) {
+    // readUint16andAdvancePosition() returns an offset *including* the uint16 field itself.
+    return ByteArrayUtils::readUint16AndAdvancePosition(buffer.data(), pos)
+            - SHORTCUT_LIST_SIZE_FIELD_SIZE;
+}
+
+/* static */ int ShortcutListReadingUtils::readShortcutTarget(const ReadOnlyByteArrayView buffer,
+        const int maxLength, int *const outWord, int *const pos) {
+    // TODO: Use codePointTable for shortcuts.
+    return ByteArrayUtils::readStringAndAdvancePosition(buffer.data(), maxLength,
+            nullptr /* codePointTable */, outWord, pos);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h b/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
new file mode 100644
index 0000000..71cb8cc
--- /dev/null
+++ b/native/jni/src/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SHORTCUT_LIST_READING_UTILS_H
+#define LATINIME_SHORTCUT_LIST_READING_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class ShortcutListReadingUtils {
+ public:
+    typedef uint8_t ShortcutFlags;
+
+    static ShortcutFlags getFlagsAndForwardPointer(const ReadOnlyByteArrayView buffer,
+            int *const pos);
+
+    static AK_FORCE_INLINE int getProbabilityFromFlags(const ShortcutFlags flags) {
+        return flags & MASK_ATTRIBUTE_PROBABILITY;
+    }
+
+    static AK_FORCE_INLINE bool hasNext(const ShortcutFlags flags) {
+        return (flags & FLAG_ATTRIBUTE_HAS_NEXT) != 0;
+    }
+
+    // This method returns the size of the shortcut list region excluding the shortcut list size
+    // field at the beginning.
+    static int getShortcutListSizeAndForwardPointer(const ReadOnlyByteArrayView buffer,
+            int *const pos);
+
+    static AK_FORCE_INLINE int getShortcutListSizeFieldSize() {
+        return SHORTCUT_LIST_SIZE_FIELD_SIZE;
+    }
+
+    static AK_FORCE_INLINE void skipShortcuts(const ReadOnlyByteArrayView buffer, int *const pos) {
+        const int shortcutListSize = getShortcutListSizeAndForwardPointer(buffer, pos);
+        *pos += shortcutListSize;
+    }
+
+    static AK_FORCE_INLINE bool isWhitelist(const ShortcutFlags flags) {
+        return getProbabilityFromFlags(flags) == WHITELIST_SHORTCUT_PROBABILITY;
+    }
+
+    static int readShortcutTarget(const ReadOnlyByteArrayView buffer, const int maxLength,
+            int *const outWord, int *const pos);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutListReadingUtils);
+
+    static const ShortcutFlags FLAG_ATTRIBUTE_HAS_NEXT;
+    static const ShortcutFlags MASK_ATTRIBUTE_PROBABILITY;
+    static const int SHORTCUT_LIST_SIZE_FIELD_SIZE;
+    static const int WHITELIST_SHORTCUT_PROBABILITY;
+};
+} // namespace latinime
+#endif // LATINIME_SHORTCUT_LIST_READING_UTILS_H
diff --git a/native/jni/src/dictionary/structure/v2/bigram/bigram_list_policy.h b/native/jni/src/dictionary/structure/v2/bigram/bigram_list_policy.h
new file mode 100644
index 0000000..25081fa
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/bigram/bigram_list_policy.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_BIGRAM_LIST_POLICY_H
+#define LATINIME_BIGRAM_LIST_POLICY_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_bigrams_structure_policy.h"
+#include "dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class BigramListPolicy : public DictionaryBigramsStructurePolicy {
+ public:
+    BigramListPolicy(const ReadOnlyByteArrayView buffer) : mBuffer(buffer) {}
+
+    ~BigramListPolicy() {}
+
+    void getNextBigram(int *const outBigramPos, int *const outProbability, bool *const outHasNext,
+            int *const pos) const {
+        BigramListReadWriteUtils::BigramFlags flags;
+        if (!BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(mBuffer, &flags,
+                outBigramPos, pos)) {
+            AKLOGE("Cannot read bigram entry. bufSize: %zd, pos: %d. ", mBuffer.size(), *pos);
+            *outProbability = NOT_A_PROBABILITY;
+            *outHasNext = false;
+            return;
+        }
+        *outProbability = BigramListReadWriteUtils::getProbabilityFromFlags(flags);
+        *outHasNext = BigramListReadWriteUtils::hasNext(flags);
+    }
+
+    bool skipAllBigrams(int *const pos) const {
+        return BigramListReadWriteUtils::skipExistingBigrams(mBuffer, pos);
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListPolicy);
+
+    const ReadOnlyByteArrayView mBuffer;
+};
+} // namespace latinime
+#endif // LATINIME_BIGRAM_LIST_POLICY_H
diff --git a/native/jni/src/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/dictionary/structure/v2/patricia_trie_policy.cpp
new file mode 100644
index 0000000..4e8b96b
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -0,0 +1,526 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v2/patricia_trie_policy.h"
+
+#include "defines.h"
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "dictionary/interface/ngram_listener.h"
+#include "dictionary/property/ngram_context.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/utils/binary_dictionary_bigrams_iterator.h"
+#include "dictionary/utils/multi_bigram_map.h"
+#include "dictionary/utils/probability_utils.h"
+#include "utils/char_utils.h"
+
+namespace latinime {
+
+void PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
+        DicNodeVector *const childDicNodes) const {
+    if (!dicNode->hasChildren()) {
+        return;
+    }
+    int nextPos = dicNode->getChildrenPtNodeArrayPos();
+    if (!isValidPos(nextPos)) {
+        AKLOGE("Children PtNode array position is invalid. pos: %d, dict size: %zd",
+                nextPos, mBuffer.size());
+        mIsCorrupted = true;
+        ASSERT(false);
+        return;
+    }
+    const int childCount = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+            mBuffer.data(), &nextPos);
+    for (int i = 0; i < childCount; i++) {
+        if (!isValidPos(nextPos)) {
+            AKLOGE("Child PtNode position is invalid. pos: %d, dict size: %zd, childCount: %d / %d",
+                    nextPos, mBuffer.size(), i, childCount);
+            mIsCorrupted = true;
+            ASSERT(false);
+            return;
+        }
+        nextPos = createAndGetLeavingChildNode(dicNode, nextPos, childDicNodes);
+    }
+}
+
+int PatriciaTriePolicy::getCodePointsAndReturnCodePointCount(const int wordId,
+        const int maxCodePointCount, int *const outCodePoints) const {
+    return getCodePointsAndProbabilityAndReturnCodePointCount(wordId, maxCodePointCount,
+            outCodePoints, nullptr /* outUnigramProbability */);
+}
+// This retrieves code points and the probability of the word by its id.
+// Due to the fact that words are ordered in the dictionary in a strict breadth-first order,
+// it is possible to check for this with advantageous complexity. For each PtNode array, we search
+// for PtNodes with children and compare the children position with the position we look for.
+// When we shoot the position we look for, it means the word we look for is in the children
+// of the previous PtNode. The only tricky part is the fact that if we arrive at the end of a
+// PtNode array with the last PtNode's children position still less than what we are searching for,
+// we must descend the last PtNode's children (for example, if the word we are searching for starts
+// with a z, it's the last PtNode of the root array, so all children addresses will be smaller
+// than the position we look for, and we have to descend the z PtNode).
+/* Parameters :
+ * wordId: Id of the word we are searching for.
+ * outCodePoints: an array to write the found word, with MAX_WORD_LENGTH size.
+ * outUnigramProbability: a pointer to an int to write the probability into.
+ * Return value : the code point count, of 0 if the word was not found.
+ */
+// TODO: Split this function to be more readable
+int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
+        const int wordId, const int maxCodePointCount, int *const outCodePoints,
+        int *const outUnigramProbability) const {
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    int pos = getRootPosition();
+    int wordPos = 0;
+    const int *const codePointTable = mHeaderPolicy.getCodePointTable();
+    if (outUnigramProbability) {
+        *outUnigramProbability = NOT_A_PROBABILITY;
+    }
+    // One iteration of the outer loop iterates through PtNode arrays. As stated above, we will
+    // only traverse PtNodes that are actually a part of the terminal we are searching, so each
+    // time we enter this loop we are one depth level further than last time.
+    // The only reason we count PtNodes is because we want to reduce the probability of infinite
+    // looping in case there is a bug. Since we know there is an upper bound to the depth we are
+    // supposed to traverse, it does not hurt to count iterations.
+    for (int loopCount = maxCodePointCount; loopCount > 0; --loopCount) {
+        int lastCandidatePtNodePos = 0;
+        // Let's loop through PtNodes in this PtNode array searching for either the terminal
+        // or one of its ascendants.
+        if (!isValidPos(pos)) {
+            AKLOGE("PtNode array position is invalid. pos: %d, dict size: %zd",
+                    pos, mBuffer.size());
+            mIsCorrupted = true;
+            ASSERT(false);
+            return 0;
+        }
+        for (int ptNodeCount = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+                mBuffer.data(), &pos); ptNodeCount > 0; --ptNodeCount) {
+            const int startPos = pos;
+            if (!isValidPos(pos)) {
+                AKLOGE("PtNode position is invalid. pos: %d, dict size: %zd", pos, mBuffer.size());
+                mIsCorrupted = true;
+                ASSERT(false);
+                return 0;
+            }
+            const PatriciaTrieReadingUtils::NodeFlags flags =
+                    PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mBuffer.data(), &pos);
+            const int character = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                    mBuffer.data(), codePointTable, &pos);
+            if (ptNodePos == startPos) {
+                // We found the position. Copy the rest of the code points in the buffer and return
+                // the length.
+                outCodePoints[wordPos] = character;
+                if (PatriciaTrieReadingUtils::hasMultipleChars(flags)) {
+                    int nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                            mBuffer.data(), codePointTable, &pos);
+                    // We count code points in order to avoid infinite loops if the file is broken
+                    // or if there is some other bug
+                    int charCount = maxCodePointCount;
+                    while (NOT_A_CODE_POINT != nextChar && --charCount > 0) {
+                        outCodePoints[++wordPos] = nextChar;
+                        nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                                mBuffer.data(), codePointTable, &pos);
+                    }
+                }
+                if (outUnigramProbability) {
+                    *outUnigramProbability =
+                            PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(
+                                    mBuffer.data(), &pos);
+                }
+                return ++wordPos;
+            }
+            // We need to skip past this PtNode, so skip any remaining code points after the
+            // first and possibly the probability.
+            if (PatriciaTrieReadingUtils::hasMultipleChars(flags)) {
+                PatriciaTrieReadingUtils::skipCharacters(mBuffer.data(), flags, MAX_WORD_LENGTH,
+                        codePointTable, &pos);
+            }
+            if (PatriciaTrieReadingUtils::isTerminal(flags)) {
+                PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mBuffer.data(), &pos);
+            }
+            // The fact that this PtNode has children is very important. Since we already know
+            // that this PtNode does not match, if it has no children we know it is irrelevant
+            // to what we are searching for.
+            const bool hasChildren = PatriciaTrieReadingUtils::hasChildrenInFlags(flags);
+            // We will write in `found' whether we have passed the children position we are
+            // searching for. For example if we search for "beer", the children of b are less
+            // than the address we are searching for and the children of c are greater. When we
+            // come here for c, we realize this is too big, and that we should descend b.
+            bool found;
+            if (hasChildren) {
+                int currentPos = pos;
+                // Here comes the tricky part. First, read the children position.
+                const int childrenPos = PatriciaTrieReadingUtils
+                        ::readChildrenPositionAndAdvancePosition(mBuffer.data(), flags,
+                                &currentPos);
+                if (childrenPos > ptNodePos) {
+                    // If the children pos is greater than the position, it means the previous
+                    // PtNode, which position is stored in lastCandidatePtNodePos, was the right
+                    // one.
+                    found = true;
+                } else if (1 >= ptNodeCount) {
+                    // However if we are on the LAST PtNode of this array, and we have NOT shot the
+                    // position we should descend THIS PtNode. So we trick the
+                    // lastCandidatePtNodePos so that we will descend this PtNode, not the previous
+                    // one.
+                    lastCandidatePtNodePos = startPos;
+                    found = true;
+                } else {
+                    // Else, we should continue looking.
+                    found = false;
+                }
+            } else {
+                // Even if we don't have children here, we could still be on the last PtNode of
+                // this array. If this is the case, we should descend the last PtNode that had
+                // children, and their position is already in lastCandidatePtNodePos.
+                found = (1 >= ptNodeCount);
+            }
+
+            if (found) {
+                // Okay, we found the PtNode we should descend. Its position is in
+                // the lastCandidatePtNodePos variable, so we just re-read it.
+                if (0 != lastCandidatePtNodePos) {
+                    const PatriciaTrieReadingUtils::NodeFlags lastFlags =
+                            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(
+                                    mBuffer.data(), &lastCandidatePtNodePos);
+                    const int lastChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                            mBuffer.data(), codePointTable, &lastCandidatePtNodePos);
+                    // We copy all the characters in this PtNode to the buffer
+                    outCodePoints[wordPos] = lastChar;
+                    if (PatriciaTrieReadingUtils::hasMultipleChars(lastFlags)) {
+                        int nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                                mBuffer.data(), codePointTable, &lastCandidatePtNodePos);
+                        int charCount = maxCodePointCount;
+                        while (-1 != nextChar && --charCount > 0) {
+                            outCodePoints[++wordPos] = nextChar;
+                            nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
+                                    mBuffer.data(), codePointTable, &lastCandidatePtNodePos);
+                        }
+                    }
+                    ++wordPos;
+                    // Now we only need to branch to the children address. Skip the probability if
+                    // it's there, read pos, and break to resume the search at pos.
+                    if (PatriciaTrieReadingUtils::isTerminal(lastFlags)) {
+                        PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mBuffer.data(),
+                                &lastCandidatePtNodePos);
+                    }
+                    pos = PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
+                            mBuffer.data(), lastFlags, &lastCandidatePtNodePos);
+                    break;
+                } else {
+                    // Here is a little tricky part: we come here if we found out that all children
+                    // addresses in this PtNode are bigger than the address we are searching for.
+                    // Should we conclude the word is not in the dictionary? No! It could still be
+                    // one of the remaining PtNodes in this array, so we have to keep looking in
+                    // this array until we find it (or we realize it's not there either, in which
+                    // case it's actually not in the dictionary). Pass the end of this PtNode,
+                    // ready to start the next one.
+                    if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) {
+                        PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
+                                mBuffer.data(), flags, &pos);
+                    }
+                    if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) {
+                        mShortcutListPolicy.skipAllShortcuts(&pos);
+                    }
+                    if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
+                        if (!mBigramListPolicy.skipAllBigrams(&pos)) {
+                            AKLOGE("Cannot skip bigrams. BufSize: %zd, pos: %d.", mBuffer.size(),
+                                    pos);
+                            mIsCorrupted = true;
+                            ASSERT(false);
+                            return 0;
+                        }
+                    }
+                }
+            } else {
+                // If we did not find it, we should record the last children address for the next
+                // iteration.
+                if (hasChildren) lastCandidatePtNodePos = startPos;
+                // Now skip the end of this PtNode (children pos and the attributes if any) so that
+                // our pos is after the end of this PtNode, at the start of the next one.
+                if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) {
+                    PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
+                            mBuffer.data(), flags, &pos);
+                }
+                if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) {
+                    mShortcutListPolicy.skipAllShortcuts(&pos);
+                }
+                if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
+                    if (!mBigramListPolicy.skipAllBigrams(&pos)) {
+                        AKLOGE("Cannot skip bigrams. BufSize: %zd, pos: %d.", mBuffer.size(), pos);
+                        mIsCorrupted = true;
+                        ASSERT(false);
+                        return 0;
+                    }
+                }
+            }
+
+        }
+    }
+    // If we have looked through all the PtNodes and found no match, the ptNodePos is
+    // not the position of a terminal in this dictionary.
+    return 0;
+}
+
+// This function gets the position of the terminal PtNode of the exact matching word in the
+// dictionary. If no match is found, it returns NOT_A_WORD_ID.
+int PatriciaTriePolicy::getWordId(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
+    DynamicPtReadingHelper readingHelper(&mPtNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(getRootPosition());
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in getWordId().");
+    }
+    return getWordIdFromTerminalPtNodePos(ptNodePos);
+}
+
+const WordAttributes PatriciaTriePolicy::getWordAttributesInContext(
+        const WordIdArrayView prevWordIds, const int wordId,
+        MultiBigramMap *const multiBigramMap) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return WordAttributes();
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    const PtNodeParams ptNodeParams =
+            mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    if (multiBigramMap) {
+        const int probability =  multiBigramMap->getBigramProbability(this /* structurePolicy */,
+                prevWordIds, wordId, ptNodeParams.getProbability());
+        return getWordAttributes(probability, ptNodeParams);
+    }
+    if (!prevWordIds.empty()) {
+        const int bigramProbability = getProbabilityOfWord(prevWordIds, wordId);
+        if (bigramProbability != NOT_A_PROBABILITY) {
+            return getWordAttributes(bigramProbability, ptNodeParams);
+        }
+    }
+    return getWordAttributes(getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY),
+            ptNodeParams);
+}
+
+const WordAttributes PatriciaTriePolicy::getWordAttributes(const int probability,
+        const PtNodeParams &ptNodeParams) const {
+    return WordAttributes(probability, false /* isBlacklisted */, ptNodeParams.isNotAWord(),
+            ptNodeParams.isPossiblyOffensive());
+}
+
+int PatriciaTriePolicy::getProbability(const int unigramProbability,
+        const int bigramProbability) const {
+    // Due to space constraints, the probability for bigrams is approximate - the lower the unigram
+    // probability, the worse the precision. The theoritical maximum error in resulting probability
+    // is 8 - although in the practice it's never bigger than 3 or 4 in very bad cases. This means
+    // that sometimes, we'll see some bigrams interverted here, but it can't get too bad.
+    if (unigramProbability == NOT_A_PROBABILITY) {
+        return NOT_A_PROBABILITY;
+    } else if (bigramProbability == NOT_A_PROBABILITY) {
+        return ProbabilityUtils::backoff(unigramProbability);
+    } else {
+        return ProbabilityUtils::computeProbabilityForBigram(unigramProbability,
+                bigramProbability);
+    }
+}
+
+int PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
+        const int wordId) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return NOT_A_PROBABILITY;
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    const PtNodeParams ptNodeParams =
+            mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    if (ptNodeParams.isNotAWord()) {
+        // If this is not a word, it should behave as having no probability outside of the
+        // suggestion process (where it should be used for shortcuts).
+        return NOT_A_PROBABILITY;
+    }
+    if (!prevWordIds.empty()) {
+        const int bigramsPosition = getBigramsPositionOfPtNode(
+                getTerminalPtNodePosFromWordId(prevWordIds[0]));
+        BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramsPosition);
+        while (bigramsIt.hasNext()) {
+            bigramsIt.next();
+            if (bigramsIt.getBigramPos() == ptNodePos
+                    && bigramsIt.getProbability() != NOT_A_PROBABILITY) {
+                return getProbability(ptNodeParams.getProbability(), bigramsIt.getProbability());
+            }
+        }
+        return NOT_A_PROBABILITY;
+    }
+    return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
+}
+
+void PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
+        NgramListener *const listener) const {
+    if (prevWordIds.empty()) {
+        return;
+    }
+    const int bigramsPosition = getBigramsPositionOfPtNode(
+            getTerminalPtNodePosFromWordId(prevWordIds[0]));
+    BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramsPosition);
+    while (bigramsIt.hasNext()) {
+        bigramsIt.next();
+        listener->onVisitEntry(bigramsIt.getProbability(),
+                getWordIdFromTerminalPtNodePos(bigramsIt.getBigramPos()));
+    }
+}
+
+BinaryDictionaryShortcutIterator PatriciaTriePolicy::getShortcutIterator(const int wordId) const {
+    const int shortcutPos = getShortcutPositionOfPtNode(getTerminalPtNodePosFromWordId(wordId));
+    return BinaryDictionaryShortcutIterator(&mShortcutListPolicy, shortcutPos);
+}
+
+int PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return NOT_A_DICT_POS;
+    }
+    return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getShortcutPos();
+}
+
+int PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return NOT_A_DICT_POS;
+    }
+    return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getBigramsPos();
+}
+
+int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNode,
+        const int ptNodePos, DicNodeVector *childDicNodes) const {
+    PatriciaTrieReadingUtils::NodeFlags flags;
+    int mergedNodeCodePointCount = 0;
+    int mergedNodeCodePoints[MAX_WORD_LENGTH];
+    int probability = NOT_A_PROBABILITY;
+    int childrenPos = NOT_A_DICT_POS;
+    int shortcutPos = NOT_A_DICT_POS;
+    int bigramPos = NOT_A_DICT_POS;
+    int siblingPos = NOT_A_DICT_POS;
+    const int *const codePointTable = mHeaderPolicy.getCodePointTable();
+    PatriciaTrieReadingUtils::readPtNodeInfo(mBuffer.data(), ptNodePos, &mShortcutListPolicy,
+            &mBigramListPolicy, codePointTable, &flags, &mergedNodeCodePointCount,
+            mergedNodeCodePoints, &probability, &childrenPos, &shortcutPos, &bigramPos,
+            &siblingPos);
+    // Skip PtNodes don't start with Unicode code point because they represent non-word information.
+    if (CharUtils::isInUnicodeSpace(mergedNodeCodePoints[0])) {
+        const int wordId = PatriciaTrieReadingUtils::isTerminal(flags) ? ptNodePos : NOT_A_WORD_ID;
+        childDicNodes->pushLeavingChild(dicNode, childrenPos, wordId,
+                CodePointArrayView(mergedNodeCodePoints, mergedNodeCodePointCount));
+    }
+    return siblingPos;
+}
+
+const WordProperty PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int wordId = getWordId(wordCodePoints, false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        AKLOGE("getWordProperty was called for invalid word.");
+        return WordProperty();
+    }
+    const int ptNodePos = getTerminalPtNodePosFromWordId(wordId);
+    const PtNodeParams ptNodeParams =
+            mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    // Fetch bigram information.
+    std::vector<NgramProperty> ngrams;
+    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
+    int bigramWord1CodePoints[MAX_WORD_LENGTH];
+    BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramListPos);
+    while (bigramsIt.hasNext()) {
+        // Fetch the next bigram information and forward the iterator.
+        bigramsIt.next();
+        // Skip the entry if the entry has been deleted. This never happens for ver2 dicts.
+        if (bigramsIt.getBigramPos() != NOT_A_DICT_POS) {
+            int word1Probability = NOT_A_PROBABILITY;
+            const int word1CodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
+                    getWordIdFromTerminalPtNodePos(bigramsIt.getBigramPos()), MAX_WORD_LENGTH,
+                    bigramWord1CodePoints, &word1Probability);
+            const int probability = getProbability(word1Probability, bigramsIt.getProbability());
+            ngrams.emplace_back(
+                    NgramContext(wordCodePoints.data(), wordCodePoints.size(),
+                            ptNodeParams.representsBeginningOfSentence()),
+                    CodePointArrayView(bigramWord1CodePoints, word1CodePointCount).toVector(),
+                    probability, HistoricalInfo());
+        }
+    }
+    // Fetch shortcut information.
+    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
+    int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
+    if (shortcutPos != NOT_A_DICT_POS) {
+        int shortcutTargetCodePoints[MAX_WORD_LENGTH];
+        ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(mBuffer, &shortcutPos);
+        bool hasNext = true;
+        while (hasNext) {
+            const ShortcutListReadingUtils::ShortcutFlags shortcutFlags =
+                    ShortcutListReadingUtils::getFlagsAndForwardPointer(mBuffer, &shortcutPos);
+            hasNext = ShortcutListReadingUtils::hasNext(shortcutFlags);
+            const int shortcutTargetLength = ShortcutListReadingUtils::readShortcutTarget(
+                    mBuffer, MAX_WORD_LENGTH, shortcutTargetCodePoints, &shortcutPos);
+            const int shortcutProbability =
+                    ShortcutListReadingUtils::getProbabilityFromFlags(shortcutFlags);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTargetCodePoints, shortcutTargetLength).toVector(),
+                    shortcutProbability);
+        }
+    }
+    const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
+            ptNodeParams.isNotAWord(), ptNodeParams.isPossiblyOffensive(),
+            ptNodeParams.getProbability(), HistoricalInfo(), std::move(shortcuts));
+    return WordProperty(wordCodePoints.toVector(), unigramProperty, ngrams);
+}
+
+int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+        int *const outCodePointCount) {
+    *outCodePointCount = 0;
+    if (token == 0) {
+        // Start iterating the dictionary.
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
+                &mTerminalPtNodePositionsForIteratingWords);
+        DynamicPtReadingHelper readingHelper(&mPtNodeReader, &mPtNodeArrayReader);
+        readingHelper.initWithPtNodeArrayPos(getRootPosition());
+        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
+    }
+    const int terminalPtNodePositionsVectorSize =
+            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
+    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
+        AKLOGE("Given token %d is invalid.", token);
+        return 0;
+    }
+    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
+    *outCodePointCount = getCodePointsAndReturnCodePointCount(
+            getWordIdFromTerminalPtNodePos(terminalPtNodePos), MAX_WORD_LENGTH, outCodePoints);
+    const int nextToken = token + 1;
+    if (nextToken >= terminalPtNodePositionsVectorSize) {
+        // All words have been iterated.
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        return 0;
+    }
+    return nextToken;
+}
+
+int PatriciaTriePolicy::getWordIdFromTerminalPtNodePos(const int ptNodePos) const {
+    return ptNodePos == NOT_A_DICT_POS ? NOT_A_WORD_ID : ptNodePos;
+}
+
+int PatriciaTriePolicy::getTerminalPtNodePosFromWordId(const int wordId) const {
+    return wordId == NOT_A_WORD_ID ? NOT_A_DICT_POS : wordId;
+}
+
+bool PatriciaTriePolicy::isValidPos(const int pos) const {
+    return pos >= 0 && pos < static_cast<int>(mBuffer.size());
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/dictionary/structure/v2/patricia_trie_policy.h
new file mode 100644
index 0000000..8edfa7d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/patricia_trie_policy.h
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PATRICIA_TRIE_POLICY_H
+#define LATINIME_PATRICIA_TRIE_POLICY_H
+
+#include <cstdint>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/header/header_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/structure/v2/bigram/bigram_list_policy.h"
+#include "dictionary/structure/v2/shortcut/shortcut_list_policy.h"
+#include "dictionary/structure/v2/ver2_patricia_trie_node_reader.h"
+#include "dictionary/structure/v2/ver2_pt_node_array_reader.h"
+#include "dictionary/utils/format_utils.h"
+#include "dictionary/utils/mmapped_buffer.h"
+#include "utils/byte_array_view.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class DicNode;
+class DicNodeVector;
+
+// Word id = Position of a PtNode that represents the word.
+// Max supported n-gram is bigram.
+class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
+ public:
+    PatriciaTriePolicy(MmappedBuffer::MmappedBufferPtr mmappedBuffer)
+            : mMmappedBuffer(std::move(mmappedBuffer)),
+              mHeaderPolicy(mMmappedBuffer->getReadOnlyByteArrayView().data(),
+                      FormatUtils::detectFormatVersion(mMmappedBuffer->getReadOnlyByteArrayView())),
+              mBuffer(mMmappedBuffer->getReadOnlyByteArrayView().skip(mHeaderPolicy.getSize())),
+              mBigramListPolicy(mBuffer), mShortcutListPolicy(mBuffer),
+              mPtNodeReader(mBuffer, &mBigramListPolicy, &mShortcutListPolicy,
+                      mHeaderPolicy.getCodePointTable()),
+              mPtNodeArrayReader(mBuffer), mTerminalPtNodePositionsForIteratingWords(),
+              mIsCorrupted(false) {}
+
+    AK_FORCE_INLINE int getRootPosition() const {
+        return 0;
+    }
+
+    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+            DicNodeVector *const childDicNodes) const;
+
+    int getCodePointsAndReturnCodePointCount(const int wordId, const int maxCodePointCount,
+            int *const outCodePoints) const;
+
+    int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
+
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
+
+    int getProbability(const int unigramProbability, const int bigramProbability) const;
+
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
+
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
+
+    BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
+
+    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+        return &mHeaderPolicy;
+    }
+
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
+            const UnigramProperty *const unigramProperty) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool addNgramEntry(const NgramProperty *const ngramProperty) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool removeNgramEntry(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints, const bool isValidWord,
+            const HistoricalInfo historicalInfo) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: updateEntriesForWordWithNgramContext() is called for non-updatable "
+                "dictionary.");
+        return false;
+    }
+
+    bool flush(const char *const filePath) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: flush() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool flushWithGC(const char *const filePath) {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    bool needsToRunGC(const bool mindsBlockByGC) const {
+        // This method should not be called for non-updatable dictionary.
+        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
+        return false;
+    }
+
+    void getProperty(const char *const query, const int queryLength, char *const outResult,
+            const int maxResultLength) {
+        // getProperty is not supported for this class.
+        if (maxResultLength > 0) {
+            outResult[0] = '\0';
+        }
+    }
+
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
+
+    int getNextWordAndNextToken(const int token, int *const outCodePoints,
+            int *const outCodePointCount);
+
+    bool isCorrupted() const {
+        return mIsCorrupted;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
+
+    const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
+    const HeaderPolicy mHeaderPolicy;
+    const ReadOnlyByteArrayView mBuffer;
+    const BigramListPolicy mBigramListPolicy;
+    const ShortcutListPolicy mShortcutListPolicy;
+    const Ver2ParticiaTrieNodeReader mPtNodeReader;
+    const Ver2PtNodeArrayReader mPtNodeArrayReader;
+    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
+    mutable bool mIsCorrupted;
+
+    int getCodePointsAndProbabilityAndReturnCodePointCount(const int wordId,
+            const int maxCodePointCount, int *const outCodePoints,
+            int *const outUnigramProbability) const;
+    int getShortcutPositionOfPtNode(const int ptNodePos) const;
+    int getBigramsPositionOfPtNode(const int ptNodePos) const;
+    int createAndGetLeavingChildNode(const DicNode *const dicNode, const int ptNodePos,
+            DicNodeVector *const childDicNodes) const;
+    int getWordIdFromTerminalPtNodePos(const int ptNodePos) const;
+    int getTerminalPtNodePosFromWordId(const int wordId) const;
+    const WordAttributes getWordAttributes(const int probability,
+            const PtNodeParams &ptNodeParams) const;
+    bool isValidPos(const int pos) const;
+};
+} // namespace latinime
+#endif // LATINIME_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/dictionary/structure/v2/shortcut/shortcut_list_policy.h b/native/jni/src/dictionary/structure/v2/shortcut/shortcut_list_policy.h
new file mode 100644
index 0000000..995b1ed
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/shortcut/shortcut_list_policy.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SHORTCUT_LIST_POLICY_H
+#define LATINIME_SHORTCUT_LIST_POLICY_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_shortcuts_structure_policy.h"
+#include "dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
+ public:
+    explicit ShortcutListPolicy(const ReadOnlyByteArrayView buffer) : mBuffer(buffer) {}
+
+    ~ShortcutListPolicy() {}
+
+    int getStartPos(const int pos) const {
+        if (pos == NOT_A_DICT_POS) {
+            return NOT_A_DICT_POS;
+        }
+        int listPos = pos;
+        ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(mBuffer, &listPos);
+        return listPos;
+    }
+
+    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
+            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
+            int *const pos) const {
+        const ShortcutListReadingUtils::ShortcutFlags flags =
+                ShortcutListReadingUtils::getFlagsAndForwardPointer(mBuffer, pos);
+        if (outHasNext) {
+            *outHasNext = ShortcutListReadingUtils::hasNext(flags);
+        }
+        if (outIsWhitelist) {
+            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(flags);
+        }
+        if (outCodePoint) {
+            *outCodePointCount = ShortcutListReadingUtils::readShortcutTarget(
+                    mBuffer, maxCodePointCount, outCodePoint, pos);
+        }
+    }
+
+    void skipAllShortcuts(int *const pos) const {
+        const int shortcutListSize = ShortcutListReadingUtils
+                ::getShortcutListSizeAndForwardPointer(mBuffer, pos);
+        *pos += shortcutListSize;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutListPolicy);
+
+    const ReadOnlyByteArrayView mBuffer;
+};
+} // namespace latinime
+#endif // LATINIME_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp b/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
new file mode 100644
index 0000000..cbb8ead
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v2/ver2_patricia_trie_node_reader.h"
+
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+
+namespace latinime {
+
+const PtNodeParams Ver2ParticiaTrieNodeReader::fetchPtNodeParamsInBufferFromPtNodePos(
+        const int ptNodePos) const {
+    if (ptNodePos < 0 || ptNodePos >= static_cast<int>(mBuffer.size())) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %zd",
+                ptNodePos, mBuffer.size());
+        ASSERT(false);
+        return PtNodeParams();
+    }
+    PatriciaTrieReadingUtils::NodeFlags flags;
+    int mergedNodeCodePointCount = 0;
+    int mergedNodeCodePoints[MAX_WORD_LENGTH];
+    int probability = NOT_A_PROBABILITY;
+    int childrenPos = NOT_A_DICT_POS;
+    int shortcutPos = NOT_A_DICT_POS;
+    int bigramPos = NOT_A_DICT_POS;
+    int siblingPos = NOT_A_DICT_POS;
+    PatriciaTrieReadingUtils::readPtNodeInfo(mBuffer.data(), ptNodePos, mShortcutPolicy,
+            mBigramPolicy, mCodePointTable, &flags, &mergedNodeCodePointCount, mergedNodeCodePoints,
+            &probability, &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
+    if (mergedNodeCodePointCount <= 0) {
+        AKLOGE("Empty PtNode is not allowed. Code point count: %d", mergedNodeCodePointCount);
+        ASSERT(false);
+        return PtNodeParams();
+    }
+    return PtNodeParams(ptNodePos, flags, mergedNodeCodePointCount, mergedNodeCodePoints,
+            probability, childrenPos, shortcutPos, bigramPos, siblingPos);
+}
+
+}
diff --git a/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.h b/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
new file mode 100644
index 0000000..dc87c7c
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H
+#define LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_reader.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class DictionaryBigramsStructurePolicy;
+class DictionaryShortcutsStructurePolicy;
+
+class Ver2ParticiaTrieNodeReader : public PtNodeReader {
+ public:
+    Ver2ParticiaTrieNodeReader(const ReadOnlyByteArrayView buffer,
+            const DictionaryBigramsStructurePolicy *const bigramPolicy,
+            const DictionaryShortcutsStructurePolicy *const shortcutPolicy,
+            const int *const codePointTable)
+            : mBuffer(buffer), mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy),
+              mCodePointTable(codePointTable) {}
+
+    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver2ParticiaTrieNodeReader);
+
+    const ReadOnlyByteArrayView mBuffer;
+    const DictionaryBigramsStructurePolicy *const mBigramPolicy;
+    const DictionaryShortcutsStructurePolicy *const mShortcutPolicy;
+    const int *const mCodePointTable;
+};
+} // namespace latinime
+#endif /* LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.cpp b/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.cpp
new file mode 100644
index 0000000..8b9b02d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v2/ver2_pt_node_array_reader.h"
+
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+
+namespace latinime {
+
+bool Ver2PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
+    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= static_cast<int>(mBuffer.size())) {
+        // Reading invalid position because of a bug or a broken dictionary.
+        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %zd",
+                ptNodeArrayPos, mBuffer.size());
+        ASSERT(false);
+        return false;
+    }
+    int readingPos = ptNodeArrayPos;
+    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+            mBuffer.data(), &readingPos);
+    *outPtNodeCount = ptNodeCountInArray;
+    *outFirstPtNodePos = readingPos;
+    return true;
+}
+
+bool Ver2PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+        int *const outNextPtNodeArrayPos) const {
+    if (forwordLinkPos < 0 || forwordLinkPos >=  static_cast<int>(mBuffer.size())) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %zd",
+                forwordLinkPos, mBuffer.size());
+        ASSERT(false);
+        return false;
+    }
+    // Ver2 dicts don't have forward links.
+    *outNextPtNodeArrayPos = NOT_A_DICT_POS;
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.h b/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.h
new file mode 100644
index 0000000..32fa96d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v2/ver2_pt_node_array_reader.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_VER2_PT_NODE_ARRAY_READER_H
+#define LATINIME_VER2_PT_NODE_ARRAY_READER_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_array_reader.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class Ver2PtNodeArrayReader : public PtNodeArrayReader {
+ public:
+    Ver2PtNodeArrayReader(const ReadOnlyByteArrayView buffer) : mBuffer(buffer) {};
+
+    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
+    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+            int *const outNextPtNodeArrayPos) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver2PtNodeArrayReader);
+
+    const ReadOnlyByteArrayView mBuffer;
+};
+} // namespace latinime
+#endif /* LATINIME_VER2_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp b/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp
new file mode 100644
index 0000000..165947f
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v4/content/dynamic_language_model_probability_utils.h"
+
+namespace latinime {
+
+// Used to provide stable probabilities even if the user's input count is small.
+const int DynamicLanguageModelProbabilityUtils::ASSUMED_MIN_COUNTS[] = {8192, 2, 2, 1};
+
+// Encoded backoff weights.
+// Note that we give positive values for trigrams and quadgrams that means the weight is more than
+// 1.
+// TODO: Apply backoff for main dictionaries and quit giving a positive backoff weight.
+const int DynamicLanguageModelProbabilityUtils::ENCODED_BACKOFF_WEIGHTS[] = {-32, -4, 2, 8};
+
+// This value is used to remove too old entries from the dictionary.
+const int DynamicLanguageModelProbabilityUtils::DURATION_TO_DISCARD_ENTRY_IN_SECONDS =
+        300 * 24 * 60 * 60; // 300 days
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h b/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h
new file mode 100644
index 0000000..71824c9
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/dynamic_language_model_probability_utils.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H
+#define LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H
+
+#include <algorithm>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "utils/ngram_utils.h"
+#include "utils/time_keeper.h"
+
+namespace latinime {
+
+class DynamicLanguageModelProbabilityUtils {
+ public:
+    static float computeRawProbabilityFromCounts(const int count, const int contextCount,
+            const NgramType ngramType) {
+        const int minCount = ASSUMED_MIN_COUNTS[static_cast<int>(ngramType)];
+        return static_cast<float>(count) / static_cast<float>(std::max(contextCount, minCount));
+    }
+
+    static float backoff(const int ngramProbability, const NgramType ngramType) {
+        const int probability =
+                ngramProbability + ENCODED_BACKOFF_WEIGHTS[static_cast<int>(ngramType)];
+        return std::min(std::max(probability, NOT_A_PROBABILITY), MAX_PROBABILITY);
+    }
+
+    static int getDecayedProbability(const int probability, const HistoricalInfo historicalInfo) {
+        const int elapsedTime = TimeKeeper::peekCurrentTime() - historicalInfo.getTimestamp();
+        if (elapsedTime < 0) {
+            AKLOGE("The elapsed time is negatime value. Timestamp overflow?");
+            return NOT_A_PROBABILITY;
+        }
+        // TODO: Improve this logic.
+        // We don't modify probability depending on the elapsed time.
+        return probability;
+    }
+
+    static int shouldRemoveEntryDuringGC(const HistoricalInfo historicalInfo) {
+        // TODO: Improve this logic.
+        const int elapsedTime = TimeKeeper::peekCurrentTime() - historicalInfo.getTimestamp();
+        return elapsedTime > DURATION_TO_DISCARD_ENTRY_IN_SECONDS;
+    }
+
+    static int getPriorityToPreventFromEviction(const HistoricalInfo historicalInfo) {
+        // TODO: Improve this logic.
+        // More recently input entries get higher priority.
+        return historicalInfo.getTimestamp();
+    }
+
+private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicLanguageModelProbabilityUtils);
+
+    static_assert(MAX_PREV_WORD_COUNT_FOR_N_GRAM <= 3, "Max supported Ngram is Quadgram.");
+
+    static const int ASSUMED_MIN_COUNTS[];
+    static const int ENCODED_BACKOFF_WEIGHTS[];
+    static const int DURATION_TO_DISCARD_ENTRY_IN_SECONDS;
+};
+
+} // namespace latinime
+#endif /* LATINIME_DYNAMIC_LANGUAGE_MODEL_PROBABILITY_UTILS_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.cpp
new file mode 100644
index 0000000..c10e490
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.cpp
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v4/content/language_model_dict_content.h"
+
+#include <algorithm>
+#include <cstring>
+
+#include "dictionary/structure/v4/content/dynamic_language_model_probability_utils.h"
+#include "dictionary/utils/probability_utils.h"
+#include "utils/ngram_utils.h"
+
+namespace latinime {
+
+const int LanguageModelDictContent::TRIE_MAP_BUFFER_INDEX = 0;
+const int LanguageModelDictContent::GLOBAL_COUNTERS_BUFFER_INDEX = 1;
+
+bool LanguageModelDictContent::save(FILE *const file) const {
+    return mTrieMap.save(file) && mGlobalCounters.save(file);
+}
+
+bool LanguageModelDictContent::runGC(
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const LanguageModelDictContent *const originalContent) {
+    return runGCInner(terminalIdMap, originalContent->mTrieMap.getEntriesInRootLevel(),
+            0 /* nextLevelBitmapEntryIndex */);
+}
+
+const WordAttributes LanguageModelDictContent::getWordAttributes(const WordIdArrayView prevWordIds,
+        const int wordId, const bool mustMatchAllPrevWords,
+        const HeaderPolicy *const headerPolicy) const {
+    int bitmapEntryIndices[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1];
+    bitmapEntryIndices[0] = mTrieMap.getRootBitmapEntryIndex();
+    int maxPrevWordCount = 0;
+    for (size_t i = 0; i < prevWordIds.size(); ++i) {
+        const int nextBitmapEntryIndex =
+                mTrieMap.get(prevWordIds[i], bitmapEntryIndices[i]).mNextLevelBitmapEntryIndex;
+        if (nextBitmapEntryIndex == TrieMap::INVALID_INDEX) {
+            break;
+        }
+        maxPrevWordCount = i + 1;
+        bitmapEntryIndices[i + 1] = nextBitmapEntryIndex;
+    }
+
+    const ProbabilityEntry unigramProbabilityEntry = getProbabilityEntry(wordId);
+    if (mHasHistoricalInfo && unigramProbabilityEntry.getHistoricalInfo()->getCount() == 0) {
+        // The word should be treated as a invalid word.
+        return WordAttributes();
+    }
+    for (int i = maxPrevWordCount; i >= 0; --i) {
+        if (mustMatchAllPrevWords && prevWordIds.size() > static_cast<size_t>(i)) {
+            break;
+        }
+        const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndices[i]);
+        if (!result.mIsValid) {
+            continue;
+        }
+        const ProbabilityEntry probabilityEntry =
+                ProbabilityEntry::decode(result.mValue, mHasHistoricalInfo);
+        int probability = NOT_A_PROBABILITY;
+        if (mHasHistoricalInfo) {
+            const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+            int contextCount = 0;
+            if (i == 0) {
+                // unigram
+                contextCount = mGlobalCounters.getTotalCount();
+            } else {
+                const ProbabilityEntry prevWordProbabilityEntry = getNgramProbabilityEntry(
+                        prevWordIds.skip(1 /* n */).limit(i - 1), prevWordIds[0]);
+                if (!prevWordProbabilityEntry.isValid()) {
+                    continue;
+                }
+                if (prevWordProbabilityEntry.representsBeginningOfSentence()
+                        && historicalInfo->getCount() == 1) {
+                    // BoS ngram requires multiple contextCount.
+                    continue;
+                }
+                contextCount = prevWordProbabilityEntry.getHistoricalInfo()->getCount();
+            }
+            const NgramType ngramType = NgramUtils::getNgramTypeFromWordCount(i + 1);
+            const float rawProbability =
+                    DynamicLanguageModelProbabilityUtils::computeRawProbabilityFromCounts(
+                            historicalInfo->getCount(), contextCount, ngramType);
+            const int encodedRawProbability =
+                    ProbabilityUtils::encodeRawProbability(rawProbability);
+            const int decayedProbability =
+                    DynamicLanguageModelProbabilityUtils::getDecayedProbability(
+                            encodedRawProbability, *historicalInfo);
+            probability = DynamicLanguageModelProbabilityUtils::backoff(
+                    decayedProbability, ngramType);
+        } else {
+            probability = probabilityEntry.getProbability();
+        }
+        // TODO: Some flags in unigramProbabilityEntry should be overwritten by flags in
+        // probabilityEntry.
+        return WordAttributes(probability, unigramProbabilityEntry.isBlacklisted(),
+                unigramProbabilityEntry.isNotAWord(),
+                unigramProbabilityEntry.isPossiblyOffensive());
+    }
+    // Cannot find the word.
+    return WordAttributes();
+}
+
+ProbabilityEntry LanguageModelDictContent::getNgramProbabilityEntry(
+        const WordIdArrayView prevWordIds, const int wordId) const {
+    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+    if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
+        return ProbabilityEntry();
+    }
+    const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndex);
+    if (!result.mIsValid) {
+        // Not found.
+        return ProbabilityEntry();
+    }
+    return ProbabilityEntry::decode(result.mValue, mHasHistoricalInfo);
+}
+
+bool LanguageModelDictContent::setNgramProbabilityEntry(const WordIdArrayView prevWordIds,
+        const int wordId, const ProbabilityEntry *const probabilityEntry) {
+    if (wordId == Ver4DictConstants::NOT_A_TERMINAL_ID) {
+        return false;
+    }
+    const int bitmapEntryIndex = createAndGetBitmapEntryIndex(prevWordIds);
+    if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
+        return false;
+    }
+    return mTrieMap.put(wordId, probabilityEntry->encode(mHasHistoricalInfo), bitmapEntryIndex);
+}
+
+bool LanguageModelDictContent::removeNgramProbabilityEntry(const WordIdArrayView prevWordIds,
+        const int wordId) {
+    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+    if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
+        // Cannot find bitmap entry for the probability entry. The entry doesn't exist.
+        return false;
+    }
+    return mTrieMap.remove(wordId, bitmapEntryIndex);
+}
+
+LanguageModelDictContent::EntryRange LanguageModelDictContent::getProbabilityEntries(
+        const WordIdArrayView prevWordIds) const {
+    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
+    return EntryRange(mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex), mHasHistoricalInfo);
+}
+
+std::vector<LanguageModelDictContent::DumppedFullEntryInfo>
+        LanguageModelDictContent::exportAllNgramEntriesRelatedToWord(
+                const HeaderPolicy *const headerPolicy, const int wordId) const {
+    const TrieMap::Result result = mTrieMap.getRoot(wordId);
+    if (!result.mIsValid || result.mNextLevelBitmapEntryIndex == TrieMap::INVALID_INDEX) {
+        // The word doesn't have any related ngram entries.
+        return std::vector<DumppedFullEntryInfo>();
+    }
+    std::vector<int> prevWordIds = { wordId };
+    std::vector<DumppedFullEntryInfo> entries;
+    exportAllNgramEntriesRelatedToWordInner(headerPolicy, result.mNextLevelBitmapEntryIndex,
+            &prevWordIds, &entries);
+    return entries;
+}
+
+void LanguageModelDictContent::exportAllNgramEntriesRelatedToWordInner(
+        const HeaderPolicy *const headerPolicy, const int bitmapEntryIndex,
+        std::vector<int> *const prevWordIds,
+        std::vector<DumppedFullEntryInfo> *const outBummpedFullEntryInfo) const {
+    for (const auto &entry : mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex)) {
+        const int wordId = entry.key();
+        const ProbabilityEntry probabilityEntry =
+                ProbabilityEntry::decode(entry.value(), mHasHistoricalInfo);
+        if (probabilityEntry.isValid()) {
+            const WordAttributes wordAttributes = getWordAttributes(
+                    WordIdArrayView(*prevWordIds), wordId, true /* mustMatchAllPrevWords */,
+                    headerPolicy);
+            outBummpedFullEntryInfo->emplace_back(*prevWordIds, wordId,
+                    wordAttributes, probabilityEntry);
+        }
+        if (entry.hasNextLevelMap()) {
+            prevWordIds->push_back(wordId);
+            exportAllNgramEntriesRelatedToWordInner(headerPolicy,
+                    entry.getNextLevelBitmapEntryIndex(), prevWordIds, outBummpedFullEntryInfo);
+            prevWordIds->pop_back();
+        }
+    }
+}
+
+bool LanguageModelDictContent::truncateEntries(const EntryCounts &currentEntryCounts,
+        const EntryCounts &maxEntryCounts, const HeaderPolicy *const headerPolicy,
+        MutableEntryCounters *const outEntryCounters) {
+    for (int prevWordCount = 0; prevWordCount <= MAX_PREV_WORD_COUNT_FOR_N_GRAM; ++prevWordCount) {
+        const int totalWordCount = prevWordCount + 1;
+        const NgramType ngramType = NgramUtils::getNgramTypeFromWordCount(totalWordCount);
+        if (currentEntryCounts.getNgramCount(ngramType)
+                <= maxEntryCounts.getNgramCount(ngramType)) {
+            outEntryCounters->setNgramCount(ngramType,
+                    currentEntryCounts.getNgramCount(ngramType));
+            continue;
+        }
+        int entryCount = 0;
+        if (!turncateEntriesInSpecifiedLevel(headerPolicy,
+                maxEntryCounts.getNgramCount(ngramType), prevWordCount, &entryCount)) {
+            return false;
+        }
+        outEntryCounters->setNgramCount(ngramType, entryCount);
+    }
+    return true;
+}
+
+bool LanguageModelDictContent::updateAllEntriesOnInputWord(const WordIdArrayView prevWordIds,
+        const int wordId, const bool isValid, const HistoricalInfo historicalInfo,
+        const HeaderPolicy *const headerPolicy, MutableEntryCounters *const entryCountersToUpdate) {
+    if (!mHasHistoricalInfo) {
+        AKLOGE("updateAllEntriesOnInputWord is called for dictionary without historical info.");
+        return false;
+    }
+    const ProbabilityEntry originalUnigramProbabilityEntry = getProbabilityEntry(wordId);
+    const ProbabilityEntry updatedUnigramProbabilityEntry = createUpdatedEntryFrom(
+            originalUnigramProbabilityEntry, isValid, historicalInfo, headerPolicy);
+    if (!setProbabilityEntry(wordId, &updatedUnigramProbabilityEntry)) {
+        return false;
+    }
+    mGlobalCounters.incrementTotalCount();
+    mGlobalCounters.updateMaxValueOfCounters(
+            updatedUnigramProbabilityEntry.getHistoricalInfo()->getCount());
+    for (size_t i = 0; i < prevWordIds.size(); ++i) {
+        if (prevWordIds[i] == NOT_A_WORD_ID) {
+            break;
+        }
+        // TODO: Optimize this code.
+        const WordIdArrayView limitedPrevWordIds = prevWordIds.limit(i + 1);
+        const ProbabilityEntry originalNgramProbabilityEntry = getNgramProbabilityEntry(
+                limitedPrevWordIds, wordId);
+        const ProbabilityEntry updatedNgramProbabilityEntry = createUpdatedEntryFrom(
+                originalNgramProbabilityEntry, isValid, historicalInfo, headerPolicy);
+        if (!setNgramProbabilityEntry(limitedPrevWordIds, wordId, &updatedNgramProbabilityEntry)) {
+            return false;
+        }
+        mGlobalCounters.updateMaxValueOfCounters(
+                updatedNgramProbabilityEntry.getHistoricalInfo()->getCount());
+        if (!originalNgramProbabilityEntry.isValid()) {
+            // (i + 2) words are used in total because the prevWords consists of (i + 1) words when
+            // looking at its i-th element.
+            entryCountersToUpdate->incrementNgramCount(
+                    NgramUtils::getNgramTypeFromWordCount(i + 2));
+        }
+    }
+    return true;
+}
+
+const ProbabilityEntry LanguageModelDictContent::createUpdatedEntryFrom(
+        const ProbabilityEntry &originalProbabilityEntry, const bool isValid,
+        const HistoricalInfo historicalInfo, const HeaderPolicy *const headerPolicy) const {
+    const HistoricalInfo updatedHistoricalInfo = HistoricalInfo(historicalInfo.getTimestamp(),
+            0 /* level */, originalProbabilityEntry.getHistoricalInfo()->getCount()
+                    + historicalInfo.getCount());
+    if (originalProbabilityEntry.isValid()) {
+        return ProbabilityEntry(originalProbabilityEntry.getFlags(), &updatedHistoricalInfo);
+    } else {
+        return ProbabilityEntry(0 /* flags */, &updatedHistoricalInfo);
+    }
+}
+
+bool LanguageModelDictContent::runGCInner(
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const TrieMap::TrieMapRange trieMapRange, const int nextLevelBitmapEntryIndex) {
+    for (auto &entry : trieMapRange) {
+        const auto it = terminalIdMap->find(entry.key());
+        if (it == terminalIdMap->end() || it->second == Ver4DictConstants::NOT_A_TERMINAL_ID) {
+            // The word has been removed.
+            continue;
+        }
+        if (!mTrieMap.put(it->second, entry.value(), nextLevelBitmapEntryIndex)) {
+            return false;
+        }
+        if (entry.hasNextLevelMap()) {
+            if (!runGCInner(terminalIdMap, entry.getEntriesInNextLevel(),
+                    mTrieMap.getNextLevelBitmapEntryIndex(it->second, nextLevelBitmapEntryIndex))) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+int LanguageModelDictContent::createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds) {
+    int lastBitmapEntryIndex = mTrieMap.getRootBitmapEntryIndex();
+    for (const int wordId : prevWordIds) {
+        const TrieMap::Result result = mTrieMap.get(wordId, lastBitmapEntryIndex);
+        if (result.mIsValid && result.mNextLevelBitmapEntryIndex != TrieMap::INVALID_INDEX) {
+            lastBitmapEntryIndex = result.mNextLevelBitmapEntryIndex;
+            continue;
+        }
+        if (!result.mIsValid) {
+            if (!mTrieMap.put(wordId, ProbabilityEntry().encode(mHasHistoricalInfo),
+                    lastBitmapEntryIndex)) {
+                AKLOGE("Failed to update trie map. wordId: %d, lastBitmapEntryIndex %d", wordId,
+                        lastBitmapEntryIndex);
+                return TrieMap::INVALID_INDEX;
+            }
+        }
+        lastBitmapEntryIndex = mTrieMap.getNextLevelBitmapEntryIndex(wordId,
+                lastBitmapEntryIndex);
+    }
+    return lastBitmapEntryIndex;
+}
+
+int LanguageModelDictContent::getBitmapEntryIndex(const WordIdArrayView prevWordIds) const {
+    int bitmapEntryIndex = mTrieMap.getRootBitmapEntryIndex();
+    for (const int wordId : prevWordIds) {
+        const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndex);
+        if (!result.mIsValid) {
+            return TrieMap::INVALID_INDEX;
+        }
+        bitmapEntryIndex = result.mNextLevelBitmapEntryIndex;
+    }
+    return bitmapEntryIndex;
+}
+
+bool LanguageModelDictContent::updateAllProbabilityEntriesForGCInner(const int bitmapEntryIndex,
+        const int prevWordCount, const HeaderPolicy *const headerPolicy,
+        const bool needsToHalveCounters, MutableEntryCounters *const outEntryCounters) {
+    for (const auto &entry : mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex)) {
+        if (prevWordCount > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
+            AKLOGE("Invalid prevWordCount. prevWordCount: %d, MAX_PREV_WORD_COUNT_FOR_N_GRAM: %d.",
+                    prevWordCount, MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+            return false;
+        }
+        const ProbabilityEntry probabilityEntry =
+                ProbabilityEntry::decode(entry.value(), mHasHistoricalInfo);
+        if (prevWordCount > 0 && probabilityEntry.isValid()
+                && !mTrieMap.getRoot(entry.key()).mIsValid) {
+            // The entry is related to a word that has been removed. Remove the entry.
+            if (!mTrieMap.remove(entry.key(), bitmapEntryIndex)) {
+                return false;
+            }
+            continue;
+        }
+        if (mHasHistoricalInfo && probabilityEntry.isValid()) {
+            const HistoricalInfo *originalHistoricalInfo = probabilityEntry.getHistoricalInfo();
+            if (DynamicLanguageModelProbabilityUtils::shouldRemoveEntryDuringGC(
+                    *originalHistoricalInfo)) {
+                // Remove the entry.
+                if (!mTrieMap.remove(entry.key(), bitmapEntryIndex)) {
+                    return false;
+                }
+                continue;
+            }
+            if (needsToHalveCounters) {
+                const int updatedCount = originalHistoricalInfo->getCount() / 2;
+                if (updatedCount == 0) {
+                    // Remove the entry.
+                    if (!mTrieMap.remove(entry.key(), bitmapEntryIndex)) {
+                        return false;
+                    }
+                    continue;
+                }
+                const HistoricalInfo historicalInfoToSave(originalHistoricalInfo->getTimestamp(),
+                        originalHistoricalInfo->getLevel(), updatedCount);
+                const ProbabilityEntry updatedEntry(probabilityEntry.getFlags(),
+                        &historicalInfoToSave);
+                if (!mTrieMap.put(entry.key(), updatedEntry.encode(mHasHistoricalInfo),
+                        bitmapEntryIndex)) {
+                    return false;
+                }
+            }
+        }
+        outEntryCounters->incrementNgramCount(
+                NgramUtils::getNgramTypeFromWordCount(prevWordCount + 1));
+        if (!entry.hasNextLevelMap()) {
+            continue;
+        }
+        if (!updateAllProbabilityEntriesForGCInner(entry.getNextLevelBitmapEntryIndex(),
+                prevWordCount + 1, headerPolicy, needsToHalveCounters, outEntryCounters)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool LanguageModelDictContent::turncateEntriesInSpecifiedLevel(
+        const HeaderPolicy *const headerPolicy, const int maxEntryCount, const int targetLevel,
+        int *const outEntryCount) {
+    std::vector<int> prevWordIds;
+    std::vector<EntryInfoToTurncate> entryInfoVector;
+    if (!getEntryInfo(headerPolicy, targetLevel, mTrieMap.getRootBitmapEntryIndex(),
+            &prevWordIds, &entryInfoVector)) {
+        return false;
+    }
+    if (static_cast<int>(entryInfoVector.size()) <= maxEntryCount) {
+        *outEntryCount = static_cast<int>(entryInfoVector.size());
+        return true;
+    }
+    *outEntryCount = maxEntryCount;
+    const int entryCountToRemove = static_cast<int>(entryInfoVector.size()) - maxEntryCount;
+    std::partial_sort(entryInfoVector.begin(), entryInfoVector.begin() + entryCountToRemove,
+            entryInfoVector.end(),
+            EntryInfoToTurncate::Comparator());
+    for (int i = 0; i < entryCountToRemove; ++i) {
+        const EntryInfoToTurncate &entryInfo = entryInfoVector[i];
+        if (!removeNgramProbabilityEntry(
+                WordIdArrayView(entryInfo.mPrevWordIds, entryInfo.mPrevWordCount),
+                entryInfo.mKey)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool LanguageModelDictContent::getEntryInfo(const HeaderPolicy *const headerPolicy,
+        const int targetLevel, const int bitmapEntryIndex,  std::vector<int> *const prevWordIds,
+        std::vector<EntryInfoToTurncate> *const outEntryInfo) const {
+    const int prevWordCount = prevWordIds->size();
+    for (const auto &entry : mTrieMap.getEntriesInSpecifiedLevel(bitmapEntryIndex)) {
+        if (prevWordCount < targetLevel) {
+            if (!entry.hasNextLevelMap()) {
+                continue;
+            }
+            prevWordIds->push_back(entry.key());
+            if (!getEntryInfo(headerPolicy, targetLevel, entry.getNextLevelBitmapEntryIndex(),
+                    prevWordIds, outEntryInfo)) {
+                return false;
+            }
+            prevWordIds->pop_back();
+            continue;
+        }
+        const ProbabilityEntry probabilityEntry =
+                ProbabilityEntry::decode(entry.value(), mHasHistoricalInfo);
+        const int priority = mHasHistoricalInfo
+                ? DynamicLanguageModelProbabilityUtils::getPriorityToPreventFromEviction(
+                        *probabilityEntry.getHistoricalInfo())
+                : probabilityEntry.getProbability();
+        outEntryInfo->emplace_back(priority, probabilityEntry.getHistoricalInfo()->getCount(),
+                entry.key(), targetLevel, prevWordIds->data());
+    }
+    return true;
+}
+
+bool LanguageModelDictContent::EntryInfoToTurncate::Comparator::operator()(
+        const EntryInfoToTurncate &left, const EntryInfoToTurncate &right) const {
+    if (left.mPriority != right.mPriority) {
+        return left.mPriority < right.mPriority;
+    }
+    if (left.mCount != right.mCount) {
+        return left.mCount < right.mCount;
+    }
+    if (left.mKey != right.mKey) {
+        return left.mKey < right.mKey;
+    }
+    if (left.mPrevWordCount != right.mPrevWordCount) {
+        return left.mPrevWordCount > right.mPrevWordCount;
+    }
+    for (int i = 0; i < left.mPrevWordCount; ++i) {
+        if (left.mPrevWordIds[i] != right.mPrevWordIds[i]) {
+            return left.mPrevWordIds[i] < right.mPrevWordIds[i];
+        }
+    }
+    // left and rigth represent the same entry.
+    return false;
+}
+
+LanguageModelDictContent::EntryInfoToTurncate::EntryInfoToTurncate(const int priority,
+        const int count, const int key, const int prevWordCount, const int *const prevWordIds)
+        : mPriority(priority), mCount(count), mKey(key), mPrevWordCount(prevWordCount) {
+    memmove(mPrevWordIds, prevWordIds, mPrevWordCount * sizeof(mPrevWordIds[0]));
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.h b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.h
new file mode 100644
index 0000000..db8c6e1
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H
+#define LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H
+
+#include <cstdio>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/property/word_attributes.h"
+#include "dictionary/structure/v4/content/language_model_dict_content_global_counters.h"
+#include "dictionary/structure/v4/content/probability_entry.h"
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/utils/entry_counters.h"
+#include "dictionary/utils/trie_map.h"
+#include "utils/byte_array_view.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class HeaderPolicy;
+
+/**
+ * Class representing language model.
+ *
+ * This class provides methods to get and store unigram/n-gram probability information and flags.
+ */
+class LanguageModelDictContent {
+ public:
+    // Pair of word id and probability entry used for iteration.
+    class WordIdAndProbabilityEntry {
+     public:
+        WordIdAndProbabilityEntry(const int wordId, const ProbabilityEntry &probabilityEntry)
+                : mWordId(wordId), mProbabilityEntry(probabilityEntry) {}
+
+        int getWordId() const { return mWordId; }
+        const ProbabilityEntry getProbabilityEntry() const { return mProbabilityEntry; }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(WordIdAndProbabilityEntry);
+        DISALLOW_ASSIGNMENT_OPERATOR(WordIdAndProbabilityEntry);
+
+        const int mWordId;
+        const ProbabilityEntry mProbabilityEntry;
+    };
+
+    // Iterator.
+    class EntryIterator {
+     public:
+        EntryIterator(const TrieMap::TrieMapIterator &trieMapIterator,
+                const bool hasHistoricalInfo)
+                : mTrieMapIterator(trieMapIterator), mHasHistoricalInfo(hasHistoricalInfo) {}
+
+        const WordIdAndProbabilityEntry operator*() const {
+            const TrieMap::TrieMapIterator::IterationResult &result = *mTrieMapIterator;
+            return WordIdAndProbabilityEntry(
+                    result.key(), ProbabilityEntry::decode(result.value(), mHasHistoricalInfo));
+        }
+
+        bool operator!=(const EntryIterator &other) const {
+            return mTrieMapIterator != other.mTrieMapIterator;
+        }
+
+        const EntryIterator &operator++() {
+            ++mTrieMapIterator;
+            return *this;
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(EntryIterator);
+        DISALLOW_ASSIGNMENT_OPERATOR(EntryIterator);
+
+        TrieMap::TrieMapIterator mTrieMapIterator;
+        const bool mHasHistoricalInfo;
+    };
+
+    // Class represents range to use range base for loops.
+    class EntryRange {
+     public:
+        EntryRange(const TrieMap::TrieMapRange trieMapRange, const bool hasHistoricalInfo)
+                : mTrieMapRange(trieMapRange), mHasHistoricalInfo(hasHistoricalInfo) {}
+
+        EntryIterator begin() const {
+            return EntryIterator(mTrieMapRange.begin(), mHasHistoricalInfo);
+        }
+
+        EntryIterator end() const {
+            return EntryIterator(mTrieMapRange.end(), mHasHistoricalInfo);
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(EntryRange);
+        DISALLOW_ASSIGNMENT_OPERATOR(EntryRange);
+
+        const TrieMap::TrieMapRange mTrieMapRange;
+        const bool mHasHistoricalInfo;
+    };
+
+    class DumppedFullEntryInfo {
+     public:
+        DumppedFullEntryInfo(std::vector<int> &prevWordIds, const int targetWordId,
+                const WordAttributes &wordAttributes, const ProbabilityEntry &probabilityEntry)
+                : mPrevWordIds(prevWordIds), mTargetWordId(targetWordId),
+                  mWordAttributes(wordAttributes), mProbabilityEntry(probabilityEntry) {}
+
+        const WordIdArrayView getPrevWordIds() const { return WordIdArrayView(mPrevWordIds); }
+        int getTargetWordId() const { return mTargetWordId; }
+        const WordAttributes &getWordAttributes() const { return mWordAttributes; }
+        const ProbabilityEntry &getProbabilityEntry() const { return mProbabilityEntry; }
+
+     private:
+        DISALLOW_ASSIGNMENT_OPERATOR(DumppedFullEntryInfo);
+
+        const std::vector<int> mPrevWordIds;
+        const int mTargetWordId;
+        const WordAttributes mWordAttributes;
+        const ProbabilityEntry mProbabilityEntry;
+    };
+
+    LanguageModelDictContent(const ReadWriteByteArrayView *const buffers,
+            const bool hasHistoricalInfo)
+            : mTrieMap(buffers[TRIE_MAP_BUFFER_INDEX]),
+              mGlobalCounters(buffers[GLOBAL_COUNTERS_BUFFER_INDEX]),
+              mHasHistoricalInfo(hasHistoricalInfo) {}
+
+    explicit LanguageModelDictContent(const bool hasHistoricalInfo)
+            : mTrieMap(), mGlobalCounters(), mHasHistoricalInfo(hasHistoricalInfo) {}
+
+    bool isNearSizeLimit() const {
+        return mTrieMap.isNearSizeLimit() || mGlobalCounters.needsToHalveCounters();
+    }
+
+    bool save(FILE *const file) const;
+
+    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+            const LanguageModelDictContent *const originalContent);
+
+    const WordAttributes getWordAttributes(const WordIdArrayView prevWordIds, const int wordId,
+            const bool mustMatchAllPrevWords, const HeaderPolicy *const headerPolicy) const;
+
+    ProbabilityEntry getProbabilityEntry(const int wordId) const {
+        return getNgramProbabilityEntry(WordIdArrayView(), wordId);
+    }
+
+    bool setProbabilityEntry(const int wordId, const ProbabilityEntry *const probabilityEntry) {
+        mGlobalCounters.addToTotalCount(probabilityEntry->getHistoricalInfo()->getCount());
+        return setNgramProbabilityEntry(WordIdArrayView(), wordId, probabilityEntry);
+    }
+
+    bool removeProbabilityEntry(const int wordId) {
+        return removeNgramProbabilityEntry(WordIdArrayView(), wordId);
+    }
+
+    ProbabilityEntry getNgramProbabilityEntry(const WordIdArrayView prevWordIds,
+            const int wordId) const;
+
+    bool setNgramProbabilityEntry(const WordIdArrayView prevWordIds, const int wordId,
+            const ProbabilityEntry *const probabilityEntry);
+
+    bool removeNgramProbabilityEntry(const WordIdArrayView prevWordIds, const int wordId);
+
+    EntryRange getProbabilityEntries(const WordIdArrayView prevWordIds) const;
+
+    std::vector<DumppedFullEntryInfo> exportAllNgramEntriesRelatedToWord(
+            const HeaderPolicy *const headerPolicy, const int wordId) const;
+
+    bool updateAllProbabilityEntriesForGC(const HeaderPolicy *const headerPolicy,
+            MutableEntryCounters *const outEntryCounters) {
+        if (!updateAllProbabilityEntriesForGCInner(mTrieMap.getRootBitmapEntryIndex(),
+                0 /* prevWordCount */, headerPolicy, mGlobalCounters.needsToHalveCounters(),
+                outEntryCounters)) {
+            return false;
+        }
+        if (mGlobalCounters.needsToHalveCounters()) {
+            mGlobalCounters.halveCounters();
+        }
+        return true;
+    }
+
+    // entryCounts should be created by updateAllProbabilityEntries.
+    bool truncateEntries(const EntryCounts &currentEntryCounts, const EntryCounts &maxEntryCounts,
+            const HeaderPolicy *const headerPolicy, MutableEntryCounters *const outEntryCounters);
+
+    bool updateAllEntriesOnInputWord(const WordIdArrayView prevWordIds, const int wordId,
+            const bool isValid, const HistoricalInfo historicalInfo,
+            const HeaderPolicy *const headerPolicy,
+            MutableEntryCounters *const entryCountersToUpdate);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(LanguageModelDictContent);
+
+    class EntryInfoToTurncate {
+     public:
+        class Comparator {
+         public:
+            bool operator()(const EntryInfoToTurncate &left,
+                    const EntryInfoToTurncate &right) const;
+         private:
+            DISALLOW_ASSIGNMENT_OPERATOR(Comparator);
+        };
+
+        EntryInfoToTurncate(const int priority, const int count, const int key,
+                const int prevWordCount, const int *const prevWordIds);
+
+        int mPriority;
+        // TODO: Remove.
+        int mCount;
+        int mKey;
+        int mPrevWordCount;
+        int mPrevWordIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1];
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(EntryInfoToTurncate);
+    };
+
+    static const int TRIE_MAP_BUFFER_INDEX;
+    static const int GLOBAL_COUNTERS_BUFFER_INDEX;
+
+    TrieMap mTrieMap;
+    LanguageModelDictContentGlobalCounters mGlobalCounters;
+    const bool mHasHistoricalInfo;
+
+    bool runGCInner(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+            const TrieMap::TrieMapRange trieMapRange, const int nextLevelBitmapEntryIndex);
+    int createAndGetBitmapEntryIndex(const WordIdArrayView prevWordIds);
+    int getBitmapEntryIndex(const WordIdArrayView prevWordIds) const;
+    bool updateAllProbabilityEntriesForGCInner(const int bitmapEntryIndex, const int prevWordCount,
+            const HeaderPolicy *const headerPolicy, const bool needsToHalveCounters,
+            MutableEntryCounters *const outEntryCounters);
+    bool turncateEntriesInSpecifiedLevel(const HeaderPolicy *const headerPolicy,
+            const int maxEntryCount, const int targetLevel, int *const outEntryCount);
+    bool getEntryInfo(const HeaderPolicy *const headerPolicy, const int targetLevel,
+            const int bitmapEntryIndex, std::vector<int> *const prevWordIds,
+            std::vector<EntryInfoToTurncate> *const outEntryInfo) const;
+    const ProbabilityEntry createUpdatedEntryFrom(const ProbabilityEntry &originalProbabilityEntry,
+            const bool isValid, const HistoricalInfo historicalInfo,
+            const HeaderPolicy *const headerPolicy) const;
+    void exportAllNgramEntriesRelatedToWordInner(const HeaderPolicy *const headerPolicy,
+            const int bitmapEntryIndex, std::vector<int> *const prevWordIds,
+            std::vector<DumppedFullEntryInfo> *const outBummpedFullEntryInfo) const;
+};
+} // namespace latinime
+#endif /* LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp
new file mode 100644
index 0000000..89cf0e3
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v4/content/language_model_dict_content_global_counters.h"
+
+#include <climits>
+
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+const int LanguageModelDictContentGlobalCounters::COUNTER_VALUE_NEAR_LIMIT_THRESHOLD =
+        (1 << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT)) - 64;
+const int LanguageModelDictContentGlobalCounters::TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD = 1 << 30;
+const int LanguageModelDictContentGlobalCounters::COUNTER_SIZE_IN_BYTES = 4;
+const int LanguageModelDictContentGlobalCounters::TOTAL_COUNT_INDEX = 0;
+const int LanguageModelDictContentGlobalCounters::MAX_VALUE_OF_COUNTERS_INDEX = 1;
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.h b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.h
new file mode 100644
index 0000000..3f87c0e
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/language_model_dict_content_global_counters.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H
+#define LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H
+
+#include <cstdio>
+
+#include "defines.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class LanguageModelDictContentGlobalCounters {
+ public:
+    explicit LanguageModelDictContentGlobalCounters(const ReadWriteByteArrayView buffer)
+            : mBuffer(buffer, 0 /* maxAdditionalBufferSize */),
+              mTotalCount(readValue(mBuffer, TOTAL_COUNT_INDEX)),
+              mMaxValueOfCounters(readValue(mBuffer, MAX_VALUE_OF_COUNTERS_INDEX)) {}
+
+    LanguageModelDictContentGlobalCounters()
+            : mBuffer(0 /* maxAdditionalBufferSize */), mTotalCount(0), mMaxValueOfCounters(0) {}
+
+    bool needsToHalveCounters() const {
+        return mMaxValueOfCounters >= COUNTER_VALUE_NEAR_LIMIT_THRESHOLD
+                || mTotalCount >= TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD;
+    }
+
+    int getTotalCount() const {
+        return mTotalCount;
+    }
+
+    bool save(FILE *const file) const {
+        BufferWithExtendableBuffer bufferToWrite(
+                BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+        if (!bufferToWrite.writeUint(mTotalCount, COUNTER_SIZE_IN_BYTES,
+                TOTAL_COUNT_INDEX * COUNTER_SIZE_IN_BYTES)) {
+            return false;
+        }
+        if (!bufferToWrite.writeUint(mMaxValueOfCounters, COUNTER_SIZE_IN_BYTES,
+                MAX_VALUE_OF_COUNTERS_INDEX * COUNTER_SIZE_IN_BYTES)) {
+            return false;
+        }
+        return DictFileWritingUtils::writeBufferToFileTail(file, &bufferToWrite);
+    }
+
+    void incrementTotalCount() {
+        mTotalCount += 1;
+    }
+
+    void addToTotalCount(const int count) {
+        mTotalCount += count;
+    }
+
+    void updateMaxValueOfCounters(const int count) {
+        mMaxValueOfCounters = std::max(count, mMaxValueOfCounters);
+    }
+
+    void halveCounters() {
+        mMaxValueOfCounters /= 2;
+        mTotalCount /= 2;
+    }
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(LanguageModelDictContentGlobalCounters);
+
+    const static int COUNTER_VALUE_NEAR_LIMIT_THRESHOLD;
+    const static int TOTAL_COUNT_VALUE_NEAR_LIMIT_THRESHOLD;
+    const static int COUNTER_SIZE_IN_BYTES;
+    const static int TOTAL_COUNT_INDEX;
+    const static int MAX_VALUE_OF_COUNTERS_INDEX;
+
+    BufferWithExtendableBuffer mBuffer;
+    int mTotalCount;
+    int mMaxValueOfCounters;
+
+    static int readValue(const BufferWithExtendableBuffer &buffer, const int index) {
+        const int pos = COUNTER_SIZE_IN_BYTES * index;
+        if (pos + COUNTER_SIZE_IN_BYTES > buffer.getTailPosition()) {
+            return 0;
+        }
+        return buffer.readUint(COUNTER_SIZE_IN_BYTES, pos);
+    }
+};
+} // namespace latinime
+#endif /* LATINIME_LANGUAGE_MODEL_DICT_CONTENT_GLOBAL_COUNTERS_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/probability_entry.h b/native/jni/src/dictionary/structure/v4/content/probability_entry.h
new file mode 100644
index 0000000..473354b
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/probability_entry.h
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PROBABILITY_ENTRY_H
+#define LATINIME_PROBABILITY_ENTRY_H
+
+#include <climits>
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/property/ngram_property.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+class ProbabilityEntry {
+ public:
+    ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
+            : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
+              mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
+
+    // Dummy entry
+    ProbabilityEntry()
+            : mFlags(Ver4DictConstants::FLAG_NOT_A_VALID_ENTRY), mProbability(NOT_A_PROBABILITY),
+              mHistoricalInfo() {}
+
+    // Entry without historical information
+    ProbabilityEntry(const int flags, const int probability)
+            : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
+
+    // Entry with historical information.
+    ProbabilityEntry(const int flags, const HistoricalInfo *const historicalInfo)
+            : mFlags(flags), mProbability(NOT_A_PROBABILITY), mHistoricalInfo(*historicalInfo) {}
+
+    // Create from unigram property.
+    ProbabilityEntry(const UnigramProperty *const unigramProperty)
+            : mFlags(createFlags(unigramProperty->representsBeginningOfSentence(),
+                    unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
+                    unigramProperty->isPossiblyOffensive())),
+              mProbability(unigramProperty->getProbability()),
+              mHistoricalInfo(unigramProperty->getHistoricalInfo()) {}
+
+    // Create from ngram property.
+    // TODO: Set flags.
+    ProbabilityEntry(const NgramProperty *const ngramProperty)
+            : mFlags(0), mProbability(ngramProperty->getProbability()),
+              mHistoricalInfo(ngramProperty->getHistoricalInfo()) {}
+
+    bool isValid() const {
+        return (mFlags & Ver4DictConstants::FLAG_NOT_A_VALID_ENTRY) == 0;
+    }
+
+    bool hasHistoricalInfo() const {
+        return mHistoricalInfo.isValid();
+    }
+
+    uint8_t getFlags() const {
+        return mFlags;
+    }
+
+    int getProbability() const {
+        return mProbability;
+    }
+
+    const HistoricalInfo *getHistoricalInfo() const {
+        return &mHistoricalInfo;
+    }
+
+    bool representsBeginningOfSentence() const {
+        return (mFlags & Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE) != 0;
+    }
+
+    bool isNotAWord() const {
+        return (mFlags & Ver4DictConstants::FLAG_NOT_A_WORD) != 0;
+    }
+
+    bool isBlacklisted() const {
+        return (mFlags & Ver4DictConstants::FLAG_BLACKLISTED) != 0;
+    }
+
+    bool isPossiblyOffensive() const {
+        return (mFlags & Ver4DictConstants::FLAG_POSSIBLY_OFFENSIVE) != 0;
+    }
+
+    uint64_t encode(const bool hasHistoricalInfo) const {
+        uint64_t encodedEntry = static_cast<uint8_t>(mFlags);
+        if (hasHistoricalInfo) {
+            encodedEntry = (encodedEntry << (Ver4DictConstants::TIME_STAMP_FIELD_SIZE * CHAR_BIT))
+                    | static_cast<uint32_t>(mHistoricalInfo.getTimestamp());
+            encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_LEVEL_FIELD_SIZE * CHAR_BIT))
+                    | static_cast<uint8_t>(mHistoricalInfo.getLevel());
+            encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT))
+                    | static_cast<uint16_t>(mHistoricalInfo.getCount());
+        } else {
+            encodedEntry = (encodedEntry << (Ver4DictConstants::PROBABILITY_SIZE * CHAR_BIT))
+                    | static_cast<uint8_t>(mProbability);
+        }
+        return encodedEntry;
+    }
+
+    static ProbabilityEntry decode(const uint64_t encodedEntry, const bool hasHistoricalInfo) {
+        if (hasHistoricalInfo) {
+            const int flags = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
+                    Ver4DictConstants::TIME_STAMP_FIELD_SIZE
+                            + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+                            + Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
+            const int timestamp = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::TIME_STAMP_FIELD_SIZE,
+                    Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
+                            + Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
+            const int level = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::WORD_LEVEL_FIELD_SIZE,
+                    Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
+            const int count = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::WORD_COUNT_FIELD_SIZE, 0 /* pos */);
+            const HistoricalInfo historicalInfo(timestamp, level, count);
+            return ProbabilityEntry(flags, &historicalInfo);
+        } else {
+            const int flags = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE,
+                    Ver4DictConstants::PROBABILITY_SIZE);
+            const int probability = readFromEncodedEntry(encodedEntry,
+                    Ver4DictConstants::PROBABILITY_SIZE, 0 /* pos */);
+            return ProbabilityEntry(flags, probability);
+        }
+    }
+
+ private:
+    // Copy constructor is public to use this class as a type of return value.
+    DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry);
+
+    const uint8_t mFlags;
+    const int mProbability;
+    const HistoricalInfo mHistoricalInfo;
+
+    static int readFromEncodedEntry(const uint64_t encodedEntry, const int size, const int pos) {
+        return static_cast<int>(
+                (encodedEntry >> (pos * CHAR_BIT)) & ((1ull << (size * CHAR_BIT)) - 1));
+    }
+
+    static uint8_t createFlags(const bool representsBeginningOfSentence,
+            const bool isNotAWord, const bool isBlacklisted, const bool isPossiblyOffensive) {
+        uint8_t flags = 0;
+        if (representsBeginningOfSentence) {
+            flags |= Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE;
+        }
+        if (isNotAWord) {
+            flags |= Ver4DictConstants::FLAG_NOT_A_WORD;
+        }
+        if (isBlacklisted) {
+            flags |= Ver4DictConstants::FLAG_BLACKLISTED;
+        }
+        if (isPossiblyOffensive) {
+            flags |= Ver4DictConstants::FLAG_POSSIBLY_OFFENSIVE;
+        }
+        return flags;
+    }
+};
+} // namespace latinime
+#endif /* LATINIME_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.cpp b/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.cpp
new file mode 100644
index 0000000..e3b4194
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/content/shortcut_dict_content.h"
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+        int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+        bool *const outhasNext, int *const shortcutEntryPos) const {
+    const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
+    if (*shortcutEntryPos < 0 || *shortcutEntryPos >=  shortcutListBuffer->getTailPosition()) {
+        AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
+                *shortcutEntryPos, shortcutListBuffer->getTailPosition());
+        ASSERT(false);
+        if (outhasNext) {
+            *outhasNext = false;
+        }
+        if (outCodePointCount) {
+            *outCodePointCount = 0;
+        }
+        return;
+    }
+
+    const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+    if (outProbability) {
+        *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
+    }
+    if (outhasNext) {
+        *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+    }
+    if (outCodePoint && outCodePointCount) {
+        shortcutListBuffer->readCodePointsAndAdvancePosition(
+                maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
+    }
+}
+
+int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
+    const SparseTable *const addressLookupTable = getAddressLookupTable();
+    if (!addressLookupTable->contains(terminalId)) {
+        return NOT_A_DICT_POS;
+    }
+    return addressLookupTable->get(terminalId);
+}
+
+bool ShortcutDictContent::runGC(
+        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+        const ShortcutDictContent *const originalShortcutDictContent) {
+   for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
+           it != terminalIdMap->end(); ++it) {
+       const int originalShortcutListPos =
+               originalShortcutDictContent->getShortcutListHeadPos(it->first);
+       if (originalShortcutListPos == NOT_A_DICT_POS) {
+           continue;
+       }
+       const int shortcutListPos = getContentBuffer()->getTailPosition();
+       // Copy shortcut list from original content.
+       if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
+               shortcutListPos)) {
+           AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
+                   originalShortcutListPos, shortcutListPos);
+           return false;
+       }
+       // Set shortcut list position to the lookup table.
+       if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
+           AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
+                   it->second, shortcutListPos);
+           return false;
+       }
+   }
+   return true;
+}
+
+bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
+    const int shortcutListListPos = getContentBuffer()->getTailPosition();
+    return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
+}
+
+bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
+    return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
+}
+
+bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
+        const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
+    bool hasNext = true;
+    int readingPos = shortcutListPos;
+    int writingPos = toPos;
+    int codePoints[MAX_WORD_LENGTH];
+    while (hasNext) {
+        int probability = 0;
+        int codePointCount = 0;
+        sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
+                codePoints, &codePointCount, &probability, &hasNext, &readingPos);
+        if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
+                hasNext, &writingPos)) {
+            AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
+    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+    const int shortcutFlags = shortcutListBuffer->readUint(
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+    const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
+    const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
+    return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
+}
+
+bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+        const int codePointCount, const int probability, const bool hasNext,
+        int *const shortcutEntryPos) {
+    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
+    const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
+    if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
+            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
+        AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
+        return false;
+    }
+    if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
+            true /* writesTerminator */, shortcutEntryPos)) {
+        AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
+        return false;
+    }
+    return true;
+}
+
+// Find a shortcut entry that has specified target and return its position.
+int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
+        const int *const targetCodePointsToFind, const int codePointCount) const {
+    bool hasNext = true;
+    int readingPos = shortcutListPos;
+    int targetCodePoints[MAX_WORD_LENGTH];
+    while (hasNext) {
+        const int entryPos = readingPos;
+        int probability = 0;
+        int targetCodePointCount = 0;
+        getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
+                &probability, &hasNext, &readingPos);
+        if (targetCodePointCount != codePointCount) {
+            continue;
+        }
+        bool matched = true;
+        for (int i = 0; i < codePointCount; ++i) {
+            if (targetCodePointsToFind[i] != targetCodePoints[i]) {
+                matched = false;
+                break;
+            }
+        }
+        if (matched) {
+            return entryPos;
+        }
+    }
+    return NOT_A_DICT_POS;
+}
+
+int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
+        const bool hasNext) const {
+    return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
+            | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.h b/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.h
new file mode 100644
index 0000000..27de4e7
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/shortcut_dict_content.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SHORTCUT_DICT_CONTENT_H
+#define LATINIME_SHORTCUT_DICT_CONTENT_H
+
+#include <cstdio>
+
+#include "defines.h"
+#include "dictionary/structure/v4/content/sparse_table_dict_content.h"
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+class ReadWriteByteArrayView;
+
+class ShortcutDictContent : public SparseTableDictContent {
+ public:
+    ShortcutDictContent(const ReadWriteByteArrayView *const buffers)
+            : SparseTableDictContent(buffers, Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+    ShortcutDictContent()
+            : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
+                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
+
+    void getShortcutEntry(const int maxCodePointCount, int *const outCodePoint,
+            int *const outCodePointCount, int *const outProbability, bool *const outhasNext,
+            const int shortcutEntryPos) {
+        int readingPos = shortcutEntryPos;
+        return getShortcutEntryAndAdvancePosition(maxCodePointCount, outCodePoint,
+                outCodePointCount, outProbability, outhasNext, &readingPos);
+    }
+
+    void getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
+            int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
+            bool *const outhasNext, int *const shortcutEntryPos) const;
+
+   // Returns head position of shortcut list for a PtNode specified by terminalId.
+   int getShortcutListHeadPos(const int terminalId) const;
+
+   bool flushToFile(FILE *const file) const {
+       return flush(file);
+   }
+
+   bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
+           const ShortcutDictContent *const originalShortcutDictContent);
+
+   bool createNewShortcutList(const int terminalId);
+
+   bool copyShortcutList(const int shortcutListPos, const int toPos);
+
+   bool setProbability(const int probability, const int shortcutEntryPos);
+
+   bool writeShortcutEntry(const int *const codePoint, const int codePointCount,
+           const int probability, const bool hasNext, const int shortcutEntryPos) {
+       int writingPos = shortcutEntryPos;
+       return writeShortcutEntryAndAdvancePosition(codePoint, codePointCount, probability,
+               hasNext, &writingPos);
+   }
+
+   bool writeShortcutEntryAndAdvancePosition(const int *const codePoint,
+           const int codePointCount, const int probability, const bool hasNext,
+           int *const shortcutEntryPos);
+
+   int findShortcutEntryAndGetPos(const int shortcutListPos,
+           const int *const targetCodePointsToFind, const int codePointCount) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent);
+
+    bool copyShortcutListFromDictContent(const int shortcutListPos,
+            const ShortcutDictContent *const sourceShortcutDictContent, const int toPos);
+
+    int createAndGetShortcutFlags(const int probability, const bool hasNext) const;
+};
+} // namespace latinime
+#endif /* LATINIME_SHORTCUT_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/single_dict_content.h b/native/jni/src/dictionary/structure/v4/content/single_dict_content.h
new file mode 100644
index 0000000..6faa9a2
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/single_dict_content.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SINGLE_DICT_CONTENT_H
+#define LATINIME_SINGLE_DICT_CONTENT_H
+
+#include <cstdio>
+
+#include "defines.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class SingleDictContent {
+ public:
+    SingleDictContent(const ReadWriteByteArrayView buffer)
+            : mExpandableContentBuffer(buffer,
+                    BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
+
+    SingleDictContent()
+            : mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE) {}
+
+    virtual ~SingleDictContent() {}
+
+    bool isNearSizeLimit() const {
+        return mExpandableContentBuffer.isNearSizeLimit();
+    }
+
+ protected:
+    BufferWithExtendableBuffer *getWritableBuffer() {
+        return &mExpandableContentBuffer;
+    }
+
+    const BufferWithExtendableBuffer *getBuffer() const {
+        return &mExpandableContentBuffer;
+    }
+
+    bool flush(FILE *const file) const {
+        return DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableContentBuffer);
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(SingleDictContent);
+
+    BufferWithExtendableBuffer mExpandableContentBuffer;
+};
+} // namespace latinime
+#endif /* LATINIME_SINGLE_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.cpp b/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.cpp
new file mode 100644
index 0000000..685365f
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/content/sparse_table_dict_content.h"
+
+#include "dictionary/utils/dict_file_writing_utils.h"
+
+namespace latinime {
+
+const int SparseTableDictContent::LOOKUP_TABLE_BUFFER_INDEX = 0;
+const int SparseTableDictContent::ADDRESS_TABLE_BUFFER_INDEX = 1;
+const int SparseTableDictContent::CONTENT_BUFFER_INDEX = 2;
+
+bool SparseTableDictContent::flush(FILE *const file) const {
+    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableLookupTableBuffer)) {
+        return false;
+    }
+    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableAddressTableBuffer)) {
+        return false;
+    }
+    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableContentBuffer)) {
+        return false;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.h b/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.h
new file mode 100644
index 0000000..6245abc
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/sparse_table_dict_content.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SPARSE_TABLE_DICT_CONTENT_H
+#define LATINIME_SPARSE_TABLE_DICT_CONTENT_H
+
+#include <cstdio>
+
+#include "defines.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/sparse_table.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+// TODO: Support multiple contents.
+class SparseTableDictContent {
+ public:
+    AK_FORCE_INLINE SparseTableDictContent(const ReadWriteByteArrayView *const buffers,
+            const int sparseTableBlockSize, const int sparseTableDataSize)
+            : mExpandableLookupTableBuffer(buffers[LOOKUP_TABLE_BUFFER_INDEX],
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mExpandableAddressTableBuffer(buffers[ADDRESS_TABLE_BUFFER_INDEX],
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mExpandableContentBuffer(buffers[CONTENT_BUFFER_INDEX],
+                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+                      sparseTableBlockSize, sparseTableDataSize) {}
+
+    SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize)
+            : mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
+                      sparseTableBlockSize, sparseTableDataSize) {}
+
+    virtual ~SparseTableDictContent() {}
+
+    bool isNearSizeLimit() const {
+        return mExpandableLookupTableBuffer.isNearSizeLimit()
+                || mExpandableAddressTableBuffer.isNearSizeLimit()
+                || mExpandableContentBuffer.isNearSizeLimit();
+    }
+
+ protected:
+    SparseTable *getUpdatableAddressLookupTable() {
+        return &mAddressLookupTable;
+    }
+
+    const SparseTable *getAddressLookupTable() const {
+        return &mAddressLookupTable;
+    }
+
+    BufferWithExtendableBuffer *getWritableContentBuffer() {
+        return &mExpandableContentBuffer;
+    }
+
+    const BufferWithExtendableBuffer *getContentBuffer() const {
+        return &mExpandableContentBuffer;
+    }
+
+    bool flush(FILE *const file) const;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
+
+    static const int LOOKUP_TABLE_BUFFER_INDEX;
+    static const int ADDRESS_TABLE_BUFFER_INDEX;
+    static const int CONTENT_BUFFER_INDEX;
+
+    BufferWithExtendableBuffer mExpandableLookupTableBuffer;
+    BufferWithExtendableBuffer mExpandableAddressTableBuffer;
+    BufferWithExtendableBuffer mExpandableContentBuffer;
+    SparseTable mAddressLookupTable;
+};
+} // namespace latinime
+#endif /* LATINIME_SPARSE_TABLE_DICT_CONTENT_H */
diff --git a/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.cpp b/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
new file mode 100644
index 0000000..5503151
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
+    if (terminalId < 0 || terminalId >= mSize) {
+        return NOT_A_DICT_POS;
+    }
+    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;
+}
+
+bool TerminalPositionLookupTable::setTerminalPtNodePosition(
+        const int terminalId, const int terminalPtNodePos) {
+    if (terminalId < 0) {
+        return false;
+    }
+    while (terminalId >= mSize) {
+        // Write new entry.
+        if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
+                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
+            return false;
+        }
+        mSize++;
+    }
+    const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
+            terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
+    return getWritableBuffer()->writeUint(terminalPos,
+            Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
+}
+
+bool TerminalPositionLookupTable::flushToFile(FILE *const file) 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)) {
+                AKLOGE("Cannot set terminal position to lookupTableToWrite."
+                        " terminalId: %d, position: %d", i, terminalPtNodePosition);
+                return false;
+            }
+        }
+        return lookupTableToWrite.flush(file);
+    } else {
+        // We can simply use this lookup table because the buffer size has not been
+        // changed.
+        return flush(file);
+    }
+}
+
+bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
+    int removedEntryCount = 0;
+    int nextNewTerminalId = 0;
+    for (int i = 0; i < mSize; ++i) {
+        const int terminalPos = getBuffer()->readUint(
+                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
+        if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
+            // This entry is a garbage.
+            removedEntryCount++;
+        } else {
+            // Give a new terminal id to the entry.
+            if (!getWritableBuffer()->writeUint(terminalPos,
+                    Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
+                    getEntryPos(nextNewTerminalId))) {
+                return false;
+            }
+            // Memorize the mapping to the old terminal id to the new terminal id.
+            terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
+            nextNewTerminalId++;
+        }
+    }
+    mSize = nextNewTerminalId;
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.h b/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.h
new file mode 100644
index 0000000..f45ceb5
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/content/terminal_position_lookup_table.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
+#define LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
+
+#include <cstdio>
+#include <unordered_map>
+
+#include "defines.h"
+#include "dictionary/structure/v4/content/single_dict_content.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+class TerminalPositionLookupTable : public SingleDictContent {
+ public:
+    typedef std::unordered_map<int, int> TerminalIdMap;
+
+    TerminalPositionLookupTable(const ReadWriteByteArrayView buffer)
+            : SingleDictContent(buffer),
+              mSize(getBuffer()->getTailPosition()
+                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
+
+    TerminalPositionLookupTable() : mSize(0) {}
+
+    int getTerminalPtNodePosition(const int terminalId) const;
+
+    bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos);
+
+    int getNextTerminalId() const {
+        return mSize;
+    }
+
+    bool flushToFile(FILE *const file) const;
+
+    bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable);
+
+    int getEntryPos(const int terminalId) const {
+        return terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+    }
+
+    int mSize;
+};
+} // namespace latinime
+#endif // LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
new file mode 100644
index 0000000..25ab225
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_SHORTCUT_LIST_POLICY_H
+#define LATINIME_VER4_SHORTCUT_LIST_POLICY_H
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_shortcuts_structure_policy.h"
+#include "dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
+#include "dictionary/structure/v4/content/shortcut_dict_content.h"
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+
+namespace latinime {
+
+class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
+ public:
+    Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
+            const TerminalPositionLookupTable *const terminalPositionLookupTable)
+            : mShortcutDictContent(shortcutDictContent) {}
+
+    ~Ver4ShortcutListPolicy() {}
+
+    int getStartPos(const int pos) const {
+        // The first shortcut entry is located at the head position of the shortcut list.
+        return pos;
+    }
+
+    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
+            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
+            int *const pos) const {
+        int probability = 0;
+        mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount,
+                outCodePoint, outCodePointCount, &probability, outHasNext, pos);
+        if (outIsWhitelist) {
+            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(probability);
+        }
+    }
+
+    void skipAllShortcuts(int *const pos) const {
+        // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries.
+    }
+
+    bool addNewShortcut(const int terminalId, const int *const codePoints, const int codePointCount,
+            const int probability) {
+        const int shortcutListPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
+        if (shortcutListPos == NOT_A_DICT_POS) {
+            // Create shortcut list.
+            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+                return false;
+            }
+            const int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
+            return mShortcutDictContent->writeShortcutEntry(codePoints, codePointCount, probability,
+                    false /* hasNext */, writingPos);
+        }
+        const int entryPos = mShortcutDictContent->findShortcutEntryAndGetPos(shortcutListPos,
+                codePoints, codePointCount);
+        if (entryPos == NOT_A_DICT_POS) {
+            // Add new entry to the shortcut list.
+            // Create new shortcut list.
+            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
+                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
+                return false;
+            }
+            int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
+            if (!mShortcutDictContent->writeShortcutEntryAndAdvancePosition(codePoints,
+                    codePointCount, probability, true /* hasNext */, &writingPos)) {
+                AKLOGE("Cannot write shortcut entry. terminal id: %d, pos: %d", terminalId,
+                        writingPos);
+                return false;
+            }
+            return mShortcutDictContent->copyShortcutList(shortcutListPos, writingPos);
+        }
+        // Overwrite existing entry.
+        bool hasNext = false;
+        mShortcutDictContent->getShortcutEntry(MAX_WORD_LENGTH, 0 /* outCodePoint */,
+                0 /* outCodePointCount */ , 0 /* probability */, &hasNext, entryPos);
+        if (!mShortcutDictContent->writeShortcutEntry(codePoints,
+                codePointCount, probability, hasNext, entryPos)) {
+            AKLOGE("Cannot overwrite shortcut entry. terminal id: %d, pos: %d", terminalId,
+                    entryPos);
+            return false;
+        }
+        return true;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
+
+    ShortcutDictContent *const mShortcutDictContent;
+};
+} // namespace latinime
+#endif // LATINIME_VER4_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.cpp b/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.cpp
new file mode 100644
index 0000000..b0a8283
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.cpp
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+
+#include <cerrno>
+#include <cstring>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <vector>
+
+#include "dictionary/utils/byte_array_utils.h"
+#include "dictionary/utils/dict_file_writing_utils.h"
+#include "dictionary/utils/file_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+/* static */ Ver4DictBuffers::Ver4DictBuffersPtr Ver4DictBuffers::openVer4DictBuffers(
+        const char *const dictPath, MmappedBuffer::MmappedBufferPtr &&headerBuffer,
+        const FormatUtils::FORMAT_VERSION formatVersion) {
+    if (!headerBuffer) {
+        ASSERT(false);
+        AKLOGE("The header buffer must be valid to open ver4 dict buffers.");
+        return Ver4DictBuffersPtr(nullptr);
+    }
+    // TODO: take only dictDirPath, and open both header and trie files in the constructor below
+    const bool isUpdatable = headerBuffer->isUpdatable();
+    MmappedBuffer::MmappedBufferPtr bodyBuffer = MmappedBuffer::openBuffer(dictPath,
+            Ver4DictConstants::BODY_FILE_EXTENSION, isUpdatable);
+    if (!bodyBuffer) {
+        return Ver4DictBuffersPtr(nullptr);
+    }
+    std::vector<ReadWriteByteArrayView> buffers;
+    const ReadWriteByteArrayView buffer = bodyBuffer->getReadWriteByteArrayView();
+    int position = 0;
+    while (position < static_cast<int>(buffer.size())) {
+        const int bufferSize = ByteArrayUtils::readUint32AndAdvancePosition(
+                buffer.data(), &position);
+        buffers.push_back(buffer.subView(position, bufferSize));
+        position += bufferSize;
+        if (bufferSize < 0 || position < 0 || position > static_cast<int>(buffer.size())) {
+            AKLOGE("The dict body file is corrupted.");
+            return Ver4DictBuffersPtr(nullptr);
+        }
+    }
+    if (buffers.size() != Ver4DictConstants::NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE) {
+        AKLOGE("The dict body file is corrupted.");
+        return Ver4DictBuffersPtr(nullptr);
+    }
+    return Ver4DictBuffersPtr(new Ver4DictBuffers(std::move(headerBuffer), std::move(bodyBuffer),
+            formatVersion, buffers));
+}
+
+bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
+        const BufferWithExtendableBuffer *const headerBuffer) const {
+    // Create temporary directory.
+    const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath,
+            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
+    char tmpDirPath[tmpDirPathBufSize];
+    FileUtils::getFilePathWithSuffix(dictDirPath,
+            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize,
+            tmpDirPath);
+    if (FileUtils::existsDir(tmpDirPath)) {
+        if (!FileUtils::removeDirAndFiles(tmpDirPath)) {
+            AKLOGE("Existing directory %s cannot be removed.", tmpDirPath);
+            ASSERT(false);
+            return false;
+        }
+    }
+    umask(S_IWGRP | S_IWOTH);
+    if (mkdir(tmpDirPath, S_IRWXU) == -1) {
+        AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
+        return false;
+    }
+    // Get dictionary base path.
+    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
+    char dictName[dictNameBufSize];
+    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
+    const int dictPathBufSize = FileUtils::getFilePathBufSize(tmpDirPath, dictName);
+    char dictPath[dictPathBufSize];
+    FileUtils::getFilePath(tmpDirPath, dictName, dictPathBufSize, dictPath);
+
+    // Write header file.
+    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
+            Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
+        AKLOGE("Dictionary header file %s%s cannot be written.", tmpDirPath,
+                Ver4DictConstants::HEADER_FILE_EXTENSION);
+        return false;
+    }
+
+    // Write body file.
+    const int bodyFilePathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictPath,
+            Ver4DictConstants::BODY_FILE_EXTENSION);
+    char bodyFilePath[bodyFilePathBufSize];
+    FileUtils::getFilePathWithSuffix(dictPath, Ver4DictConstants::BODY_FILE_EXTENSION,
+            bodyFilePathBufSize, bodyFilePath);
+
+    const int fd = open(bodyFilePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+    if (fd == -1) {
+        AKLOGE("File %s cannot be opened. errno: %d", bodyFilePath, errno);
+        ASSERT(false);
+        return false;
+    }
+    FILE *const file = fdopen(fd, "wb");
+    if (!file) {
+        AKLOGE("fdopen failed for the file %s. errno: %d", bodyFilePath, errno);
+        ASSERT(false);
+        return false;
+    }
+
+    if (!flushDictBuffers(file)) {
+        fclose(file);
+        return false;
+    }
+    fclose(file);
+    // Remove existing dictionary.
+    if (!FileUtils::removeDirAndFiles(dictDirPath)) {
+        AKLOGE("Existing directory %s cannot be removed.", dictDirPath);
+        ASSERT(false);
+        return false;
+    }
+    // Rename temporary directory.
+    if (rename(tmpDirPath, dictDirPath) != 0) {
+        AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath);
+        ASSERT(false);
+        return false;
+    }
+    return true;
+}
+
+bool Ver4DictBuffers::flushDictBuffers(FILE *const file) const {
+    // Write trie.
+    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableTrieBuffer)) {
+        AKLOGE("Trie cannot be written.");
+        return false;
+    }
+    // Write terminal position lookup table.
+    if (!mTerminalPositionLookupTable.flushToFile(file)) {
+        AKLOGE("Terminal position lookup table cannot be written.");
+        return false;
+    }
+    // Write language model content.
+    if (!mLanguageModelDictContent.save(file)) {
+        AKLOGE("Language model dict content cannot be written.");
+        return false;
+    }
+    // Write shortcut dict content.
+    if (!mShortcutDictContent.flushToFile(file)) {
+        AKLOGE("Shortcut dict content cannot be written.");
+        return false;
+    }
+    return true;
+}
+
+Ver4DictBuffers::Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer,
+        MmappedBuffer::MmappedBufferPtr &&bodyBuffer,
+        const FormatUtils::FORMAT_VERSION formatVersion,
+        const std::vector<ReadWriteByteArrayView> &contentBuffers)
+        : mHeaderBuffer(std::move(headerBuffer)), mDictBuffer(std::move(bodyBuffer)),
+          mHeaderPolicy(mHeaderBuffer->getReadOnlyByteArrayView().data(), formatVersion),
+          mExpandableHeaderBuffer(mHeaderBuffer->getReadWriteByteArrayView(),
+                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+          mExpandableTrieBuffer(contentBuffers[Ver4DictConstants::TRIE_BUFFER_INDEX],
+                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
+          mTerminalPositionLookupTable(
+                  contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]),
+          mLanguageModelDictContent(&contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX],
+                  mHeaderPolicy.hasHistoricalInfoOfWords()),
+          mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]),
+          mIsUpdatable(mDictBuffer->isUpdatable()) {}
+
+Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize)
+        : mHeaderBuffer(nullptr), mDictBuffer(nullptr), mHeaderPolicy(headerPolicy),
+          mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
+          mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
+          mLanguageModelDictContent(headerPolicy->hasHistoricalInfoOfWords()),
+          mShortcutDictContent(),  mIsUpdatable(true) {}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.h b/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.h
new file mode 100644
index 0000000..c8270c9
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_dict_buffers.h
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_DICT_BUFFER_H
+#define LATINIME_VER4_DICT_BUFFER_H
+
+#include <cstdio>
+#include <memory>
+
+#include "defines.h"
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/v4/content/language_model_dict_content.h"
+#include "dictionary/structure/v4/content/shortcut_dict_content.h"
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/mmapped_buffer.h"
+
+namespace latinime {
+
+class Ver4DictBuffers {
+ public:
+    typedef std::unique_ptr<Ver4DictBuffers> Ver4DictBuffersPtr;
+
+    static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
+            MmappedBuffer::MmappedBufferPtr &&headerBuffer,
+            const FormatUtils::FORMAT_VERSION formatVersion);
+
+    static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
+            const HeaderPolicy *const headerPolicy, const int maxTrieSize) {
+        return Ver4DictBuffersPtr(new Ver4DictBuffers(headerPolicy, maxTrieSize));
+    }
+
+    AK_FORCE_INLINE bool isValid() const {
+        return mHeaderBuffer && mDictBuffer && mHeaderPolicy.isValid();
+    }
+
+    AK_FORCE_INLINE bool isNearSizeLimit() const {
+        return mExpandableTrieBuffer.isNearSizeLimit()
+                || mTerminalPositionLookupTable.isNearSizeLimit()
+                || mLanguageModelDictContent.isNearSizeLimit()
+                || mShortcutDictContent.isNearSizeLimit();
+    }
+
+    AK_FORCE_INLINE const HeaderPolicy *getHeaderPolicy() const {
+        return &mHeaderPolicy;
+    }
+
+    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() {
+        return &mExpandableHeaderBuffer;
+    }
+
+    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() {
+        return &mExpandableTrieBuffer;
+    }
+
+    AK_FORCE_INLINE const BufferWithExtendableBuffer *getTrieBuffer() const {
+        return &mExpandableTrieBuffer;
+    }
+
+    AK_FORCE_INLINE TerminalPositionLookupTable *getMutableTerminalPositionLookupTable() {
+        return &mTerminalPositionLookupTable;
+    }
+
+    AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const {
+        return &mTerminalPositionLookupTable;
+    }
+
+    AK_FORCE_INLINE LanguageModelDictContent *getMutableLanguageModelDictContent() {
+        return &mLanguageModelDictContent;
+    }
+
+    AK_FORCE_INLINE const LanguageModelDictContent *getLanguageModelDictContent() const {
+        return &mLanguageModelDictContent;
+    }
+
+    AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
+        return &mShortcutDictContent;
+    }
+
+    AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const {
+        return &mShortcutDictContent;
+    }
+
+    AK_FORCE_INLINE bool isUpdatable() const {
+        return mIsUpdatable;
+    }
+
+    bool flush(const char *const dictDirPath) const {
+        return flushHeaderAndDictBuffers(dictDirPath, &mExpandableHeaderBuffer);
+    }
+
+    bool flushHeaderAndDictBuffers(const char *const dictDirPath,
+            const BufferWithExtendableBuffer *const headerBuffer) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
+
+    Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer,
+            MmappedBuffer::MmappedBufferPtr &&bodyBuffer,
+            const FormatUtils::FORMAT_VERSION formatVersion,
+            const std::vector<ReadWriteByteArrayView> &contentBuffers);
+
+    Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize);
+
+    bool flushDictBuffers(FILE *const file) const;
+
+    const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
+    const MmappedBuffer::MmappedBufferPtr mDictBuffer;
+    const HeaderPolicy mHeaderPolicy;
+    BufferWithExtendableBuffer mExpandableHeaderBuffer;
+    BufferWithExtendableBuffer mExpandableTrieBuffer;
+    TerminalPositionLookupTable mTerminalPositionLookupTable;
+    LanguageModelDictContent mLanguageModelDictContent;
+    ShortcutDictContent mShortcutDictContent;
+    const int mIsUpdatable;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_DICT_BUFFER_H */
diff --git a/native/jni/src/dictionary/structure/v4/ver4_dict_constants.cpp b/native/jni/src/dictionary/structure/v4/ver4_dict_constants.cpp
new file mode 100644
index 0000000..fd69078
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_dict_constants.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+
+const char *const Ver4DictConstants::BODY_FILE_EXTENSION = ".body";
+const char *const Ver4DictConstants::HEADER_FILE_EXTENSION = ".header";
+
+// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets.
+const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 8 * 1024 * 1024;
+// Extended region size, which is not GCed region size in dict file + additional buffer size, is
+// limited to 1MB to prevent from inefficient traversing.
+const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
+
+// NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT for Trie and TerminalAddressLookupTable.
+// NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT for language model.
+// NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT for shortcut.
+const size_t Ver4DictConstants::NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE =
+        NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT * 2
+                + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT
+                + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
+const int Ver4DictConstants::TRIE_BUFFER_INDEX = 0;
+const int Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX =
+        TRIE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
+const int Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX =
+        TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
+const int Ver4DictConstants::SHORTCUT_BUFFERS_INDEX =
+        LANGUAGE_MODEL_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
+
+const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
+const int Ver4DictConstants::PROBABILITY_SIZE = 1;
+const int Ver4DictConstants::FLAGS_IN_LANGUAGE_MODEL_SIZE = 1;
+const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
+const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
+const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
+const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4;
+const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 0;
+const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 2;
+
+const uint8_t Ver4DictConstants::FLAG_REPRESENTS_BEGINNING_OF_SENTENCE = 0x1;
+const uint8_t Ver4DictConstants::FLAG_NOT_A_VALID_ENTRY = 0x2;
+const uint8_t Ver4DictConstants::FLAG_NOT_A_WORD = 0x4;
+const uint8_t Ver4DictConstants::FLAG_BLACKLISTED = 0x8;
+const uint8_t Ver4DictConstants::FLAG_POSSIBLY_OFFENSIVE = 0x10;
+
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
+const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
+
+const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
+const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
+const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
+
+const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT = 1;
+const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT = 3;
+const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT = 2;
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_dict_constants.h b/native/jni/src/dictionary/structure/v4/ver4_dict_constants.h
new file mode 100644
index 0000000..13d7a57
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_dict_constants.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_DICT_CONSTANTS_H
+#define LATINIME_VER4_DICT_CONSTANTS_H
+
+#include "defines.h"
+
+#include <cstddef>
+#include <cstdint>
+
+namespace latinime {
+
+// TODO: Create PtConstants under the pt_common and move some constant values there.
+// Note that there are corresponding definitions in FormatSpec.java.
+class Ver4DictConstants {
+ public:
+    static const char *const BODY_FILE_EXTENSION;
+    static const char *const HEADER_FILE_EXTENSION;
+    static const int MAX_DICTIONARY_SIZE;
+    static const int MAX_DICT_EXTENDED_REGION_SIZE;
+
+    static const size_t NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE;
+    static const int TRIE_BUFFER_INDEX;
+    static const int TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX;
+    static const int LANGUAGE_MODEL_BUFFER_INDEX;
+    static const int BIGRAM_BUFFERS_INDEX;
+    static const int SHORTCUT_BUFFERS_INDEX;
+
+    static const int NOT_A_TERMINAL_ID;
+    static const int PROBABILITY_SIZE;
+    static const int FLAGS_IN_LANGUAGE_MODEL_SIZE;
+    static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
+    static const int NOT_A_TERMINAL_ADDRESS;
+    static const int TERMINAL_ID_FIELD_SIZE;
+    static const int TIME_STAMP_FIELD_SIZE;
+    // TODO: Remove
+    static const int WORD_LEVEL_FIELD_SIZE;
+    static const int WORD_COUNT_FIELD_SIZE;
+    // Flags in probability entry.
+    static const uint8_t FLAG_REPRESENTS_BEGINNING_OF_SENTENCE;
+    static const uint8_t FLAG_NOT_A_VALID_ENTRY;
+    static const uint8_t FLAG_NOT_A_WORD;
+    static const uint8_t FLAG_BLACKLISTED;
+    static const uint8_t FLAG_POSSIBLY_OFFENSIVE;
+
+    static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
+    static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
+
+    static const int SHORTCUT_FLAGS_FIELD_SIZE;
+    static const int SHORTCUT_PROBABILITY_MASK;
+    static const int SHORTCUT_HAS_NEXT_MASK;
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
+
+    static const size_t NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
+    static const size_t NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
+    static const size_t NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_DICT_CONSTANTS_H */
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
new file mode 100644
index 0000000..b38b03d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/v4/content/language_model_dict_content.h"
+#include "dictionary/structure/v4/content/probability_entry.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_reading_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+
+const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
+        const int ptNodePos, const int siblingNodePos) const {
+    if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
+                ptNodePos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return PtNodeParams();
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int pos = ptNodePos;
+    const int headPos = ptNodePos;
+    if (usesAdditionalBuffer) {
+        pos -= mBuffer->getOriginalBufferSize();
+    }
+    const PatriciaTrieReadingUtils::NodeFlags flags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const int parentPosOffset =
+            DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
+                    dictBuf, &pos);
+    const int parentPos =
+            DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
+    int codePoints[MAX_WORD_LENGTH];
+    // Code point table is not used for ver4 dictionaries.
+    const int codePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
+            dictBuf, flags, MAX_WORD_LENGTH, nullptr /* codePointTable */, codePoints, &pos);
+    int terminalIdFieldPos = NOT_A_DICT_POS;
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (PatriciaTrieReadingUtils::isTerminal(flags)) {
+        terminalIdFieldPos = pos;
+        if (usesAdditionalBuffer) {
+            terminalIdFieldPos += mBuffer->getOriginalBufferSize();
+        }
+        terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
+    }
+    int childrenPosFieldPos = pos;
+    if (usesAdditionalBuffer) {
+        childrenPosFieldPos += mBuffer->getOriginalBufferSize();
+    }
+    int childrenPos = DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
+            dictBuf, &pos);
+    if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
+        childrenPos += mBuffer->getOriginalBufferSize();
+    }
+    if (usesAdditionalBuffer) {
+        pos += mBuffer->getOriginalBufferSize();
+    }
+    // Sibling position is the tail position of original PtNode.
+    int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos;
+    // Read destination node if the read node is a moved node.
+    if (DynamicPtReadingUtils::isMoved(flags)) {
+        // The destination position is stored at the same place as the parent position.
+        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
+    } else {
+        return PtNodeParams(headPos, flags, parentPos, codePointCount, codePoints,
+                terminalIdFieldPos, terminalId, NOT_A_PROBABILITY, childrenPosFieldPos, childrenPos,
+                newSiblingNodePos);
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
new file mode 100644
index 0000000..4e5ae3a
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H
+#define LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_reader.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+class HeaderPolicy;
+class LanguageModelDictContent;
+
+/*
+ * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
+ * node and reads node attributes.
+ */
+class Ver4PatriciaTrieNodeReader : public PtNodeReader {
+ public:
+    explicit Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer)
+            : mBuffer(buffer) {}
+
+    ~Ver4PatriciaTrieNodeReader() {}
+
+    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
+        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
+                NOT_A_DICT_POS /* siblingNodePos */);
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
+
+    const BufferWithExtendableBuffer *const mBuffer;
+
+    const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
+            const int siblingNodePos) const;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
new file mode 100644
index 0000000..d974b50
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
@@ -0,0 +1,354 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/structure/v4/content/probability_entry.h"
+#include "dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+namespace latinime {
+
+const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3;
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted(
+        const PtNodeParams *const toBeUpdatedPtNodeParams) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+                    true /* isDeleted */, false /* willBecomeNonTerminal */);
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    // Update flags.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos)) {
+        return false;
+    }
+    if (toBeUpdatedPtNodeParams->isTerminal()) {
+        // The PtNode is a terminal. Delete entry from the terminal position lookup table.
+        return mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+                toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */);
+    } else {
+        return true;
+    }
+}
+
+// TODO: Quit using bigramLinkedNodePos.
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const int movedPos, const int bigramLinkedNodePos) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
+                    false /* isDeleted */, false /* willBecomeNonTerminal */);
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    // Update flags.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos)) {
+        return false;
+    }
+    // Update moved position, which is stored in the parent offset field.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+            mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+        return false;
+    }
+    if (toBeUpdatedPtNodeParams->hasChildren()) {
+        // Update children's parent position.
+        mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
+        while (!mReadingHelper.isEnd()) {
+            const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams());
+            int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
+                    + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+            if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
+                    mTrieBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
+                    &parentOffsetFieldPos)) {
+                // Parent offset cannot be written because of a bug or a broken dictionary; thus,
+                // we give up to update dictionary.
+                return false;
+            }
+            mReadingHelper.readNextSiblingNode(childPtNodeParams);
+        }
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::markPtNodeAsWillBecomeNonTerminal(
+        const PtNodeParams *const toBeUpdatedPtNodeParams) {
+    int pos = toBeUpdatedPtNodeParams->getHeadPos();
+    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
+    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
+    if (usesAdditionalBuffer) {
+        pos -= mTrieBuffer->getOriginalBufferSize();
+    }
+    // Read original flags
+    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
+            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
+    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
+            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
+                    false /* isDeleted */, true /* willBecomeNonTerminal */);
+    if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+            toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */)) {
+        AKLOGE("Cannot update terminal position lookup table. terminal id: %d",
+                toBeUpdatedPtNodeParams->getTerminalId());
+        return false;
+    }
+    // Update flags.
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
+    return DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
+            &writingPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const UnigramProperty *const unigramProperty) {
+    // Update probability and historical information.
+    // TODO: Update other information in the unigram property.
+    if (!toBeUpdatedPtNodeParams->isTerminal()) {
+        return false;
+    }
+    const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
+    return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
+            toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntryOfUnigramProperty);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+        const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
+    if (!toBeUpdatedPtNodeParams->isTerminal()) {
+        AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
+        return false;
+    }
+    const ProbabilityEntry originalProbabilityEntry =
+            mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
+                    toBeUpdatedPtNodeParams->getTerminalId());
+    if (originalProbabilityEntry.isValid()) {
+        *outNeedsToKeepPtNode = true;
+        return true;
+    }
+    if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
+        AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
+        return false;
+    }
+    *outNeedsToKeepPtNode = false;
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
+        const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
+    int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
+    return DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+            newChildrenPosition, &childrenPosFieldPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const int newTerminalId) {
+    return mTrieBuffer->writeUint(newTerminalId, Ver4DictConstants::TERMINAL_ID_FIELD_SIZE,
+            toBeUpdatedPtNodeParams->getTerminalIdFieldPos());
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) {
+    return writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, 0 /* outTerminalId */,
+            ptNodeWritingPos);
+}
+
+bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, const UnigramProperty *const unigramProperty,
+        int *const ptNodeWritingPos) {
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (!writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, &terminalId,
+            ptNodeWritingPos)) {
+        return false;
+    }
+    // Write probability.
+    ProbabilityEntry newProbabilityEntry;
+    const ProbabilityEntry probabilityEntryOfUnigramProperty = ProbabilityEntry(unigramProperty);
+    return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
+            terminalId, &probabilityEntryOfUnigramProperty);
+}
+
+// TODO: Support counting ngram entries.
+bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
+        const NgramProperty *const ngramProperty, bool *const outAddedNewBigram) {
+    LanguageModelDictContent *const languageModelDictContent =
+            mBuffers->getMutableLanguageModelDictContent();
+    const ProbabilityEntry probabilityEntry =
+            languageModelDictContent->getNgramProbabilityEntry(prevWordIds, wordId);
+    const ProbabilityEntry probabilityEntryOfNgramProperty(ngramProperty);
+    if (!languageModelDictContent->setNgramProbabilityEntry(
+            prevWordIds, wordId, &probabilityEntryOfNgramProperty)) {
+        AKLOGE("Cannot add new ngram entry. prevWordId[0]: %d, prevWordId.size(): %zd, wordId: %d",
+                prevWordIds[0], prevWordIds.size(), wordId);
+        return false;
+    }
+    if (!probabilityEntry.isValid() && outAddedNewBigram) {
+        *outAddedNewBigram = true;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
+        const int wordId) {
+    LanguageModelDictContent *const languageModelDictContent =
+            mBuffers->getMutableLanguageModelDictContent();
+    return languageModelDictContent->removeNgramProbabilityEntry(prevWordIds, wordId);
+}
+
+// TODO: Remove when we stop supporting v402 format.
+bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
+            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
+    // Do nothing.
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
+        const PtNodeParams *const toBeUpdatedPtNodeParams,
+        const DictPositionRelocationMap *const dictPositionRelocationMap,
+        int *const outBigramEntryCount) {
+    int parentPos = toBeUpdatedPtNodeParams->getParentPos();
+    if (parentPos != NOT_A_DICT_POS) {
+        PtNodeWriter::PtNodePositionRelocationMap::const_iterator it =
+                dictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
+        if (it != dictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
+            parentPos = it->second;
+        }
+    }
+    int writingPos = toBeUpdatedPtNodeParams->getHeadPos()
+            + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
+    // Write updated parent offset.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+            parentPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
+        return false;
+    }
+
+    // Updates children position.
+    int childrenPos = toBeUpdatedPtNodeParams->getChildrenPos();
+    if (childrenPos != NOT_A_DICT_POS) {
+        PtNodeWriter::PtNodeArrayPositionRelocationMap::const_iterator it =
+                dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
+        if (it != dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
+            childrenPos = it->second;
+        }
+    }
+    if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptNodeParams,
+        const int *const targetCodePoints, const int targetCodePointCount,
+        const int shortcutProbability) {
+    if (!mShortcutPolicy->addNewShortcut(ptNodeParams->getTerminalId(),
+            targetCodePoints, targetCodePointCount, shortcutProbability)) {
+        AKLOGE("Cannot add new shortcut entry. terminalId: %d", ptNodeParams->getTerminalId());
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
+        const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+        int *const ptNodeWritingPos) {
+    const int nodePos = *ptNodeWritingPos;
+    // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the
+    // PtNode writing.
+    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer,
+            0 /* nodeFlags */, ptNodeWritingPos)) {
+        return false;
+    }
+    // Calculate a parent offset and write the offset.
+    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) {
+        return false;
+    }
+    // Write code points
+    if (!DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) {
+        return false;
+    }
+    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (!ptNodeParams->willBecomeNonTerminal()) {
+        if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) {
+            terminalId = ptNodeParams->getTerminalId();
+        } else if (ptNodeParams->isTerminal()) {
+            // Write terminal information using a new terminal id.
+            // Get a new unused terminal id.
+            terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId();
+        }
+    }
+    const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
+    if (isTerminal) {
+        // Update the lookup table.
+        if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
+                terminalId, nodePos)) {
+            return false;
+        }
+        // Write terminal Id.
+        if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId,
+                Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) {
+            return false;
+        }
+        if (outTerminalId) {
+            *outTerminalId = terminalId;
+        }
+    }
+    // Write children position
+    if (!DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
+            ptNodeParams->getChildrenPos(), ptNodeWritingPos)) {
+        return false;
+    }
+    return updatePtNodeFlags(nodePos, isTerminal,
+            ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
+}
+
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos, const bool isTerminal,
+        const bool hasMultipleChars) {
+    // Create node flags and write them.
+    PatriciaTrieReadingUtils::NodeFlags nodeFlags =
+            PatriciaTrieReadingUtils::createAndGetFlags(false /* isNotAWord */,
+                    false /* isPossiblyOffensive */, isTerminal, false /* hasShortcutTargets */,
+                    false /* hasBigrams */, hasMultipleChars, CHILDREN_POSITION_FIELD_SIZE);
+    if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
+        AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
+        return false;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
new file mode 100644
index 0000000..5585611
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H
+#define LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/pt_common/pt_node_params.h"
+#include "dictionary/structure/pt_common/pt_node_writer.h"
+#include "dictionary/structure/v4/content/probability_entry.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+class HeaderPolicy;
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PtNodeArrayReader;
+class Ver4ShortcutListPolicy;
+
+/*
+ * This class is used for helping to writes nodes of ver4 patricia trie.
+ */
+class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
+ public:
+    Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer,
+            Ver4DictBuffers *const buffers, const PtNodeReader *const ptNodeReader,
+            const PtNodeArrayReader *const ptNodeArrayReader,
+            Ver4ShortcutListPolicy *const shortcutPolicy)
+            : mTrieBuffer(trieBuffer), mBuffers(buffers),
+              mReadingHelper(ptNodeReader, ptNodeArrayReader), mShortcutPolicy(shortcutPolicy) {}
+
+    virtual ~Ver4PatriciaTrieNodeWriter() {}
+
+    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int movedPos, const int bigramLinkedNodePos);
+
+    virtual bool markPtNodeAsWillBecomeNonTerminal(
+            const PtNodeParams *const toBeUpdatedPtNodeParams);
+
+    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const UnigramProperty *const unigramProperty);
+
+    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+            const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
+
+    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int newChildrenPosition);
+
+    bool updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const int newTerminalId);
+
+    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            int *const ptNodeWritingPos);
+
+    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
+            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
+
+    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
+            const NgramProperty *const ngramProperty, bool *const outAddedNewEntry);
+
+    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId);
+
+    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
+            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount);
+
+    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
+            const DictPositionRelocationMap *const dictPositionRelocationMap,
+            int *const outBigramEntryCount);
+
+    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
+            const int *const targetCodePoints, const int targetCodePointCount,
+            const int shortcutProbability);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
+
+    bool writePtNodeAndGetTerminalIdAndAdvancePosition(
+            const PtNodeParams *const ptNodeParams, int *const outTerminalId,
+            int *const ptNodeWritingPos);
+
+    bool updatePtNodeFlags(const int ptNodePos, const bool isTerminal, const bool hasMultipleChars);
+
+    static const int CHILDREN_POSITION_FIELD_SIZE;
+
+    BufferWithExtendableBuffer *const mTrieBuffer;
+    Ver4DictBuffers *const mBuffers;
+    DynamicPtReadingHelper mReadingHelper;
+    Ver4ShortcutListPolicy *const mShortcutPolicy;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H */
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
new file mode 100644
index 0000000..1dbec55
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -0,0 +1,603 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_patricia_trie_policy.h"
+
+#include <array>
+#include <vector>
+
+#include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/dicnode/dic_node_vector.h"
+#include "dictionary/interface/ngram_listener.h"
+#include "dictionary/property/ngram_context.h"
+#include "dictionary/property/ngram_property.h"
+#include "dictionary/property/unigram_property.h"
+#include "dictionary/property/word_property.h"
+#include "dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+#include "dictionary/utils/multi_bigram_map.h"
+#include "dictionary/utils/probability_utils.h"
+#include "utils/ngram_utils.h"
+
+namespace latinime {
+
+// Note that there are corresponding definitions in Java side in BinaryDictionaryTests and
+// BinaryDictionaryDecayingTests.
+const char *const Ver4PatriciaTriePolicy::UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
+const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
+const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024;
+const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
+        Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+
+void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
+        DicNodeVector *const childDicNodes) const {
+    if (!dicNode->hasChildren()) {
+        return;
+    }
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
+    while (!readingHelper.isEnd()) {
+        const PtNodeParams ptNodeParams = readingHelper.getPtNodeParams();
+        if (!ptNodeParams.isValid()) {
+            break;
+        }
+        const bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
+        const int wordId = isTerminal ? ptNodeParams.getTerminalId() : NOT_A_WORD_ID;
+        childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getChildrenPos(),
+                wordId, ptNodeParams.getCodePointArrayView());
+        readingHelper.readNextSiblingNode(ptNodeParams);
+    }
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
+    }
+}
+
+int Ver4PatriciaTriePolicy::getCodePointsAndReturnCodePointCount(const int wordId,
+        const int maxCodePointCount, int *const outCodePoints) const {
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    const int ptNodePos =
+            mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(wordId);
+    readingHelper.initWithPtNodePos(ptNodePos);
+    const int codePointCount =  readingHelper.getCodePointsAndReturnCodePointCount(
+            maxCodePointCount, outCodePoints);
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in getCodePointsAndProbabilityAndReturnCodePointCount().");
+    }
+    return codePointCount;
+}
+
+int Ver4PatriciaTriePolicy::getWordId(const CodePointArrayView wordCodePoints,
+        const bool forceLowerCaseSearch) const {
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(getRootPosition());
+    const int ptNodePos = readingHelper.getTerminalPtNodePositionOfWord(wordCodePoints.data(),
+            wordCodePoints.size(), forceLowerCaseSearch);
+    if (readingHelper.isError()) {
+        mIsCorrupted = true;
+        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
+    }
+    if (ptNodePos == NOT_A_DICT_POS) {
+        return NOT_A_WORD_ID;
+    }
+    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    if (ptNodeParams.isDeleted()) {
+        return NOT_A_WORD_ID;
+    }
+    return ptNodeParams.getTerminalId();
+}
+
+const WordAttributes Ver4PatriciaTriePolicy::getWordAttributesInContext(
+        const WordIdArrayView prevWordIds, const int wordId,
+        MultiBigramMap *const multiBigramMap) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return WordAttributes();
+    }
+    return mBuffers->getLanguageModelDictContent()->getWordAttributes(prevWordIds, wordId,
+            false /* mustMatchAllPrevWords */, mHeaderPolicy);
+}
+
+int Ver4PatriciaTriePolicy::getProbabilityOfWord(const WordIdArrayView prevWordIds,
+        const int wordId) const {
+    if (wordId == NOT_A_WORD_ID || prevWordIds.contains(NOT_A_WORD_ID)) {
+        return NOT_A_PROBABILITY;
+    }
+    const WordAttributes wordAttributes =
+            mBuffers->getLanguageModelDictContent()->getWordAttributes(prevWordIds, wordId,
+                    true /* mustMatchAllPrevWords */, mHeaderPolicy);
+    if (wordAttributes.isBlacklisted() || wordAttributes.isNotAWord()) {
+        return NOT_A_PROBABILITY;
+    }
+    return wordAttributes.getProbability();
+}
+
+BinaryDictionaryShortcutIterator Ver4PatriciaTriePolicy::getShortcutIterator(
+        const int wordId) const {
+    const int shortcutPos = getShortcutPositionOfWord(wordId);
+    return BinaryDictionaryShortcutIterator(&mShortcutPolicy, shortcutPos);
+}
+
+void Ver4PatriciaTriePolicy::iterateNgramEntries(const WordIdArrayView prevWordIds,
+        NgramListener *const listener) const {
+    if (prevWordIds.empty()) {
+        return;
+    }
+    const auto languageModelDictContent = mBuffers->getLanguageModelDictContent();
+    for (size_t i = 1; i <= prevWordIds.size(); ++i) {
+        for (const auto entry : languageModelDictContent->getProbabilityEntries(
+                prevWordIds.limit(i))) {
+            const ProbabilityEntry &probabilityEntry = entry.getProbabilityEntry();
+            if (!probabilityEntry.isValid()) {
+                continue;
+            }
+            int probability = NOT_A_PROBABILITY;
+            if (probabilityEntry.hasHistoricalInfo()) {
+                // TODO: Quit checking count here.
+                // If count <= 1, the word can be an invaild word. The actual probability should
+                // be checked using getWordAttributesInContext() in onVisitEntry().
+                probability = probabilityEntry.getHistoricalInfo()->getCount() <= 1 ?
+                        NOT_A_PROBABILITY : 0;
+            } else {
+                probability = probabilityEntry.getProbability();
+            }
+            listener->onVisitEntry(probability, entry.getWordId());
+        }
+    }
+}
+
+int Ver4PatriciaTriePolicy::getShortcutPositionOfWord(const int wordId) const {
+    if (wordId == NOT_A_WORD_ID) {
+        return NOT_A_DICT_POS;
+    }
+    const int ptNodePos =
+            mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(wordId);
+    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
+    if (ptNodeParams.isDeleted()) {
+        return NOT_A_DICT_POS;
+    }
+    return mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
+            ptNodeParams.getTerminalId());
+}
+
+bool Ver4PatriciaTriePolicy::addUnigramEntry(const CodePointArrayView wordCodePoints,
+        const UnigramProperty *const unigramProperty) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert to the dictionary, length: %zd",
+                wordCodePoints.size());
+        return false;
+    }
+    for (const auto &shortcut : unigramProperty->getShortcuts()) {
+        if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %zd",
+                    shortcut.getTargetCodePoints()->size());
+            return false;
+        }
+    }
+    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(getRootPosition());
+    bool addedNewUnigram = false;
+    int codePointsToAdd[MAX_WORD_LENGTH];
+    int codePointCountToAdd = wordCodePoints.size();
+    memmove(codePointsToAdd, wordCodePoints.data(), sizeof(int) * codePointCountToAdd);
+    if (unigramProperty->representsBeginningOfSentence()) {
+        codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
+                codePointCountToAdd, MAX_WORD_LENGTH);
+    }
+    if (codePointCountToAdd <= 0) {
+        return false;
+    }
+    const CodePointArrayView codePointArrayView(codePointsToAdd, codePointCountToAdd);
+    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointArrayView, unigramProperty,
+            &addedNewUnigram)) {
+        if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
+            mEntryCounters.incrementNgramCount(NgramType::Unigram);
+        }
+        if (unigramProperty->getShortcuts().size() > 0) {
+            // Add shortcut target.
+            const int wordId = getWordId(codePointArrayView, false /* forceLowerCaseSearch */);
+            if (wordId == NOT_A_WORD_ID) {
+                AKLOGE("Cannot find word id to add shortcut target.");
+                return false;
+            }
+            const int wordPos =
+                    mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(wordId);
+            for (const auto &shortcut : unigramProperty->getShortcuts()) {
+                if (!mUpdatingHelper.addShortcutTarget(wordPos,
+                        CodePointArrayView(*shortcut.getTargetCodePoints()),
+                        shortcut.getProbability())) {
+                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %zd, "
+                            "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
+                            shortcut.getProbability());
+                    return false;
+                }
+            }
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool Ver4PatriciaTriePolicy::removeUnigramEntry(const CodePointArrayView wordCodePoints) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    const int wordId = getWordId(wordCodePoints, false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        return false;
+    }
+    const int ptNodePos =
+            mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(wordId);
+    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
+    if (!mNodeWriter.markPtNodeAsDeleted(&ptNodeParams)) {
+        AKLOGE("Cannot remove unigram. ptNodePos: %d", ptNodePos);
+        return false;
+    }
+    if (!mBuffers->getMutableLanguageModelDictContent()->removeProbabilityEntry(wordId)) {
+        return false;
+    }
+    if (!ptNodeParams.representsNonWordInfo()) {
+        mEntryCounters.decrementNgramCount(NgramType::Unigram);
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::addNgramEntry(const NgramProperty *const ngramProperty) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    const NgramContext *const ngramContext = ngramProperty->getNgramContext();
+    if (!ngramContext->isValid()) {
+        AKLOGE("Ngram context is not valid for adding n-gram entry to the dictionary.");
+        return false;
+    }
+    if (ngramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
+        AKLOGE("The word is too long to insert the ngram to the dictionary. "
+                "length: %zd", ngramProperty->getTargetCodePoints()->size());
+        return false;
+    }
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSearch */);
+    if (prevWordIds.empty()) {
+        return false;
+    }
+    for (size_t i = 0; i < prevWordIds.size(); ++i) {
+        if (prevWordIds[i] != NOT_A_WORD_ID) {
+            continue;
+        }
+        if (!ngramContext->isNthPrevWordBeginningOfSentence(i + 1 /* n */)) {
+            return false;
+        }
+        const UnigramProperty beginningOfSentenceUnigramProperty(
+                true /* representsBeginningOfSentence */, true /* isNotAWord */,
+                false /* isBlacklisted */, false /* isPossiblyOffensive */,
+                MAX_PROBABILITY /* probability */, HistoricalInfo());
+        if (!addUnigramEntry(ngramContext->getNthPrevWordCodePoints(1 /* n */),
+                &beginningOfSentenceUnigramProperty)) {
+            AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
+            return false;
+        }
+        // Refresh word ids.
+        ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */);
+    }
+    const int wordId = getWordId(CodePointArrayView(*ngramProperty->getTargetCodePoints()),
+            false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        return false;
+    }
+    bool addedNewEntry = false;
+    if (mNodeWriter.addNgramEntry(prevWordIds, wordId, ngramProperty, &addedNewEntry)) {
+        if (addedNewEntry) {
+            mEntryCounters.incrementNgramCount(
+                    NgramUtils::getNgramTypeFromWordCount(prevWordIds.size() + 1));
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool Ver4PatriciaTriePolicy::removeNgramEntry(const NgramContext *const ngramContext,
+        const CodePointArrayView wordCodePoints) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
+        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
+                mDictBuffer->getTailPosition());
+        return false;
+    }
+    if (!ngramContext->isValid()) {
+        AKLOGE("Ngram context is not valid for removing n-gram entry form the dictionary.");
+        return false;
+    }
+    if (wordCodePoints.size() > MAX_WORD_LENGTH) {
+        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %zd",
+                wordCodePoints.size());
+    }
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSerch */);
+    if (prevWordIds.empty() || prevWordIds.contains(NOT_A_WORD_ID)) {
+        return false;
+    }
+    const int wordId = getWordId(wordCodePoints, false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        return false;
+    }
+    if (mNodeWriter.removeNgramEntry(prevWordIds, wordId)) {
+        mEntryCounters.decrementNgramCount(
+                NgramUtils::getNgramTypeFromWordCount(prevWordIds.size() + 1));
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool Ver4PatriciaTriePolicy::updateEntriesForWordWithNgramContext(
+        const NgramContext *const ngramContext, const CodePointArrayView wordCodePoints,
+        const bool isValidWord, const HistoricalInfo historicalInfo) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: updateEntriesForWordWithNgramContext() is called for non-updatable "
+                "dictionary.");
+        return false;
+    }
+    const bool updateAsAValidWord = ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */) ?
+            false : isValidWord;
+    int wordId = getWordId(wordCodePoints, false /* tryLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        // The word is not in the dictionary.
+        const UnigramProperty unigramProperty(false /* representsBeginningOfSentence */,
+                false /* isNotAWord */, false /* isBlacklisted */, false /* isPossiblyOffensive */,
+                NOT_A_PROBABILITY, HistoricalInfo(historicalInfo.getTimestamp(), 0 /* level */,
+                0 /* count */));
+        if (!addUnigramEntry(wordCodePoints, &unigramProperty)) {
+            AKLOGE("Cannot add unigarm entry in updateEntriesForWordWithNgramContext().");
+            return false;
+        }
+        if (!isValidWord) {
+            return true;
+        }
+        wordId = getWordId(wordCodePoints, false /* tryLowerCaseSearch */);
+    }
+
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(this, &prevWordIdArray,
+            false /* tryLowerCaseSearch */);
+    if (ngramContext->isNthPrevWordBeginningOfSentence(1 /* n */)) {
+        if (prevWordIds.firstOrDefault(NOT_A_WORD_ID) == NOT_A_WORD_ID) {
+            const UnigramProperty beginningOfSentenceUnigramProperty(
+                    true /* representsBeginningOfSentence */,
+                    true /* isNotAWord */, false /* isPossiblyOffensive */, NOT_A_PROBABILITY,
+                    HistoricalInfo(historicalInfo.getTimestamp(), 0 /* level */, 0 /* count */));
+            if (!addUnigramEntry(ngramContext->getNthPrevWordCodePoints(1 /* n */),
+                    &beginningOfSentenceUnigramProperty)) {
+                AKLOGE("Cannot add BoS entry in updateEntriesForWordWithNgramContext().");
+                return false;
+            }
+            // Refresh word ids.
+            ngramContext->getPrevWordIds(this, &prevWordIdArray, false /* tryLowerCaseSearch */);
+        }
+        // Update entries for beginning of sentence.
+        if (!mBuffers->getMutableLanguageModelDictContent()->updateAllEntriesOnInputWord(
+                prevWordIds.skip(1 /* n */), prevWordIds[0], true /* isVaild */, historicalInfo,
+                mHeaderPolicy, &mEntryCounters)) {
+            return false;
+        }
+    }
+    if (!mBuffers->getMutableLanguageModelDictContent()->updateAllEntriesOnInputWord(prevWordIds,
+            wordId, updateAsAValidWord, historicalInfo, mHeaderPolicy, &mEntryCounters)) {
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::flush(const char *const filePath) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath);
+        return false;
+    }
+    if (!mWritingHelper.writeToDictFile(filePath, mEntryCounters.getEntryCounts())) {
+        AKLOGE("Cannot flush the dictionary to file.");
+        mIsCorrupted = true;
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) {
+        AKLOGE("Cannot flush the dictionary to file with GC.");
+        mIsCorrupted = true;
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
+    if (!mBuffers->isUpdatable()) {
+        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
+        return false;
+    }
+    if (mBuffers->isNearSizeLimit()) {
+        // Additional buffer size is near the limit.
+        return true;
+    } else if (mHeaderPolicy->getExtendedRegionSize() + mDictBuffer->getUsedAdditionalBufferSize()
+            > Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE) {
+        // Total extended region size of the trie exceeds the limit.
+        return true;
+    } else if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS
+            && mDictBuffer->getUsedAdditionalBufferSize() > 0) {
+        // Needs to reduce dictionary size.
+        return true;
+    } else if (mHeaderPolicy->isDecayingDict()) {
+        return ForgettingCurveUtils::needsToDecay(mindsBlockByGC, mEntryCounters.getEntryCounts(),
+                mHeaderPolicy);
+    }
+    return false;
+}
+
+void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength,
+        char *const outResult, const int maxResultLength) {
+    const int compareLength = queryLength + 1 /* terminator */;
+    if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mEntryCounters.getNgramCount(NgramType::Unigram));
+    } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d", mEntryCounters.getNgramCount(NgramType::Bigram));
+    } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mHeaderPolicy->isDecayingDict() ?
+                        ForgettingCurveUtils::getEntryCountHardLimit(
+                                mHeaderPolicy->getMaxNgramCounts().getNgramCount(
+                                        NgramType::Unigram)) :
+                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) {
+        snprintf(outResult, maxResultLength, "%d",
+                mHeaderPolicy->isDecayingDict() ?
+                        ForgettingCurveUtils::getEntryCountHardLimit(
+                                mHeaderPolicy->getMaxNgramCounts().getNgramCount(
+                                        NgramType::Bigram)) :
+                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    }
+}
+
+const WordProperty Ver4PatriciaTriePolicy::getWordProperty(
+        const CodePointArrayView wordCodePoints) const {
+    const int wordId = getWordId(wordCodePoints, false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) {
+        AKLOGE("getWordProperty is called for invalid word.");
+        return WordProperty();
+    }
+    const LanguageModelDictContent *const languageModelDictContent =
+            mBuffers->getLanguageModelDictContent();
+    // Fetch ngram information.
+    std::vector<NgramProperty> ngrams;
+    int ngramTargetCodePoints[MAX_WORD_LENGTH];
+    int ngramPrevWordsCodePoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH];
+    int ngramPrevWordsCodePointCount[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    bool ngramPrevWordIsBeginningOfSentense[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    for (const auto entry : languageModelDictContent->exportAllNgramEntriesRelatedToWord(
+            mHeaderPolicy, wordId)) {
+        const int codePointCount = getCodePointsAndReturnCodePointCount(entry.getTargetWordId(),
+                MAX_WORD_LENGTH, ngramTargetCodePoints);
+        const WordIdArrayView prevWordIds = entry.getPrevWordIds();
+        for (size_t i = 0; i < prevWordIds.size(); ++i) {
+            ngramPrevWordsCodePointCount[i] = getCodePointsAndReturnCodePointCount(prevWordIds[i],
+                       MAX_WORD_LENGTH, ngramPrevWordsCodePoints[i]);
+            ngramPrevWordIsBeginningOfSentense[i] = languageModelDictContent->getProbabilityEntry(
+                    prevWordIds[i]).representsBeginningOfSentence();
+            if (ngramPrevWordIsBeginningOfSentense[i]) {
+                ngramPrevWordsCodePointCount[i] = CharUtils::removeBeginningOfSentenceMarker(
+                        ngramPrevWordsCodePoints[i], ngramPrevWordsCodePointCount[i]);
+            }
+        }
+        const NgramContext ngramContext(ngramPrevWordsCodePoints, ngramPrevWordsCodePointCount,
+                ngramPrevWordIsBeginningOfSentense, prevWordIds.size());
+        const ProbabilityEntry ngramProbabilityEntry = entry.getProbabilityEntry();
+        const HistoricalInfo *const historicalInfo = ngramProbabilityEntry.getHistoricalInfo();
+        // TODO: Output flags in WordAttributes.
+        ngrams.emplace_back(ngramContext,
+                CodePointArrayView(ngramTargetCodePoints, codePointCount).toVector(),
+                entry.getWordAttributes().getProbability(), *historicalInfo);
+    }
+    // Fetch shortcut information.
+    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
+    int shortcutPos = getShortcutPositionOfWord(wordId);
+    if (shortcutPos != NOT_A_DICT_POS) {
+        int shortcutTarget[MAX_WORD_LENGTH];
+        const ShortcutDictContent *const shortcutDictContent =
+                mBuffers->getShortcutDictContent();
+        bool hasNext = true;
+        while (hasNext) {
+            int shortcutTargetLength = 0;
+            int shortcutProbability = NOT_A_PROBABILITY;
+            shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
+                    &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTarget, shortcutTargetLength).toVector(),
+                    shortcutProbability);
+        }
+    }
+    const WordAttributes wordAttributes = languageModelDictContent->getWordAttributes(
+            WordIdArrayView(), wordId, true /* mustMatchAllPrevWords */, mHeaderPolicy);
+    const ProbabilityEntry probabilityEntry = languageModelDictContent->getProbabilityEntry(wordId);
+    const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+    const UnigramProperty unigramProperty(probabilityEntry.representsBeginningOfSentence(),
+            wordAttributes.isNotAWord(), wordAttributes.isBlacklisted(),
+            wordAttributes.isPossiblyOffensive(), wordAttributes.getProbability(),
+            *historicalInfo, std::move(shortcuts));
+    return WordProperty(wordCodePoints.toVector(), unigramProperty, ngrams);
+}
+
+int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
+        int *const outCodePointCount) {
+    *outCodePointCount = 0;
+    if (token == 0) {
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
+                &mTerminalPtNodePositionsForIteratingWords);
+        DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
+        readingHelper.initWithPtNodeArrayPos(getRootPosition());
+        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
+    }
+    const int terminalPtNodePositionsVectorSize =
+            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
+    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
+        AKLOGE("Given token %d is invalid.", token);
+        return 0;
+    }
+    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
+    const PtNodeParams ptNodeParams =
+            mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(terminalPtNodePos);
+    *outCodePointCount = getCodePointsAndReturnCodePointCount(ptNodeParams.getTerminalId(),
+            MAX_WORD_LENGTH, outCodePoints);
+    const int nextToken = token + 1;
+    if (nextToken >= terminalPtNodePositionsVectorSize) {
+        // All words have been iterated.
+        mTerminalPtNodePositionsForIteratingWords.clear();
+        return 0;
+    }
+    return nextToken;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.h
new file mode 100644
index 0000000..d130a4e
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_PATRICIA_TRIE_POLICY_H
+#define LATINIME_VER4_PATRICIA_TRIE_POLICY_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/header/header_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
+#include "dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_writing_helper.h"
+#include "dictionary/structure/v4/ver4_pt_node_array_reader.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/entry_counters.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+class DicNode;
+class DicNodeVector;
+
+// Word id = Artificial id that is stored in the PtNode looked up by the word.
+class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
+ public:
+    Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
+            : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
+              mDictBuffer(mBuffers->getWritableTrieBuffer()),
+              mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+                      mBuffers->getTerminalPositionLookupTable()),
+              mNodeReader(mDictBuffer), mPtNodeArrayReader(mDictBuffer),
+              mNodeWriter(mDictBuffer, mBuffers.get(), &mNodeReader, &mPtNodeArrayReader,
+                      &mShortcutPolicy),
+              mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
+              mWritingHelper(mBuffers.get()),
+              mEntryCounters(mHeaderPolicy->getNgramCounts().getCountArray()),
+              mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
+
+    AK_FORCE_INLINE int getRootPosition() const {
+        return 0;
+    }
+
+    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
+            DicNodeVector *const childDicNodes) const;
+
+    int getCodePointsAndReturnCodePointCount(const int wordId, const int maxCodePointCount,
+            int *const outCodePoints) const;
+
+    int getWordId(const CodePointArrayView wordCodePoints, const bool forceLowerCaseSearch) const;
+
+    const WordAttributes getWordAttributesInContext(const WordIdArrayView prevWordIds,
+            const int wordId, MultiBigramMap *const multiBigramMap) const;
+
+    // TODO: Remove
+    int getProbability(const int unigramProbability, const int bigramProbability) const {
+        // Not used.
+        return NOT_A_PROBABILITY;
+    }
+
+    int getProbabilityOfWord(const WordIdArrayView prevWordIds, const int wordId) const;
+
+    void iterateNgramEntries(const WordIdArrayView prevWordIds,
+            NgramListener *const listener) const;
+
+    BinaryDictionaryShortcutIterator getShortcutIterator(const int wordId) const;
+
+    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
+        return mHeaderPolicy;
+    }
+
+    bool addUnigramEntry(const CodePointArrayView wordCodePoints,
+            const UnigramProperty *const unigramProperty);
+
+    bool removeUnigramEntry(const CodePointArrayView wordCodePoints);
+
+    bool addNgramEntry(const NgramProperty *const ngramProperty);
+
+    bool removeNgramEntry(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints);
+
+    bool updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+            const CodePointArrayView wordCodePoints, const bool isValidWord,
+            const HistoricalInfo historicalInfo);
+
+    bool flush(const char *const filePath);
+
+    bool flushWithGC(const char *const filePath);
+
+    bool needsToRunGC(const bool mindsBlockByGC) const;
+
+    void getProperty(const char *const query, const int queryLength, char *const outResult,
+            const int maxResultLength);
+
+    const WordProperty getWordProperty(const CodePointArrayView wordCodePoints) const;
+
+    int getNextWordAndNextToken(const int token, int *const outCodePoints,
+            int *const outCodePointCount);
+
+    bool isCorrupted() const {
+        return mIsCorrupted;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
+
+    static const char *const UNIGRAM_COUNT_QUERY;
+    static const char *const BIGRAM_COUNT_QUERY;
+    static const char *const MAX_UNIGRAM_COUNT_QUERY;
+    static const char *const MAX_BIGRAM_COUNT_QUERY;
+    // When the dictionary size is near the maximum size, we have to refuse dynamic operations to
+    // prevent the dictionary from overflowing.
+    static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
+    static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
+
+    const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
+    const HeaderPolicy *const mHeaderPolicy;
+    BufferWithExtendableBuffer *const mDictBuffer;
+    Ver4ShortcutListPolicy mShortcutPolicy;
+    Ver4PatriciaTrieNodeReader mNodeReader;
+    Ver4PtNodeArrayReader mPtNodeArrayReader;
+    Ver4PatriciaTrieNodeWriter mNodeWriter;
+    DynamicPtUpdatingHelper mUpdatingHelper;
+    Ver4PatriciaTrieWritingHelper mWritingHelper;
+    MutableEntryCounters mEntryCounters;
+    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
+    mutable bool mIsCorrupted;
+
+    int getShortcutPositionOfWord(const int wordId) const;
+};
+} // namespace latinime
+#endif // LATINIME_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
new file mode 100644
index 0000000..ccb70cd
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_patricia_trie_reading_utils.h"
+
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(
+        const uint8_t *const buffer, int *pos) {
+    return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
rename to native/jni/src/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
new file mode 100644
index 0000000..6dfdf4d
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/structure/v4/ver4_patricia_trie_writing_helper.h"
+
+#include <cstring>
+#include <queue>
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
+#include "dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
+#include "dictionary/structure/v4/ver4_pt_node_array_reader.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/file_utils.h"
+#include "dictionary/utils/forgetting_curve_utils.h"
+#include "utils/ngram_utils.h"
+
+namespace latinime {
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFile(const char *const dictDirPath,
+        const EntryCounts &entryCounts) const {
+    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+    BufferWithExtendableBuffer headerBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
+            + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
+            entryCounts, extendedRegionSize, &headerBuffer)) {
+        AKLOGE("Cannot write header structure to buffer. "
+                "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, trigramCount: %d,"
+                "extendedRegionSize: %d", false, entryCounts.getNgramCount(NgramType::Unigram),
+                entryCounts.getNgramCount(NgramType::Bigram),
+                entryCounts.getNgramCount(NgramType::Trigram),
+                extendedRegionSize);
+        return false;
+    }
+    return mBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
+        const char *const dictDirPath) {
+    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
+    Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
+            Ver4DictBuffers::createVer4DictBuffers(headerPolicy,
+                    Ver4DictConstants::MAX_DICTIONARY_SIZE));
+    MutableEntryCounters entryCounters;
+    if (!runGC(rootPtNodeArrayPos, headerPolicy, dictBuffers.get(), &entryCounters)) {
+        return false;
+    }
+    BufferWithExtendableBuffer headerBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+            entryCounters.getEntryCounts(), 0 /* extendedRegionSize */, &headerBuffer)) {
+        return false;
+    }
+    return dictBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
+}
+
+bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
+        const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
+        MutableEntryCounters *const outEntryCounters) {
+    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer());
+    Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
+    Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
+            mBuffers->getTerminalPositionLookupTable());
+    Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
+            mBuffers, &ptNodeReader, &ptNodeArrayReader, &shortcutPolicy);
+
+    if (!mBuffers->getMutableLanguageModelDictContent()->updateAllProbabilityEntriesForGC(
+            headerPolicy, outEntryCounters)) {
+        AKLOGE("Failed to update probabilities in language model dict content.");
+        return false;
+    }
+    if (headerPolicy->isDecayingDict()) {
+        const EntryCounts &maxEntryCounts = headerPolicy->getMaxNgramCounts();
+        if (!mBuffers->getMutableLanguageModelDictContent()->truncateEntries(
+                outEntryCounters->getEntryCounts(), maxEntryCounts, headerPolicy,
+                outEntryCounters)) {
+            AKLOGE("Failed to truncate entries in language model dict content.");
+            return false;
+        }
+    }
+
+    DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader);
+    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    DynamicPtGcEventListeners
+            ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
+                    traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
+                            &ptNodeWriter);
+    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+            &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
+        return false;
+    }
+
+    // Mapping from positions in mBuffer to positions in bufferToWrite.
+    PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
+    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
+            buffersToWrite, &ptNodeReader, &ptNodeArrayReader, &shortcutPolicy);
+    DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
+            traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
+                    buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
+    if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+            &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
+        return false;
+    }
+
+    // Create policy instances for the GCed dictionary.
+    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer());
+    Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
+    Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
+            buffersToWrite->getTerminalPositionLookupTable());
+    Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
+            buffersToWrite, &newPtNodeReader, &newPtNodeArrayreader,
+            &newShortcutPolicy);
+    // Re-assign terminal IDs for valid terminal PtNodes.
+    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
+    if(!buffersToWrite->getMutableTerminalPositionLookupTable()->runGCTerminalIds(
+            &terminalIdMap)) {
+        return false;
+    }
+    // Run GC for language model dict content.
+    if (!buffersToWrite->getMutableLanguageModelDictContent()->runGC(&terminalIdMap,
+            mBuffers->getLanguageModelDictContent())) {
+        return false;
+    }
+    // Run GC for shortcut dict content.
+    if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
+            mBuffers->getShortcutDictContent())) {
+        return false;
+    }
+    DynamicPtReadingHelper newDictReadingHelper(&newPtNodeReader, &newPtNodeArrayreader);
+    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
+            traversePolicyToUpdateAllPositionFields(&newPtNodeWriter, &dictPositionRelocationMap);
+    if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
+            &traversePolicyToUpdateAllPositionFields)) {
+        return false;
+    }
+    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
+    TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+            traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(&newPtNodeWriter, &terminalIdMap);
+    if (!newDictReadingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
+            &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
+        return false;
+    }
+    return true;
+}
+
+bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
+    if (!ptNodeParams->isTerminal()) {
+        return true;
+    }
+    TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
+            mTerminalIdMap->find(ptNodeParams->getTerminalId());
+    if (it == mTerminalIdMap->end()) {
+        AKLOGE("terminal Id %d is not in the terminal position map. map size: %zd",
+                ptNodeParams->getTerminalId(), mTerminalIdMap->size());
+        return false;
+    }
+    if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
+        AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
+        return false;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
new file mode 100644
index 0000000..68dd1ca
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+#define LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+#include "dictionary/utils/entry_counters.h"
+
+namespace latinime {
+
+class HeaderPolicy;
+class Ver4DictBuffers;
+class Ver4PatriciaTrieNodeReader;
+class Ver4PatriciaTrieNodeWriter;
+
+class Ver4PatriciaTrieWritingHelper {
+ public:
+    Ver4PatriciaTrieWritingHelper(Ver4DictBuffers *const buffers)
+            : mBuffers(buffers) {}
+
+    bool writeToDictFile(const char *const dictDirPath, const EntryCounts &entryCounts) const;
+
+    // This method cannot be const because the original dictionary buffer will be updated to detect
+    // useless PtNodes during GC.
+    bool writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const dictDirPath);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieWritingHelper);
+
+    class TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
+            : public DynamicPtReadingHelper::TraversingEventListener {
+     public:
+        TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(
+                Ver4PatriciaTrieNodeWriter *const ptNodeWriter,
+                const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap)
+                : mPtNodeWriter(ptNodeWriter), mTerminalIdMap(terminalIdMap) {}
+
+        bool onAscend() { return true; }
+
+        bool onDescend(const int ptNodeArrayPos) { return true; }
+
+        bool onReadingPtNodeArrayTail() { return true; }
+
+        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
+
+     private:
+        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds);
+
+        Ver4PatriciaTrieNodeWriter *const mPtNodeWriter;
+        const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
+    };
+
+    bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
+            Ver4DictBuffers *const buffersToWrite, MutableEntryCounters *const outEntryCounters);
+
+    Ver4DictBuffers *const mBuffers;
+};
+} // namespace latinime
+
+#endif /* LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H */
diff --git a/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.cpp b/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
new file mode 100644
index 0000000..63d0b4a
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/structure/v4/ver4_pt_node_array_reader.h"
+
+#include "dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
+#include "dictionary/structure/pt_common/patricia_trie_reading_utils.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
+    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of a bug or a broken dictionary.
+        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
+                ptNodeArrayPos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return false;
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int readingPos = ptNodeArrayPos;
+    if (usesAdditionalBuffer) {
+        readingPos -= mBuffer->getOriginalBufferSize();
+    }
+    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
+            dictBuf, &readingPos);
+    if (usesAdditionalBuffer) {
+        readingPos += mBuffer->getOriginalBufferSize();
+    }
+    if (ptNodeCountInArray < 0) {
+        AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
+        return false;
+    }
+    *outPtNodeCount = ptNodeCountInArray;
+    *outFirstPtNodePos = readingPos;
+    return true;
+}
+
+bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+        int *const outNextPtNodeArrayPos) const {
+    if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
+        // Reading invalid position because of bug or broken dictionary.
+        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
+                forwordLinkPos, mBuffer->getTailPosition());
+        ASSERT(false);
+        return false;
+    }
+    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
+    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
+    int readingPos = forwordLinkPos;
+    if (usesAdditionalBuffer) {
+        readingPos -= mBuffer->getOriginalBufferSize();
+    }
+    const int nextPtNodeArrayOffset =
+            DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
+    if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
+        *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
+    } else {
+        *outNextPtNodeArrayPos = NOT_A_DICT_POS;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.h b/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.h
new file mode 100644
index 0000000..ccb760b
--- /dev/null
+++ b/native/jni/src/dictionary/structure/v4/ver4_pt_node_array_reader.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_VER4_PT_NODE_ARRAY_READER_H
+#define LATINIME_VER4_PT_NODE_ARRAY_READER_H
+
+#include "defines.h"
+#include "dictionary/structure/pt_common/pt_node_array_reader.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+
+class Ver4PtNodeArrayReader : public PtNodeArrayReader {
+ public:
+    Ver4PtNodeArrayReader(const BufferWithExtendableBuffer *const buffer) : mBuffer(buffer) {};
+
+    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
+            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
+    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
+            int *const outNextPtNodeArrayPos) const;
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(Ver4PtNodeArrayReader);
+
+    const BufferWithExtendableBuffer *const mBuffer;
+};
+} // namespace latinime
+#endif /* LATINIME_VER4_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/dictionary/utils/binary_dictionary_bigrams_iterator.h b/native/jni/src/dictionary/utils/binary_dictionary_bigrams_iterator.h
new file mode 100644
index 0000000..8a61473
--- /dev/null
+++ b/native/jni/src/dictionary/utils/binary_dictionary_bigrams_iterator.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
+#define LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_bigrams_structure_policy.h"
+
+namespace latinime {
+
+class BinaryDictionaryBigramsIterator {
+ public:
+    // Empty iterator.
+    BinaryDictionaryBigramsIterator()
+           : mBigramsStructurePolicy(nullptr), mPos(NOT_A_DICT_POS),
+             mBigramPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY), mHasNext(false) {}
+
+    BinaryDictionaryBigramsIterator(
+            const DictionaryBigramsStructurePolicy *const bigramsStructurePolicy, const int pos)
+            : mBigramsStructurePolicy(bigramsStructurePolicy), mPos(pos),
+              mBigramPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY),
+              mHasNext(pos != NOT_A_DICT_POS) {}
+
+    BinaryDictionaryBigramsIterator(BinaryDictionaryBigramsIterator &&bigramsIterator)
+            : mBigramsStructurePolicy(bigramsIterator.mBigramsStructurePolicy),
+              mPos(bigramsIterator.mPos), mBigramPos(bigramsIterator.mBigramPos),
+              mProbability(bigramsIterator.mProbability), mHasNext(bigramsIterator.mHasNext) {}
+
+    AK_FORCE_INLINE bool hasNext() const {
+        return mHasNext;
+    }
+
+    AK_FORCE_INLINE void next() {
+        mBigramsStructurePolicy->getNextBigram(&mBigramPos, &mProbability, &mHasNext, &mPos);
+    }
+
+    AK_FORCE_INLINE int getProbability() const {
+        return mProbability;
+    }
+
+    AK_FORCE_INLINE int getBigramPos() const {
+        return mBigramPos;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(BinaryDictionaryBigramsIterator);
+
+    const DictionaryBigramsStructurePolicy *const mBigramsStructurePolicy;
+    int mPos;
+    int mBigramPos;
+    int mProbability;
+    bool mHasNext;
+};
+} // namespace latinime
+#endif // LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
diff --git a/native/jni/src/dictionary/utils/binary_dictionary_shortcut_iterator.h b/native/jni/src/dictionary/utils/binary_dictionary_shortcut_iterator.h
new file mode 100644
index 0000000..a4ddd58
--- /dev/null
+++ b/native/jni/src/dictionary/utils/binary_dictionary_shortcut_iterator.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
+#define LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_shortcuts_structure_policy.h"
+
+namespace latinime {
+
+class BinaryDictionaryShortcutIterator {
+ public:
+    BinaryDictionaryShortcutIterator(
+            const DictionaryShortcutsStructurePolicy *const shortcutStructurePolicy,
+            const int shortcutPos)
+            : mShortcutStructurePolicy(shortcutStructurePolicy),
+              mPos(shortcutStructurePolicy->getStartPos(shortcutPos)),
+              mHasNextShortcutTarget(shortcutPos != NOT_A_DICT_POS) {}
+
+    BinaryDictionaryShortcutIterator(const BinaryDictionaryShortcutIterator &&shortcutIterator)
+            : mShortcutStructurePolicy(shortcutIterator.mShortcutStructurePolicy),
+              mPos(shortcutIterator.mPos),
+              mHasNextShortcutTarget(shortcutIterator.mHasNextShortcutTarget) {}
+
+    AK_FORCE_INLINE bool hasNextShortcutTarget() const {
+        return mHasNextShortcutTarget;
+    }
+
+    // Gets the shortcut target itself as an int string and put it to outTarget, put its length
+    // to outTargetLength, put whether it is whitelist to outIsWhitelist.
+    AK_FORCE_INLINE void nextShortcutTarget(
+            const int maxDepth, int *const outTarget, int *const outTargetLength,
+            bool *const outIsWhitelist) {
+        mShortcutStructurePolicy->getNextShortcut(maxDepth, outTarget, outTargetLength,
+                outIsWhitelist, &mHasNextShortcutTarget, &mPos);
+    }
+
+ private:
+    DISALLOW_DEFAULT_CONSTRUCTOR(BinaryDictionaryShortcutIterator);
+    DISALLOW_ASSIGNMENT_OPERATOR(BinaryDictionaryShortcutIterator);
+
+    const DictionaryShortcutsStructurePolicy *const mShortcutStructurePolicy;
+    int mPos;
+    bool mHasNextShortcutTarget;
+};
+} // namespace latinime
+#endif // LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
diff --git a/native/jni/src/suggest/core/dictionary/bloom_filter.h b/native/jni/src/dictionary/utils/bloom_filter.h
similarity index 100%
rename from native/jni/src/suggest/core/dictionary/bloom_filter.h
rename to native/jni/src/dictionary/utils/bloom_filter.h
diff --git a/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.cpp b/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.cpp
new file mode 100644
index 0000000..2175696
--- /dev/null
+++ b/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+const size_t BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE = 1024 * 1024;
+const int BufferWithExtendableBuffer::NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE = 90;
+// TODO: Needs to allocate larger memory corresponding to the current vector size.
+const size_t BufferWithExtendableBuffer::EXTEND_ADDITIONAL_BUFFER_SIZE_STEP = 128 * 1024;
+
+uint32_t BufferWithExtendableBuffer::readUint(const int size, const int pos) const {
+    const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(pos);
+    const int posInBuffer = readingPosIsInAdditionalBuffer ? pos - mOriginalBuffer.size() : pos;
+    return ByteArrayUtils::readUint(getBuffer(readingPosIsInAdditionalBuffer), size, posInBuffer);
+}
+
+uint32_t BufferWithExtendableBuffer::readUintAndAdvancePosition(const int size,
+        int *const pos) const {
+    const uint32_t value = readUint(size, *pos);
+    *pos += size;
+    return value;
+}
+
+void BufferWithExtendableBuffer::readCodePointsAndAdvancePosition(const int maxCodePointCount,
+        int *const outCodePoints, int *outCodePointCount, int *const pos) const {
+    const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(*pos);
+    if (readingPosIsInAdditionalBuffer) {
+        *pos -= mOriginalBuffer.size();
+    }
+    // Code point table is not used for dynamic format.
+    *outCodePointCount = ByteArrayUtils::readStringAndAdvancePosition(
+            getBuffer(readingPosIsInAdditionalBuffer), maxCodePointCount,
+            nullptr /* codePointTable */, outCodePoints, pos);
+    if (readingPosIsInAdditionalBuffer) {
+        *pos += mOriginalBuffer.size();
+    }
+}
+
+bool BufferWithExtendableBuffer::extend(const int size) {
+    return checkAndPrepareWriting(getTailPosition(), size);
+}
+
+bool BufferWithExtendableBuffer::writeUint(const uint32_t data, const int size, const int pos) {
+    int writingPos = pos;
+    return writeUintAndAdvancePosition(data, size, &writingPos);
+}
+
+bool BufferWithExtendableBuffer::writeUintAndAdvancePosition(const uint32_t data, const int size,
+        int *const pos) {
+    if (!(size >= 1 && size <= 4)) {
+        AKLOGI("writeUintAndAdvancePosition() is called with invalid size: %d", size);
+        ASSERT(false);
+        return false;
+    }
+    if (!checkAndPrepareWriting(*pos, size)) {
+        return false;
+    }
+    const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos);
+    uint8_t *const buffer =
+            usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data();
+    if (usesAdditionalBuffer) {
+        *pos -= mOriginalBuffer.size();
+    }
+    ByteArrayUtils::writeUintAndAdvancePosition(buffer, data, size, pos);
+    if (usesAdditionalBuffer) {
+        *pos += mOriginalBuffer.size();
+    }
+    return true;
+}
+
+bool BufferWithExtendableBuffer::writeCodePointsAndAdvancePosition(const int *const codePoints,
+        const int codePointCount, const bool writesTerminator, int *const pos) {
+    const size_t size = ByteArrayUtils::calculateRequiredByteCountToStoreCodePoints(
+            codePoints, codePointCount, writesTerminator);
+    if (!checkAndPrepareWriting(*pos, size)) {
+        return false;
+    }
+    const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos);
+    uint8_t *const buffer =
+            usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data();
+    if (usesAdditionalBuffer) {
+        *pos -= mOriginalBuffer.size();
+    }
+    ByteArrayUtils::writeCodePointsAndAdvancePosition(buffer, codePoints, codePointCount,
+            writesTerminator, pos);
+    if (usesAdditionalBuffer) {
+        *pos += mOriginalBuffer.size();
+    }
+    return true;
+}
+
+bool BufferWithExtendableBuffer::extendBuffer(const size_t size) {
+    const size_t extendSize = std::max(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP, size);
+    const size_t sizeAfterExtending =
+            std::min(mAdditionalBuffer.size() + extendSize, mMaxAdditionalBufferSize);
+    if (sizeAfterExtending < mAdditionalBuffer.size() + size) {
+        return false;
+    }
+    mAdditionalBuffer.resize(sizeAfterExtending);
+    return true;
+}
+
+bool BufferWithExtendableBuffer::checkAndPrepareWriting(const int pos, const int size) {
+    if (pos < 0 || size < 0) {
+        // Invalid position or size.
+        return false;
+    }
+    const size_t totalRequiredSize = static_cast<size_t>(pos + size);
+    if (!isInAdditionalBuffer(pos)) {
+        // Here don't need to care about the additional buffer.
+        if (mOriginalBuffer.size() < totalRequiredSize) {
+            // Violate the boundary.
+            return false;
+        }
+        // The buffer has sufficient capacity.
+        return true;
+    }
+    // Hereafter, pos is in the additional buffer.
+    const size_t tailPosition = static_cast<size_t>(getTailPosition());
+    if (totalRequiredSize <= tailPosition) {
+        // The buffer has sufficient capacity.
+        return true;
+    }
+    if (static_cast<size_t>(pos) != tailPosition) {
+        // The additional buffer must be extended from the tail position.
+        return false;
+    }
+    const size_t extendSize = totalRequiredSize -
+            std::min(mAdditionalBuffer.size() + mOriginalBuffer.size(), totalRequiredSize);
+    if (extendSize > 0 && !extendBuffer(extendSize)) {
+        // Failed to extend the buffer.
+        return false;
+    }
+    mUsedAdditionalBufferSize += size;
+    return true;
+}
+
+bool BufferWithExtendableBuffer::copy(const BufferWithExtendableBuffer *const sourceBuffer) {
+    int copyingPos = 0;
+    const int tailPos = sourceBuffer->getTailPosition();
+    const int maxDataChunkSize = sizeof(uint32_t);
+    while (copyingPos < tailPos) {
+        const int remainingSize = tailPos - copyingPos;
+        const int copyingSize = (remainingSize >= maxDataChunkSize) ?
+                maxDataChunkSize : remainingSize;
+        const uint32_t data = sourceBuffer->readUint(copyingSize, copyingPos);
+        if (!writeUint(data, copyingSize, copyingPos)) {
+            return false;
+        }
+        copyingPos += copyingSize;
+    }
+    return true;
+}
+
+}
diff --git a/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.h b/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.h
new file mode 100644
index 0000000..0a141d4
--- /dev/null
+++ b/native/jni/src/dictionary/utils/buffer_with_extendable_buffer.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H
+#define LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/utils/byte_array_utils.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+// This is used as a buffer that can be extended for updatable dictionaries.
+// To optimize performance, raw pointer is directly used for reading buffer. The position has to be
+// adjusted to access additional buffer. On the other hand, this class does not provide writable
+// raw pointer but provides several methods that handle boundary checking for writing data.
+class BufferWithExtendableBuffer {
+ public:
+    static const size_t DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE;
+
+    BufferWithExtendableBuffer(const ReadWriteByteArrayView originalBuffer,
+            const int maxAdditionalBufferSize)
+            : mOriginalBuffer(originalBuffer), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
+              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
+
+    // Without original buffer.
+    BufferWithExtendableBuffer(const int maxAdditionalBufferSize)
+            : mOriginalBuffer(), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
+              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
+
+    AK_FORCE_INLINE int getTailPosition() const {
+        return mOriginalBuffer.size() + mUsedAdditionalBufferSize;
+    }
+
+    AK_FORCE_INLINE int getUsedAdditionalBufferSize() const {
+        return mUsedAdditionalBufferSize;
+    }
+
+    /**
+     * For reading.
+     */
+    AK_FORCE_INLINE bool isInAdditionalBuffer(const int position) const {
+        return position >= static_cast<int>(mOriginalBuffer.size());
+    }
+
+    // TODO: Resolve the issue that the address can be changed when the vector is resized.
+    // CAVEAT!: Be careful about array out of bound access with buffers
+    AK_FORCE_INLINE const uint8_t *getBuffer(const bool usesAdditionalBuffer) const {
+        if (usesAdditionalBuffer) {
+            return mAdditionalBuffer.data();
+        } else {
+            return mOriginalBuffer.data();
+        }
+    }
+
+    uint32_t readUint(const int size, const int pos) const;
+
+    uint32_t readUintAndAdvancePosition(const int size, int *const pos) const;
+
+    void readCodePointsAndAdvancePosition(const int maxCodePointCount,
+            int *const outCodePoints, int *outCodePointCount, int *const pos) const;
+
+    AK_FORCE_INLINE int getOriginalBufferSize() const {
+        return mOriginalBuffer.size();
+    }
+
+    AK_FORCE_INLINE bool isNearSizeLimit() const {
+        return mAdditionalBuffer.size() >= ((mMaxAdditionalBufferSize
+                * NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE) / 100);
+    }
+
+    bool extend(const int size);
+
+    /**
+     * For writing.
+     *
+     * Writing is allowed for original buffer, already written region of additional buffer and the
+     * tail of additional buffer.
+     */
+    bool writeUint(const uint32_t data, const int size, const int pos);
+
+    bool writeUintAndAdvancePosition(const uint32_t data, const int size, int *const pos);
+
+    bool writeCodePointsAndAdvancePosition(const int *const codePoints, const int codePointCount,
+            const bool writesTerminator, int *const pos);
+
+    bool copy(const BufferWithExtendableBuffer *const sourceBuffer);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(BufferWithExtendableBuffer);
+
+    static const int NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE;
+    static const size_t EXTEND_ADDITIONAL_BUFFER_SIZE_STEP;
+
+    const ReadWriteByteArrayView mOriginalBuffer;
+    std::vector<uint8_t> mAdditionalBuffer;
+    int mUsedAdditionalBufferSize;
+    const size_t mMaxAdditionalBufferSize;
+
+    // Return if the buffer is successfully extended or not.
+    bool extendBuffer(const size_t size);
+
+    // Returns if it is possible to write size-bytes from pos. When pos is at the tail position of
+    // the additional buffer, try extending the buffer.
+    bool checkAndPrepareWriting(const int pos, const int size);
+};
+}
+#endif /* LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H */
diff --git a/native/jni/src/dictionary/utils/byte_array_utils.cpp b/native/jni/src/dictionary/utils/byte_array_utils.cpp
new file mode 100644
index 0000000..d38f082
--- /dev/null
+++ b/native/jni/src/dictionary/utils/byte_array_utils.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+const uint8_t ByteArrayUtils::MINIMUM_ONE_BYTE_CHARACTER_VALUE = 0x20;
+const uint8_t ByteArrayUtils::MAXIMUM_ONE_BYTE_CHARACTER_VALUE = 0xFF;
+const uint8_t ByteArrayUtils::CHARACTER_ARRAY_TERMINATOR = 0x1F;
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/byte_array_utils.h b/native/jni/src/dictionary/utils/byte_array_utils.h
new file mode 100644
index 0000000..abb9790
--- /dev/null
+++ b/native/jni/src/dictionary/utils/byte_array_utils.h
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_BYTE_ARRAY_UTILS_H
+#define LATINIME_BYTE_ARRAY_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+
+namespace latinime {
+
+/**
+ * Utility methods for reading byte arrays.
+ */
+class ByteArrayUtils {
+ public:
+    /**
+     * Integer writing
+     *
+     * Each method write a corresponding size integer in a big endian manner.
+     */
+    static AK_FORCE_INLINE void writeUintAndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, const int size, int *const pos) {
+        // size must be in 1 to 4.
+        ASSERT(size >= 1 && size <= 4);
+        switch (size) {
+            case 1:
+                ByteArrayUtils::writeUint8AndAdvancePosition(buffer, data, pos);
+                return;
+            case 2:
+                ByteArrayUtils::writeUint16AndAdvancePosition(buffer, data, pos);
+                return;
+            case 3:
+                ByteArrayUtils::writeUint24AndAdvancePosition(buffer, data, pos);
+                return;
+            case 4:
+                ByteArrayUtils::writeUint32AndAdvancePosition(buffer, data, pos);
+                return;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Integer reading
+     *
+     * Each method read a corresponding size integer in a big endian manner.
+     */
+    static AK_FORCE_INLINE uint32_t readUint32(const uint8_t *const buffer, const int pos) {
+        return (buffer[pos] << 24) ^ (buffer[pos + 1] << 16)
+                ^ (buffer[pos + 2] << 8) ^ buffer[pos + 3];
+    }
+
+    static AK_FORCE_INLINE uint32_t readUint24(const uint8_t *const buffer, const int pos) {
+        return (buffer[pos] << 16) ^ (buffer[pos + 1] << 8) ^ buffer[pos + 2];
+    }
+
+    static AK_FORCE_INLINE uint16_t readUint16(const uint8_t *const buffer, const int pos) {
+        return (buffer[pos] << 8) ^ buffer[pos + 1];
+    }
+
+    static AK_FORCE_INLINE uint8_t readUint8(const uint8_t *const buffer, const int pos) {
+        return buffer[pos];
+    }
+
+    static AK_FORCE_INLINE uint32_t readUint32AndAdvancePosition(
+            const uint8_t *const buffer, int *const pos) {
+        const uint32_t value = readUint32(buffer, *pos);
+        *pos += 4;
+        return value;
+    }
+
+    static AK_FORCE_INLINE int readSint24AndAdvancePosition(
+            const uint8_t *const buffer, int *const pos) {
+        const uint8_t value = readUint8(buffer, *pos);
+        if (value < 0x80) {
+            return readUint24AndAdvancePosition(buffer, pos);
+        } else {
+            (*pos)++;
+            return -(((value & 0x7F) << 16) ^ readUint16AndAdvancePosition(buffer, pos));
+        }
+    }
+
+    static AK_FORCE_INLINE uint32_t readUint24AndAdvancePosition(
+            const uint8_t *const buffer, int *const pos) {
+        const uint32_t value = readUint24(buffer, *pos);
+        *pos += 3;
+        return value;
+    }
+
+    static AK_FORCE_INLINE uint16_t readUint16AndAdvancePosition(
+            const uint8_t *const buffer, int *const pos) {
+        const uint16_t value = readUint16(buffer, *pos);
+        *pos += 2;
+        return value;
+    }
+
+    static AK_FORCE_INLINE uint8_t readUint8AndAdvancePosition(
+            const uint8_t *const buffer, int *const pos) {
+        return buffer[(*pos)++];
+    }
+
+    static AK_FORCE_INLINE uint32_t readUint(const uint8_t *const buffer,
+            const int size, const int pos) {
+        // size must be in 1 to 4.
+        ASSERT(size >= 1 && size <= 4);
+        switch (size) {
+            case 1:
+                return ByteArrayUtils::readUint8(buffer, pos);
+            case 2:
+                return ByteArrayUtils::readUint16(buffer, pos);
+            case 3:
+                return ByteArrayUtils::readUint24(buffer, pos);
+            case 4:
+                return ByteArrayUtils::readUint32(buffer, pos);
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Code Point Reading
+     *
+     * 1 byte = bbbbbbbb match
+     * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
+     * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
+     *       unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
+     *       00011111 would be outside unicode.
+     * else: iso-latin-1 code
+     * This allows for the whole unicode range to be encoded, including chars outside of
+     * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
+     * characters which should never happen anyway (and still work, but take 3 bytes).
+     */
+    static AK_FORCE_INLINE int readCodePoint(const uint8_t *const buffer, const int pos) {
+        int p = pos;
+        return readCodePointAndAdvancePosition(buffer, nullptr /* codePointTable */, &p);
+    }
+
+    static AK_FORCE_INLINE int readCodePointAndAdvancePosition(
+            const uint8_t *const buffer, const int *const codePointTable, int *const pos) {
+        /*
+         * codePointTable is an array to convert the most frequent characters in this dictionary to
+         * 1 byte code points. It is only made of the original code points of the most frequent
+         * characters used in this dictionary. 0x20 - 0xFF is used for the 1 byte characters.
+         * The original code points are restored by picking the code points at the indices of the
+         * codePointTable. The indices are calculated by subtracting 0x20 from the firstByte.
+         */
+        const uint8_t firstByte = readUint8(buffer, *pos);
+        if (firstByte < MINIMUM_ONE_BYTE_CHARACTER_VALUE) {
+            if (firstByte == CHARACTER_ARRAY_TERMINATOR) {
+                *pos += 1;
+                return NOT_A_CODE_POINT;
+            } else {
+                return readUint24AndAdvancePosition(buffer, pos);
+            }
+        } else {
+            *pos += 1;
+            if (codePointTable) {
+                return codePointTable[firstByte - MINIMUM_ONE_BYTE_CHARACTER_VALUE];
+            }
+            return firstByte;
+        }
+    }
+
+    /**
+     * String (array of code points) Reading
+     *
+     * Reads code points until the terminator is found.
+     */
+    // Returns the length of the string.
+    static int readStringAndAdvancePosition(const uint8_t *const buffer,
+            const int maxLength, const int *const codePointTable, int *const outBuffer,
+            int *const pos) {
+        int length = 0;
+        int codePoint = readCodePointAndAdvancePosition(buffer, codePointTable, pos);
+        while (NOT_A_CODE_POINT != codePoint && length < maxLength) {
+            outBuffer[length++] = codePoint;
+            codePoint = readCodePointAndAdvancePosition(buffer, codePointTable, pos);
+        }
+        return length;
+    }
+
+    // Advances the position and returns the length of the string.
+    static int advancePositionToBehindString(
+            const uint8_t *const buffer, const int maxLength, int *const pos) {
+        int length = 0;
+        int codePoint = readCodePointAndAdvancePosition(buffer, nullptr /* codePointTable */, pos);
+        while (NOT_A_CODE_POINT != codePoint && length < maxLength) {
+            codePoint = readCodePointAndAdvancePosition(buffer, nullptr /* codePointTable */, pos);
+            length++;
+        }
+        return length;
+    }
+
+    /**
+     * String (array of code points) Writing
+     */
+    static void writeCodePointsAndAdvancePosition(uint8_t *const buffer,
+            const int *const codePoints, const int codePointCount, const bool writesTerminator,
+            int *const pos) {
+        for (int i = 0; i < codePointCount; ++i) {
+            const int codePoint = codePoints[i];
+            if (codePoint == NOT_A_CODE_POINT || codePoint == CHARACTER_ARRAY_TERMINATOR) {
+                break;
+            } else if (codePoint < MINIMUM_ONE_BYTE_CHARACTER_VALUE
+                    || codePoint > MAXIMUM_ONE_BYTE_CHARACTER_VALUE) {
+                // three bytes character.
+                writeUint24AndAdvancePosition(buffer, codePoint, pos);
+            } else {
+                // one byte character.
+                writeUint8AndAdvancePosition(buffer, codePoint, pos);
+            }
+        }
+        if (writesTerminator) {
+            writeUint8AndAdvancePosition(buffer, CHARACTER_ARRAY_TERMINATOR, pos);
+        }
+    }
+
+    static int calculateRequiredByteCountToStoreCodePoints(const int *const codePoints,
+            const int codePointCount, const bool writesTerminator) {
+        int byteCount = 0;
+        for (int i = 0; i < codePointCount; ++i) {
+            const int codePoint = codePoints[i];
+            if (codePoint == NOT_A_CODE_POINT || codePoint == CHARACTER_ARRAY_TERMINATOR) {
+                break;
+            } else if (codePoint < MINIMUM_ONE_BYTE_CHARACTER_VALUE
+                    || codePoint > MAXIMUM_ONE_BYTE_CHARACTER_VALUE) {
+                // three bytes character.
+                byteCount += 3;
+            } else {
+                // one byte character.
+                byteCount += 1;
+            }
+        }
+        if (writesTerminator) {
+            // The terminator is one byte.
+            byteCount += 1;
+        }
+        return byteCount;
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayUtils);
+
+    static const uint8_t MINIMUM_ONE_BYTE_CHARACTER_VALUE;
+    static const uint8_t MAXIMUM_ONE_BYTE_CHARACTER_VALUE;
+    static const uint8_t CHARACTER_ARRAY_TERMINATOR;
+
+    static AK_FORCE_INLINE void writeUint32AndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 24) & 0xFF;
+        buffer[(*pos)++] = (data >> 16) & 0xFF;
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint24AndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 16) & 0xFF;
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint16AndAdvancePosition(uint8_t *const buffer,
+            const uint16_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint8AndAdvancePosition(uint8_t *const buffer,
+            const uint8_t data, int *const pos) {
+        buffer[(*pos)++] = data & 0xFF;
+    }
+};
+} // namespace latinime
+#endif /* LATINIME_BYTE_ARRAY_UTILS_H */
diff --git a/native/jni/src/dictionary/utils/dict_file_writing_utils.cpp b/native/jni/src/dictionary/utils/dict_file_writing_utils.cpp
new file mode 100644
index 0000000..033a758
--- /dev/null
+++ b/native/jni/src/dictionary/utils/dict_file_writing_utils.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/dict_file_writing_utils.h"
+
+#include <cstdio>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/structure/backward/v402/ver4_dict_buffers.h"
+#include "dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
+#include "dictionary/structure/v4/ver4_dict_buffers.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "dictionary/utils/entry_counters.h"
+#include "dictionary/utils/file_utils.h"
+#include "dictionary/utils/format_utils.h"
+#include "utils/time_keeper.h"
+
+namespace latinime {
+
+const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE = ".tmp";
+// Enough size to describe buffer size.
+const int DictFileWritingUtils::SIZE_OF_BUFFER_SIZE_FIELD = 4;
+
+/* static */ bool DictFileWritingUtils::createEmptyDictFile(const char *const filePath,
+        const int dictVersion, const std::vector<int> localeAsCodePointVector,
+        const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
+    TimeKeeper::setCurrentTime();
+    const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::getFormatVersion(dictVersion);
+    switch (formatVersion) {
+        case FormatUtils::VERSION_402:
+            return createEmptyV4DictFile<backward::v402::Ver4DictConstants,
+                    backward::v402::Ver4DictBuffers,
+                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr>(
+                            filePath, localeAsCodePointVector, attributeMap, formatVersion);
+        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
+        case FormatUtils::VERSION_403:
+            return createEmptyV4DictFile<Ver4DictConstants, Ver4DictBuffers,
+                    Ver4DictBuffers::Ver4DictBuffersPtr>(
+                            filePath, localeAsCodePointVector, attributeMap, formatVersion);
+        default:
+            AKLOGE("Cannot create dictionary %s because format version %d is not supported.",
+                    filePath, dictVersion);
+            return false;
+    }
+}
+
+template<class DictConstants, class DictBuffers, class DictBuffersPtr>
+/* static */ bool DictFileWritingUtils::createEmptyV4DictFile(const char *const dirPath,
+        const std::vector<int> localeAsCodePointVector,
+        const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
+        const FormatUtils::FORMAT_VERSION formatVersion) {
+    HeaderPolicy headerPolicy(formatVersion, localeAsCodePointVector, attributeMap);
+    DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
+            DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
+    headerPolicy.fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
+            EntryCounts(), 0 /* extendedRegionSize */, dictBuffers->getWritableHeaderBuffer());
+    if (!DynamicPtWritingUtils::writeEmptyDictionary(
+            dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
+        AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
+        return false;
+    }
+    return dictBuffers->flush(dirPath);
+}
+
+/* static */ bool DictFileWritingUtils::flushBufferToFileWithSuffix(const char *const basePath,
+        const char *const suffix, const BufferWithExtendableBuffer *const buffer) {
+    const int filePathBufSize = FileUtils::getFilePathWithSuffixBufSize(basePath, suffix);
+    char filePath[filePathBufSize];
+    FileUtils::getFilePathWithSuffix(basePath, suffix, filePathBufSize, filePath);
+    return flushBufferToFile(filePath, buffer);
+}
+
+/* static */ bool DictFileWritingUtils::writeBufferToFileTail(FILE *const file,
+        const BufferWithExtendableBuffer *const buffer) {
+    uint8_t bufferSize[SIZE_OF_BUFFER_SIZE_FIELD];
+    int writingPos = 0;
+    ByteArrayUtils::writeUintAndAdvancePosition(bufferSize, buffer->getTailPosition(),
+            SIZE_OF_BUFFER_SIZE_FIELD, &writingPos);
+    if (fwrite(bufferSize, SIZE_OF_BUFFER_SIZE_FIELD, 1 /* count */, file) < 1) {
+        return false;
+    }
+    return writeBufferToFile(file, buffer);
+}
+
+/* static */ bool DictFileWritingUtils::flushBufferToFile(const char *const filePath,
+        const BufferWithExtendableBuffer *const buffer) {
+    const int fd = open(filePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+    if (fd == -1) {
+        AKLOGE("File %s cannot be opened. errno: %d", filePath, errno);
+        ASSERT(false);
+        return false;
+    }
+    FILE *const file = fdopen(fd, "wb");
+    if (!file) {
+        AKLOGE("fdopen failed for the file %s. errno: %d", filePath, errno);
+        ASSERT(false);
+        return false;
+    }
+    if (!writeBufferToFile(file, buffer)) {
+        fclose(file);
+        remove(filePath);
+        AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath,
+                buffer->getTailPosition());
+        ASSERT(false);
+        return false;
+    }
+    fclose(file);
+    return true;
+}
+
+// Returns whether the writing was succeeded or not.
+/* static */ bool DictFileWritingUtils::writeBufferToFile(FILE *const file,
+        const BufferWithExtendableBuffer *const buffer) {
+    const int originalBufSize = buffer->getOriginalBufferSize();
+    if (originalBufSize > 0 && fwrite(buffer->getBuffer(false /* usesAdditionalBuffer */),
+            originalBufSize, 1, file) < 1) {
+        return false;
+    }
+    const int additionalBufSize = buffer->getUsedAdditionalBufferSize();
+    if (additionalBufSize > 0 && fwrite(buffer->getBuffer(true /* usesAdditionalBuffer */),
+            additionalBufSize, 1, file) < 1) {
+        return false;
+    }
+    return true;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/dict_file_writing_utils.h b/native/jni/src/dictionary/utils/dict_file_writing_utils.h
new file mode 100644
index 0000000..102a89d
--- /dev/null
+++ b/native/jni/src/dictionary/utils/dict_file_writing_utils.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_DICT_FILE_WRITING_UTILS_H
+#define LATINIME_DICT_FILE_WRITING_UTILS_H
+
+#include <cstdio>
+
+#include "defines.h"
+#include "dictionary/header/header_read_write_utils.h"
+#include "dictionary/utils/format_utils.h"
+
+namespace latinime {
+
+class BufferWithExtendableBuffer;
+
+class DictFileWritingUtils {
+ public:
+    static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE;
+
+    static bool createEmptyDictFile(const char *const filePath, const int dictVersion,
+            const std::vector<int> localeAsCodePointVector,
+            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
+
+    static bool flushBufferToFileWithSuffix(const char *const basePath, const char *const suffix,
+            const BufferWithExtendableBuffer *const buffer);
+
+    static bool writeBufferToFileTail(FILE *const file,
+            const BufferWithExtendableBuffer *const buffer);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils);
+
+    static const int SIZE_OF_BUFFER_SIZE_FIELD;
+
+    static bool createEmptyV401DictFile(const char *const filePath,
+            const std::vector<int> localeAsCodePointVector,
+            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
+            const FormatUtils::FORMAT_VERSION formatVersion);
+
+    template<class DictConstants, class DictBuffers, class DictBuffersPtr>
+    static bool createEmptyV4DictFile(const char *const filePath,
+            const std::vector<int> localeAsCodePointVector,
+            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
+            const FormatUtils::FORMAT_VERSION formatVersion);
+
+    static bool flushBufferToFile(const char *const filePath,
+            const BufferWithExtendableBuffer *const buffer);
+
+    static bool writeBufferToFile(FILE *const file,
+            const BufferWithExtendableBuffer *const buffer);
+};
+} // namespace latinime
+#endif /* LATINIME_DICT_FILE_WRITING_UTILS_H */
diff --git a/native/jni/src/dictionary/utils/entry_counters.h b/native/jni/src/dictionary/utils/entry_counters.h
new file mode 100644
index 0000000..5e44302
--- /dev/null
+++ b/native/jni/src/dictionary/utils/entry_counters.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_ENTRY_COUNTERS_H
+#define LATINIME_ENTRY_COUNTERS_H
+
+#include <array>
+
+#include "defines.h"
+#include "utils/ngram_utils.h"
+
+namespace latinime {
+
+// Copyable but immutable
+class EntryCounts final {
+ public:
+    EntryCounts() : mEntryCounts({{0, 0, 0, 0}}) {}
+
+    explicit EntryCounts(const std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1> &counters)
+            : mEntryCounts(counters) {}
+
+    int getNgramCount(const NgramType ngramType) const {
+        return mEntryCounts[static_cast<int>(ngramType)];
+    }
+
+    const std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1> &getCountArray() const {
+        return mEntryCounts;
+    }
+
+ private:
+    DISALLOW_ASSIGNMENT_OPERATOR(EntryCounts);
+
+    // Counts from Unigram (0-th element) to (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram
+    // (MAX_PREV_WORD_COUNT_FOR_N_GRAM-th element)
+    const std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1> mEntryCounts;
+};
+
+class MutableEntryCounters final {
+ public:
+    MutableEntryCounters() {
+        mEntryCounters.fill(0);
+    }
+
+    explicit MutableEntryCounters(
+            const std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1> &counters)
+            : mEntryCounters(counters) {}
+
+    const EntryCounts getEntryCounts() const {
+        return EntryCounts(mEntryCounters);
+    }
+
+    void incrementNgramCount(const NgramType ngramType) {
+        ++mEntryCounters[static_cast<int>(ngramType)];
+    }
+
+    void decrementNgramCount(const NgramType ngramType) {
+        --mEntryCounters[static_cast<int>(ngramType)];
+    }
+
+    int getNgramCount(const NgramType ngramType) const {
+        return mEntryCounters[static_cast<int>(ngramType)];
+    }
+
+    void setNgramCount(const NgramType ngramType, const int count) {
+        mEntryCounters[static_cast<int>(ngramType)] = count;
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(MutableEntryCounters);
+
+    // Counters from Unigram (0-th element) to (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram
+    // (MAX_PREV_WORD_COUNT_FOR_N_GRAM-th element)
+    std::array<int, MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1> mEntryCounters;
+};
+} // namespace latinime
+#endif /* LATINIME_ENTRY_COUNTERS_H */
diff --git a/native/jni/src/dictionary/utils/file_utils.cpp b/native/jni/src/dictionary/utils/file_utils.cpp
new file mode 100644
index 0000000..bb392fb
--- /dev/null
+++ b/native/jni/src/dictionary/utils/file_utils.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/file_utils.h"
+
+#include <cstdio>
+#include <cstring>
+#include <dirent.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace latinime {
+
+// Returns -1 on error.
+/* static */ int FileUtils::getFileSize(const char *const filePath) {
+    const int fd = open(filePath, O_RDONLY);
+    if (fd == -1) {
+        return -1;
+    }
+    struct stat statBuf;
+    if (fstat(fd, &statBuf) != 0) {
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    return static_cast<int>(statBuf.st_size);
+}
+
+/* static */ bool FileUtils::existsDir(const char *const dirPath) {
+    DIR *const dir = opendir(dirPath);
+    if (dir == NULL) {
+        return false;
+    }
+    closedir(dir);
+    return true;
+}
+
+// Remove a directory and all files in the directory.
+/* static */ bool FileUtils::removeDirAndFiles(const char *const dirPath) {
+    return removeDirAndFiles(dirPath, 5 /* maxTries */);
+}
+
+// Remove a directory and all files in the directory, trying up to maxTimes.
+/* static */ bool FileUtils::removeDirAndFiles(const char *const dirPath, const int maxTries) {
+    DIR *const dir = opendir(dirPath);
+    if (dir == NULL) {
+        AKLOGE("Cannot open dir %s.", dirPath);
+        return true;
+    }
+    struct dirent *dirent;
+    while ((dirent = readdir(dir)) != NULL) {
+        if (dirent->d_type == DT_DIR) {
+            continue;
+        }
+        if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
+            continue;
+        }
+        const int filePathBufSize = getFilePathBufSize(dirPath, dirent->d_name);
+        char filePath[filePathBufSize];
+        getFilePath(dirPath, dirent->d_name, filePathBufSize, filePath);
+        if (remove(filePath) != 0) {
+            AKLOGE("Cannot remove file %s.", filePath);
+            closedir(dir);
+            return false;
+        }
+    }
+    closedir(dir);
+    if (remove(dirPath) != 0) {
+        if (maxTries > 0) {
+            // On NFS, deleting files sometimes creates new files. I'm not sure what the
+            // correct way of dealing with this is, but for the time being, this seems to work.
+            removeDirAndFiles(dirPath, maxTries - 1);
+        } else {
+            AKLOGE("Cannot remove directory %s.", dirPath);
+            return false;
+        }
+    }
+    return true;
+}
+
+/* static */ int FileUtils::getFilePathWithSuffixBufSize(const char *const filePath,
+        const char *const suffix) {
+    return strlen(filePath) + strlen(suffix) + 1 /* terminator */;
+}
+
+/* static */ void FileUtils::getFilePathWithSuffix(const char *const filePath,
+        const char *const suffix, const int filePathBufSize, char *const outFilePath) {
+    snprintf(outFilePath, filePathBufSize, "%s%s", filePath, suffix);
+}
+
+/* static */ int FileUtils::getFilePathBufSize(const char *const dirPath,
+        const char *const fileName) {
+    return strlen(dirPath) + 1 /* '/' */ + strlen(fileName) + 1 /* terminator */;
+}
+
+/* static */ void FileUtils::getFilePath(const char *const dirPath, const char *const fileName,
+        const int filePathBufSize, char *const outFilePath) {
+    snprintf(outFilePath, filePathBufSize, "%s/%s", dirPath, fileName);
+}
+
+/* static */ bool FileUtils::getFilePathWithoutSuffix(const char *const filePath,
+        const char *const suffix, const int outDirPathBufSize, char *const outDirPath) {
+    const int filePathLength = strlen(filePath);
+    const int suffixLength = strlen(suffix);
+    if (filePathLength <= suffixLength) {
+        AKLOGE("File path length (%s:%d) is shorter that suffix length (%s:%d).",
+                filePath, filePathLength, suffix, suffixLength);
+        return false;
+    }
+    const int resultFilePathLength = filePathLength - suffixLength;
+    if (outDirPathBufSize <= resultFilePathLength) {
+        AKLOGE("outDirPathBufSize is too small. filePath: %s, suffix: %s, outDirPathBufSize: %d",
+                filePath, suffix, outDirPathBufSize);
+        return false;
+    }
+    if (strncmp(filePath + resultFilePathLength, suffix, suffixLength) != 0) {
+        AKLOGE("File Path %s does not have %s as a suffix", filePath, suffix);
+        return false;
+    }
+    snprintf(outDirPath, resultFilePathLength + 1 /* terminator */, "%s", filePath);
+    return true;
+}
+
+/* static */ void FileUtils::getDirPath(const char *const filePath, const int outDirPathBufSize,
+        char *const outDirPath) {
+    for (int i = strlen(filePath) - 1; i >= 0; --i) {
+        if (filePath[i] == '/') {
+            if (i >= outDirPathBufSize) {
+                AKLOGE("outDirPathBufSize is too small. filePath: %s, outDirPathBufSize: %d",
+                        filePath, outDirPathBufSize);
+                ASSERT(false);
+                return;
+            }
+            snprintf(outDirPath, i + 1 /* terminator */, "%s", filePath);
+            return;
+        }
+    }
+}
+
+/* static */ void FileUtils::getBasename(const char *const filePath,
+        const int outNameBufSize, char *const outName) {
+    const int filePathBufSize = strlen(filePath) + 1 /* terminator */;
+    char filePathBuf[filePathBufSize];
+    snprintf(filePathBuf, filePathBufSize, "%s", filePath);
+    const char *const baseName = basename(filePathBuf);
+    const int baseNameLength = strlen(baseName);
+    if (baseNameLength >= outNameBufSize) {
+        AKLOGE("outNameBufSize is too small. filePath: %s, outNameBufSize: %d",
+                filePath, outNameBufSize);
+        return;
+    }
+    snprintf(outName, baseNameLength + 1 /* terminator */, "%s", baseName);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h b/native/jni/src/dictionary/utils/file_utils.h
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.h
rename to native/jni/src/dictionary/utils/file_utils.h
diff --git a/native/jni/src/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/dictionary/utils/forgetting_curve_utils.cpp
new file mode 100644
index 0000000..d79ed91
--- /dev/null
+++ b/native/jni/src/dictionary/utils/forgetting_curve_utils.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/forgetting_curve_utils.h"
+
+#include <algorithm>
+#include <cmath>
+#include <stdlib.h>
+
+#include "dictionary/header/header_policy.h"
+#include "dictionary/utils/probability_utils.h"
+#include "utils/time_keeper.h"
+
+namespace latinime {
+
+const int ForgettingCurveUtils::MULTIPLIER_TWO_IN_PROBABILITY_SCALE = 8;
+const int ForgettingCurveUtils::DECAY_INTERVAL_SECONDS = 2 * 60 * 60;
+
+const int ForgettingCurveUtils::MAX_LEVEL = 15;
+const int ForgettingCurveUtils::MIN_VISIBLE_LEVEL = 2;
+const int ForgettingCurveUtils::MAX_ELAPSED_TIME_STEP_COUNT = 31;
+const int ForgettingCurveUtils::DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD = 30;
+const int ForgettingCurveUtils::OCCURRENCES_TO_RAISE_THE_LEVEL = 1;
+// TODO: Evaluate whether this should be 7.5 days.
+// 15 days
+const int ForgettingCurveUtils::DURATION_TO_LOWER_THE_LEVEL_IN_SECONDS = 15 * 24 * 60 * 60;
+
+const float ForgettingCurveUtils::ENTRY_COUNT_HARD_LIMIT_WEIGHT = 1.2;
+
+const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityTable;
+
+// TODO: Revise the logic to decide the initial probability depending on the given probability.
+/* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfo(
+        const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
+        const HistoricalInfo *const newHistoricalInfo, const HeaderPolicy *const headerPolicy) {
+    const int timestamp = newHistoricalInfo->getTimestamp();
+    if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) {
+        // Add entry as a valid word.
+        const int level = clampToVisibleEntryLevelRange(newHistoricalInfo->getLevel());
+        const int count = clampToValidCountRange(newHistoricalInfo->getCount(), headerPolicy);
+        return HistoricalInfo(timestamp, level, count);
+    } else if (!originalHistoricalInfo->isValid()
+            || originalHistoricalInfo->getLevel() < newHistoricalInfo->getLevel()
+            || (originalHistoricalInfo->getLevel() == newHistoricalInfo->getLevel()
+                    && originalHistoricalInfo->getCount() < newHistoricalInfo->getCount())) {
+        // Initial information.
+        int count = newHistoricalInfo->getCount();
+        if (count >= OCCURRENCES_TO_RAISE_THE_LEVEL) {
+            const int level = clampToValidLevelRange(newHistoricalInfo->getLevel() + 1);
+            return HistoricalInfo(timestamp, level, 0 /* count */);
+        }
+        const int level = clampToValidLevelRange(newHistoricalInfo->getLevel());
+        return HistoricalInfo(timestamp, level, clampToValidCountRange(count, headerPolicy));
+    } else {
+        const int updatedCount = originalHistoricalInfo->getCount() + 1;
+        if (updatedCount >= OCCURRENCES_TO_RAISE_THE_LEVEL) {
+            // The count exceeds the max value the level can be incremented.
+            if (originalHistoricalInfo->getLevel() >= MAX_LEVEL) {
+                // The level is already max.
+                return HistoricalInfo(timestamp,
+                        originalHistoricalInfo->getLevel(), originalHistoricalInfo->getCount());
+            } else {
+                // Raise the level.
+                return HistoricalInfo(timestamp,
+                        originalHistoricalInfo->getLevel() + 1, 0 /* count */);
+            }
+        } else {
+            return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(), updatedCount);
+        }
+    }
+}
+
+/* static */ int ForgettingCurveUtils::decodeProbability(
+        const HistoricalInfo *const historicalInfo, const HeaderPolicy *const headerPolicy) {
+    const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimestamp(),
+            DURATION_TO_LOWER_THE_LEVEL_IN_SECONDS);
+    return sProbabilityTable.getProbability(
+            headerPolicy->getForgettingCurveProbabilityValuesTableId(),
+            clampToValidLevelRange(historicalInfo->getLevel()),
+            clampToValidTimeStepCountRange(elapsedTimeStepCount));
+}
+
+/* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo,
+        const HeaderPolicy *const headerPolicy) {
+    return historicalInfo->getLevel() > 0
+            || getElapsedTimeStepCount(historicalInfo->getTimestamp(),
+                    DURATION_TO_LOWER_THE_LEVEL_IN_SECONDS)
+                            < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
+}
+
+/* static */ const HistoricalInfo ForgettingCurveUtils::createHistoricalInfoToSave(
+        const HistoricalInfo *const originalHistoricalInfo,
+        const HeaderPolicy *const headerPolicy) {
+    if (originalHistoricalInfo->getTimestamp() == NOT_A_TIMESTAMP) {
+        return HistoricalInfo();
+    }
+    const int durationToLevelDownInSeconds = DURATION_TO_LOWER_THE_LEVEL_IN_SECONDS;
+    const int elapsedTimeStep = getElapsedTimeStepCount(
+            originalHistoricalInfo->getTimestamp(), durationToLevelDownInSeconds);
+    if (elapsedTimeStep <= MAX_ELAPSED_TIME_STEP_COUNT) {
+        // No need to update historical info.
+        return *originalHistoricalInfo;
+    }
+    // Lower the level.
+    const int maxLevelDownAmonut = elapsedTimeStep / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
+    const int levelDownAmount = (maxLevelDownAmonut >= originalHistoricalInfo->getLevel()) ?
+            originalHistoricalInfo->getLevel() : maxLevelDownAmonut;
+    const int adjustedTimestampInSeconds = originalHistoricalInfo->getTimestamp() +
+            levelDownAmount * durationToLevelDownInSeconds;
+    return HistoricalInfo(adjustedTimestampInSeconds,
+            originalHistoricalInfo->getLevel() - levelDownAmount, 0 /* count */);
+}
+
+/* static */ bool ForgettingCurveUtils::needsToDecay(const bool mindsBlockByDecay,
+        const EntryCounts &entryCounts, const HeaderPolicy *const headerPolicy) {
+    const EntryCounts &maxNgramCounts = headerPolicy->getMaxNgramCounts();
+    for (const auto ngramType : AllNgramTypes::ASCENDING) {
+        if (entryCounts.getNgramCount(ngramType)
+                >= getEntryCountHardLimit(maxNgramCounts.getNgramCount(ngramType))) {
+            // Unigram count exceeds the limit.
+            return true;
+        }
+    }
+    if (mindsBlockByDecay) {
+        return false;
+    }
+    if (headerPolicy->getLastDecayedTime() + DECAY_INTERVAL_SECONDS
+            < TimeKeeper::peekCurrentTime()) {
+        // Time to decay.
+        return true;
+    }
+    return false;
+}
+
+// See comments in ProbabilityUtils::backoff().
+/* static */ int ForgettingCurveUtils::backoff(const int unigramProbability) {
+    // See TODO comments in ForgettingCurveUtils::getProbability().
+    return unigramProbability;
+}
+
+/* static */ int ForgettingCurveUtils::getElapsedTimeStepCount(const int timestamp,
+        const int durationToLevelDownInSeconds) {
+    const int elapsedTimeInSeconds = TimeKeeper::peekCurrentTime() - timestamp;
+    const int timeStepDurationInSeconds =
+            durationToLevelDownInSeconds / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
+    return elapsedTimeInSeconds / timeStepDurationInSeconds;
+}
+
+/* static */ int ForgettingCurveUtils::clampToVisibleEntryLevelRange(const int level) {
+    return std::min(std::max(level, MIN_VISIBLE_LEVEL), MAX_LEVEL);
+}
+
+/* static */ int ForgettingCurveUtils::clampToValidCountRange(const int count,
+        const HeaderPolicy *const headerPolicy) {
+    return std::min(std::max(count, 0), OCCURRENCES_TO_RAISE_THE_LEVEL - 1);
+}
+
+/* static */ int ForgettingCurveUtils::clampToValidLevelRange(const int level) {
+    return std::min(std::max(level, 0), MAX_LEVEL);
+}
+
+/* static */ int ForgettingCurveUtils::clampToValidTimeStepCountRange(const int timeStepCount) {
+    return std::min(std::max(timeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT);
+}
+
+const int ForgettingCurveUtils::ProbabilityTable::PROBABILITY_TABLE_COUNT = 4;
+const int ForgettingCurveUtils::ProbabilityTable::WEAK_PROBABILITY_TABLE_ID = 0;
+const int ForgettingCurveUtils::ProbabilityTable::MODEST_PROBABILITY_TABLE_ID = 1;
+const int ForgettingCurveUtils::ProbabilityTable::STRONG_PROBABILITY_TABLE_ID = 2;
+const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_PROBABILITY_TABLE_ID = 3;
+const int ForgettingCurveUtils::ProbabilityTable::WEAK_MAX_PROBABILITY = 127;
+const int ForgettingCurveUtils::ProbabilityTable::MODEST_BASE_PROBABILITY = 8;
+const int ForgettingCurveUtils::ProbabilityTable::STRONG_BASE_PROBABILITY = 9;
+const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_BASE_PROBABILITY = 10;
+
+
+ForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTables() {
+    mTables.resize(PROBABILITY_TABLE_COUNT);
+    for (int tableId = 0; tableId < PROBABILITY_TABLE_COUNT; ++tableId) {
+        mTables[tableId].resize(MAX_LEVEL + 1);
+        for (int level = 0; level <= MAX_LEVEL; ++level) {
+            mTables[tableId][level].resize(MAX_ELAPSED_TIME_STEP_COUNT + 1);
+            const float initialProbability = getBaseProbabilityForLevel(tableId, level);
+            const float endProbability = getBaseProbabilityForLevel(tableId, level - 1);
+            for (int timeStepCount = 0; timeStepCount <= MAX_ELAPSED_TIME_STEP_COUNT;
+                    ++timeStepCount) {
+                if (level < MIN_VISIBLE_LEVEL) {
+                    mTables[tableId][level][timeStepCount] = NOT_A_PROBABILITY;
+                    continue;
+                }
+                const float probability = initialProbability
+                        * powf(initialProbability / endProbability,
+                                -1.0f * static_cast<float>(timeStepCount)
+                                        / static_cast<float>(MAX_ELAPSED_TIME_STEP_COUNT + 1));
+                mTables[tableId][level][timeStepCount] =
+                        std::min(std::max(static_cast<int>(probability), 1), MAX_PROBABILITY);
+            }
+        }
+    }
+}
+
+/* static */ int ForgettingCurveUtils::ProbabilityTable::getBaseProbabilityForLevel(
+        const int tableId, const int level) {
+    if (tableId == WEAK_PROBABILITY_TABLE_ID) {
+        // Max probability is 127.
+        return static_cast<float>(WEAK_MAX_PROBABILITY / (1 << (MAX_LEVEL - level)));
+    } else if (tableId == MODEST_PROBABILITY_TABLE_ID) {
+        // Max probability is 128.
+        return static_cast<float>(MODEST_BASE_PROBABILITY * (level + 1));
+    } else if (tableId == STRONG_PROBABILITY_TABLE_ID) {
+        // Max probability is 140.
+        return static_cast<float>(STRONG_BASE_PROBABILITY * (level + 1));
+    } else if (tableId == AGGRESSIVE_PROBABILITY_TABLE_ID) {
+        // Max probability is 160.
+        return static_cast<float>(AGGRESSIVE_BASE_PROBABILITY * (level + 1));
+    } else {
+        return NOT_A_PROBABILITY;
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/forgetting_curve_utils.h b/native/jni/src/dictionary/utils/forgetting_curve_utils.h
new file mode 100644
index 0000000..ddaac7e
--- /dev/null
+++ b/native/jni/src/dictionary/utils/forgetting_curve_utils.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_FORGETTING_CURVE_UTILS_H
+#define LATINIME_FORGETTING_CURVE_UTILS_H
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/utils/entry_counters.h"
+
+namespace latinime {
+
+class HeaderPolicy;
+
+class ForgettingCurveUtils {
+ public:
+    static const HistoricalInfo createUpdatedHistoricalInfo(
+            const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
+            const HistoricalInfo *const newHistoricalInfo, const HeaderPolicy *const headerPolicy);
+
+    static const HistoricalInfo createHistoricalInfoToSave(
+            const HistoricalInfo *const originalHistoricalInfo,
+            const HeaderPolicy *const headerPolicy);
+
+    static int decodeProbability(const HistoricalInfo *const historicalInfo,
+            const HeaderPolicy *const headerPolicy);
+
+    static bool needsToKeep(const HistoricalInfo *const historicalInfo,
+            const HeaderPolicy *const headerPolicy);
+
+    static bool needsToDecay(const bool mindsBlockByDecay, const EntryCounts &entryCounters,
+            const HeaderPolicy *const headerPolicy);
+
+    // TODO: Improve probability computation method and remove this.
+    static int getProbabilityBiasForNgram(const int n) {
+        return (n - 1) * MULTIPLIER_TWO_IN_PROBABILITY_SCALE;
+    }
+
+    AK_FORCE_INLINE static int getEntryCountHardLimit(const int maxEntryCount) {
+        return static_cast<int>(static_cast<float>(maxEntryCount)
+                * ENTRY_COUNT_HARD_LIMIT_WEIGHT);
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ForgettingCurveUtils);
+
+    class ProbabilityTable {
+     public:
+        ProbabilityTable();
+
+        int getProbability(const int tableId, const int level,
+                const int elapsedTimeStepCount) const {
+            return mTables[tableId][level][elapsedTimeStepCount];
+        }
+
+     private:
+        DISALLOW_COPY_AND_ASSIGN(ProbabilityTable);
+
+        static const int PROBABILITY_TABLE_COUNT;
+        static const int WEAK_PROBABILITY_TABLE_ID;
+        static const int MODEST_PROBABILITY_TABLE_ID;
+        static const int STRONG_PROBABILITY_TABLE_ID;
+        static const int AGGRESSIVE_PROBABILITY_TABLE_ID;
+
+        static const int WEAK_MAX_PROBABILITY;
+        static const int MODEST_BASE_PROBABILITY;
+        static const int STRONG_BASE_PROBABILITY;
+        static const int AGGRESSIVE_BASE_PROBABILITY;
+
+        std::vector<std::vector<std::vector<int>>> mTables;
+
+        static int getBaseProbabilityForLevel(const int tableId, const int level);
+    };
+
+    static const int MULTIPLIER_TWO_IN_PROBABILITY_SCALE;
+    static const int DECAY_INTERVAL_SECONDS;
+
+    static const int MAX_LEVEL;
+    static const int MIN_VISIBLE_LEVEL;
+    static const int MAX_ELAPSED_TIME_STEP_COUNT;
+    static const int DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
+    static const int OCCURRENCES_TO_RAISE_THE_LEVEL;
+    static const int DURATION_TO_LOWER_THE_LEVEL_IN_SECONDS;
+
+    static const float ENTRY_COUNT_HARD_LIMIT_WEIGHT;
+
+    static const ProbabilityTable sProbabilityTable;
+
+    static int backoff(const int unigramProbability);
+    static int getElapsedTimeStepCount(const int timestamp, const int durationToLevelDown);
+    static int clampToVisibleEntryLevelRange(const int level);
+    static int clampToValidLevelRange(const int level);
+    static int clampToValidCountRange(const int count, const HeaderPolicy *const headerPolicy);
+    static int clampToValidTimeStepCountRange(const int timeStepCount);
+};
+} // namespace latinime
+#endif /* LATINIME_FORGETTING_CURVE_UTILS_H */
diff --git a/native/jni/src/dictionary/utils/format_utils.cpp b/native/jni/src/dictionary/utils/format_utils.cpp
new file mode 100644
index 0000000..cef3b09
--- /dev/null
+++ b/native/jni/src/dictionary/utils/format_utils.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/format_utils.h"
+
+#include "dictionary/utils/byte_array_utils.h"
+
+namespace latinime {
+
+const uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
+
+// Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
+const size_t FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
+
+/* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) {
+    switch (formatVersion) {
+        case VERSION_2:
+        case VERSION_201:
+            AKLOGE("Dictionary versions 2 and 201 are incompatible with this version");
+            return UNKNOWN_VERSION;
+        case VERSION_202:
+            return VERSION_202;
+        case VERSION_4_ONLY_FOR_TESTING:
+            return VERSION_4_ONLY_FOR_TESTING;
+        case VERSION_402:
+            return VERSION_402;
+        case VERSION_403:
+            return VERSION_403;
+        default:
+            return UNKNOWN_VERSION;
+    }
+}
+/* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
+        const ReadOnlyByteArrayView dictBuffer) {
+    // The magic number is stored big-endian.
+    // If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
+    // understand this format.
+    if (dictBuffer.size() < DICTIONARY_MINIMUM_SIZE) {
+        return UNKNOWN_VERSION;
+    }
+    const uint32_t magicNumber = ByteArrayUtils::readUint32(dictBuffer.data(), 0);
+    switch (magicNumber) {
+        case MAGIC_NUMBER:
+            // The layout of the header is as follows:
+            // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE
+            // Dictionary format version number (2 bytes)
+            // Options (2 bytes)
+            // Header size (4 bytes) : integer, big endian
+            // Conceptually this converts the hardcoded value of the bytes in the file into
+            // the symbolic value we use in the code. But we want the constants to be the
+            // same so we use them for both here.
+            return getFormatVersion(ByteArrayUtils::readUint16(dictBuffer.data(), 4));
+        default:
+            return UNKNOWN_VERSION;
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/format_utils.h b/native/jni/src/dictionary/utils/format_utils.h
new file mode 100644
index 0000000..1616efc
--- /dev/null
+++ b/native/jni/src/dictionary/utils/format_utils.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_FORMAT_UTILS_H
+#define LATINIME_FORMAT_UTILS_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+/**
+ * Methods to handle binary dictionary format version.
+ */
+class FormatUtils {
+ public:
+    enum FORMAT_VERSION {
+        // These MUST have the same values as the relevant constants in FormatSpec.java.
+        // TODO: Remove VERSION_2 and VERSION_201 when we:
+        // * Confirm that old versions of LatinIME download old-format dictionaries
+        // * We no longer need the corresponding constants on the Java side for dicttool
+        VERSION_2 = 2,
+        VERSION_201 = 201,
+        VERSION_202 = 202,
+        VERSION_4_ONLY_FOR_TESTING = 399,
+        VERSION_402 = 402,
+        VERSION_403 = 403,
+        UNKNOWN_VERSION = -1
+    };
+
+    // 32 bit magic number is stored at the beginning of the dictionary header to reject
+    // unsupported or obsolete dictionary formats.
+    static const uint32_t MAGIC_NUMBER;
+
+    static FORMAT_VERSION getFormatVersion(const int formatVersion);
+    static FORMAT_VERSION detectFormatVersion(const ReadOnlyByteArrayView dictBuffer);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(FormatUtils);
+
+    static const size_t DICTIONARY_MINIMUM_SIZE;
+};
+} // namespace latinime
+#endif /* LATINIME_FORMAT_UTILS_H */
diff --git a/native/jni/src/dictionary/utils/mmapped_buffer.cpp b/native/jni/src/dictionary/utils/mmapped_buffer.cpp
new file mode 100644
index 0000000..c5259de
--- /dev/null
+++ b/native/jni/src/dictionary/utils/mmapped_buffer.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/mmapped_buffer.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "dictionary/utils/file_utils.h"
+
+namespace latinime {
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+        const char *const path, const int bufferOffset, const int bufferSize,
+        const bool isUpdatable) {
+    const int mmapFd = open(path, O_RDONLY);
+    if (mmapFd < 0) {
+        AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
+        return nullptr;
+    }
+    const int pagesize = sysconf(_SC_PAGESIZE);
+    const int offset = bufferOffset % pagesize;
+    int alignedOffset = bufferOffset - offset;
+    int alignedSize = bufferSize + offset;
+    const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
+    void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
+            alignedOffset);
+    if (mmappedBuffer == MAP_FAILED) {
+        AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
+        close(mmapFd);
+        return nullptr;
+    }
+    uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
+    if (!buffer) {
+        AKLOGE("DICT: buffer is null");
+        close(mmapFd);
+        return nullptr;
+    }
+    return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
+            mmapFd, isUpdatable));
+}
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+        const char *const path, const bool isUpdatable) {
+    const int fileSize = FileUtils::getFileSize(path);
+    if (fileSize == -1) {
+        return nullptr;
+    } else if (fileSize == 0) {
+        return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
+    } else {
+        return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
+    }
+}
+
+/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
+        const char *const dirPath, const char *const fileName, const bool isUpdatable) {
+    const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
+    char filePath[filePathBufferSize];
+    const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
+            fileName);
+    if (filePathLength >= filePathBufferSize) {
+        return nullptr;
+    }
+    return openBuffer(filePath, isUpdatable);
+}
+
+MmappedBuffer::~MmappedBuffer() {
+    if (mAlignedSize == 0) {
+        return;
+    }
+    int ret = munmap(mMmappedBuffer, mAlignedSize);
+    if (ret != 0) {
+        AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
+    }
+    ret = close(mMmapFd);
+    if (ret != 0) {
+        AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
+    }
+}
+
+} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h b/native/jni/src/dictionary/utils/mmapped_buffer.h
similarity index 100%
rename from native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.h
rename to native/jni/src/dictionary/utils/mmapped_buffer.h
diff --git a/native/jni/src/dictionary/utils/multi_bigram_map.cpp b/native/jni/src/dictionary/utils/multi_bigram_map.cpp
new file mode 100644
index 0000000..e730fff
--- /dev/null
+++ b/native/jni/src/dictionary/utils/multi_bigram_map.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/multi_bigram_map.h"
+
+#include <cstddef>
+#include <unordered_map>
+
+namespace latinime {
+
+// Max number of bigram maps (previous word contexts) to be cached. Increasing this number
+// could improve bigram lookup speed for multi-word suggestions, but at the cost of more memory
+// usage. Also, there are diminishing returns since the most frequently used bigrams are
+// typically near the beginning of the input and are thus the first ones to be cached. Note
+// that these bigrams are reset for each new composing word.
+const size_t MultiBigramMap::MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP = 25;
+
+// Most common previous word contexts currently have 100 bigrams
+const int MultiBigramMap::BigramMap::DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP = 100;
+
+// Look up the bigram probability for the given word pair from the cached bigram maps.
+// Also caches the bigrams if there is space remaining and they have not been cached already.
+int MultiBigramMap::getBigramProbability(
+        const DictionaryStructureWithBufferPolicy *const structurePolicy,
+        const WordIdArrayView prevWordIds, const int nextWordId,
+        const int unigramProbability) {
+    if (prevWordIds.empty() || prevWordIds[0] == NOT_A_WORD_ID) {
+        return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
+    }
+    const auto mapPosition = mBigramMaps.find(prevWordIds[0]);
+    if (mapPosition != mBigramMaps.end()) {
+        return mapPosition->second.getBigramProbability(structurePolicy, nextWordId,
+                unigramProbability);
+    }
+    if (mBigramMaps.size() < MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP) {
+        addBigramsForWord(structurePolicy, prevWordIds);
+        return mBigramMaps[prevWordIds[0]].getBigramProbability(structurePolicy,
+                nextWordId, unigramProbability);
+    }
+    return readBigramProbabilityFromBinaryDictionary(structurePolicy, prevWordIds,
+            nextWordId, unigramProbability);
+}
+
+void MultiBigramMap::BigramMap::init(
+        const DictionaryStructureWithBufferPolicy *const structurePolicy,
+        const WordIdArrayView prevWordIds) {
+    structurePolicy->iterateNgramEntries(prevWordIds, this /* listener */);
+}
+
+int MultiBigramMap::BigramMap::getBigramProbability(
+        const DictionaryStructureWithBufferPolicy *const structurePolicy,
+        const int nextWordId, const int unigramProbability) const {
+    int bigramProbability = NOT_A_PROBABILITY;
+    if (mBloomFilter.isInFilter(nextWordId)) {
+        const auto bigramProbabilityIt = mBigramMap.find(nextWordId);
+        if (bigramProbabilityIt != mBigramMap.end()) {
+            bigramProbability = bigramProbabilityIt->second;
+        }
+    }
+    return structurePolicy->getProbability(unigramProbability, bigramProbability);
+}
+
+void MultiBigramMap::BigramMap::onVisitEntry(const int ngramProbability, const int targetWordId) {
+    if (targetWordId == NOT_A_WORD_ID) {
+        return;
+    }
+    mBigramMap[targetWordId] = ngramProbability;
+    mBloomFilter.setInFilter(targetWordId);
+}
+
+void MultiBigramMap::addBigramsForWord(
+        const DictionaryStructureWithBufferPolicy *const structurePolicy,
+        const WordIdArrayView prevWordIds) {
+    mBigramMaps[prevWordIds[0]].init(structurePolicy, prevWordIds);
+}
+
+int MultiBigramMap::readBigramProbabilityFromBinaryDictionary(
+        const DictionaryStructureWithBufferPolicy *const structurePolicy,
+        const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability) {
+    const int bigramProbability = structurePolicy->getProbabilityOfWord(prevWordIds, nextWordId);
+    if (bigramProbability != NOT_A_PROBABILITY) {
+        return bigramProbability;
+    }
+    return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/multi_bigram_map.h b/native/jni/src/dictionary/utils/multi_bigram_map.h
new file mode 100644
index 0000000..6f23d98
--- /dev/null
+++ b/native/jni/src/dictionary/utils/multi_bigram_map.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_MULTI_BIGRAM_MAP_H
+#define LATINIME_MULTI_BIGRAM_MAP_H
+
+#include <cstddef>
+#include <unordered_map>
+
+#include "defines.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/interface/ngram_listener.h"
+#include "dictionary/utils/binary_dictionary_bigrams_iterator.h"
+#include "dictionary/utils/bloom_filter.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+
+// Class for caching bigram maps for multiple previous word contexts. This is useful since the
+// algorithm needs to look up the set of bigrams for every word pair that occurs in every
+// multi-word suggestion.
+class MultiBigramMap {
+ public:
+    MultiBigramMap() : mBigramMaps() {}
+    ~MultiBigramMap() {}
+
+    // Look up the bigram probability for the given word pair from the cached bigram maps.
+    // Also caches the bigrams if there is space remaining and they have not been cached already.
+    int getBigramProbability(const DictionaryStructureWithBufferPolicy *const structurePolicy,
+            const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability);
+
+    void clear() {
+        mBigramMaps.clear();
+    }
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(MultiBigramMap);
+
+    class BigramMap : public NgramListener {
+     public:
+        BigramMap() : mBigramMap(DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP), mBloomFilter() {}
+        // Copy constructor needed for std::unordered_map.
+        BigramMap(const BigramMap &bigramMap)
+                : mBigramMap(bigramMap.mBigramMap), mBloomFilter(bigramMap.mBloomFilter) {}
+        virtual ~BigramMap() {}
+
+        void init(const DictionaryStructureWithBufferPolicy *const structurePolicy,
+                const WordIdArrayView prevWordIds);
+        int getBigramProbability(
+                const DictionaryStructureWithBufferPolicy *const structurePolicy,
+                const int nextWordId, const int unigramProbability) const;
+        virtual void onVisitEntry(const int ngramProbability, const int targetWordId);
+
+     private:
+        static const int DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP;
+        std::unordered_map<int, int> mBigramMap;
+        BloomFilter mBloomFilter;
+    };
+
+    void addBigramsForWord(const DictionaryStructureWithBufferPolicy *const structurePolicy,
+            const WordIdArrayView prevWordIds);
+
+    int readBigramProbabilityFromBinaryDictionary(
+            const DictionaryStructureWithBufferPolicy *const structurePolicy,
+            const WordIdArrayView prevWordIds, const int nextWordId, const int unigramProbability);
+
+    static const size_t MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP;
+    std::unordered_map<int, BigramMap> mBigramMaps;
+};
+} // namespace latinime
+#endif // LATINIME_MULTI_BIGRAM_MAP_H
diff --git a/native/jni/src/dictionary/utils/probability_utils.cpp b/native/jni/src/dictionary/utils/probability_utils.cpp
new file mode 100644
index 0000000..426a0e7
--- /dev/null
+++ b/native/jni/src/dictionary/utils/probability_utils.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/utils/probability_utils.h"
+
+namespace latinime {
+
+const float ProbabilityUtils::PROBABILITY_ENCODING_SCALER = 8.58923700372f;
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/probability_utils.h b/native/jni/src/dictionary/utils/probability_utils.h
new file mode 100644
index 0000000..2050af1
--- /dev/null
+++ b/native/jni/src/dictionary/utils/probability_utils.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_PROBABILITY_UTILS_H
+#define LATINIME_PROBABILITY_UTILS_H
+
+#include <algorithm>
+#include <cmath>
+
+#include "defines.h"
+
+namespace latinime {
+
+// TODO: Quit using bigram probability to indicate the delta.
+class ProbabilityUtils {
+ public:
+    static AK_FORCE_INLINE int backoff(const int unigramProbability) {
+        return unigramProbability;
+        // For some reason, applying the backoff weight gives bad results in tests. To apply the
+        // backoff weight, we divide the probability by 2, which in our storing format means
+        // decreasing the score by 8.
+        // TODO: figure out what's wrong with this.
+        // return unigramProbability > 8 ?
+        //         unigramProbability - 8 : (0 == unigramProbability ? 0 : 8);
+    }
+
+    static AK_FORCE_INLINE int computeProbabilityForBigram(
+            const int unigramProbability, const int bigramProbability) {
+        // We divide the range [unigramProbability..255] in 16.5 steps - in other words, we want
+        // the unigram probability to be the median value of the 17th step from the top. A value of
+        // 0 for the bigram probability represents the middle of the 16th step from the top,
+        // while a value of 15 represents the middle of the top step.
+        // See makedict.BinaryDictEncoder#makeBigramFlags for details.
+        const float stepSize = static_cast<float>(MAX_PROBABILITY - unigramProbability)
+                / (1.5f + MAX_BIGRAM_ENCODED_PROBABILITY);
+        return unigramProbability
+                + static_cast<int>(static_cast<float>(bigramProbability + 1) * stepSize);
+    }
+
+    // Encode probability using the same way as we are doing for main dictionaries.
+    static AK_FORCE_INLINE int encodeRawProbability(const float rawProbability) {
+        const float probability = static_cast<float>(MAX_PROBABILITY)
+                + log2f(rawProbability) * PROBABILITY_ENCODING_SCALER;
+        if (probability < 0.0f) {
+            return 0;
+        }
+        return std::min(static_cast<int>(probability + 0.5f), MAX_PROBABILITY);
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(ProbabilityUtils);
+
+    static const float PROBABILITY_ENCODING_SCALER;
+};
+}
+#endif /* LATINIME_PROBABILITY_UTILS_H */
diff --git a/native/jni/src/dictionary/utils/sparse_table.cpp b/native/jni/src/dictionary/utils/sparse_table.cpp
new file mode 100644
index 0000000..029329f
--- /dev/null
+++ b/native/jni/src/dictionary/utils/sparse_table.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#include "dictionary/utils/sparse_table.h"
+
+namespace latinime {
+
+const int SparseTable::NOT_EXIST = -1;
+const int SparseTable::INDEX_SIZE = 4;
+
+bool SparseTable::contains(const int id) const {
+    const int readingPos = getPosInIndexTable(id);
+    if (id < 0 || mIndexTableBuffer->getTailPosition() <= readingPos) {
+        return false;
+    }
+    const int index = mIndexTableBuffer->readUint(INDEX_SIZE, readingPos);
+    return index != NOT_EXIST;
+}
+
+uint32_t SparseTable::get(const int id) const {
+    const int indexTableReadingPos = getPosInIndexTable(id);
+    const int index = mIndexTableBuffer->readUint(INDEX_SIZE, indexTableReadingPos);
+    const int contentTableReadingPos = getPosInContentTable(id, index);
+    if (contentTableReadingPos < 0
+            || contentTableReadingPos >= mContentTableBuffer->getTailPosition()) {
+        AKLOGE("contentTableReadingPos(%d) is invalid. id: %d, index: %d",
+                contentTableReadingPos, id, index);
+        return NOT_A_DICT_POS;
+    }
+    const int contentValue = mContentTableBuffer->readUint(mDataSize, contentTableReadingPos);
+    return contentValue == NOT_EXIST ? NOT_A_DICT_POS : contentValue;
+}
+
+bool SparseTable::set(const int id, const uint32_t value) {
+    const int posInIndexTable = getPosInIndexTable(id);
+    // Extends the index table if needed.
+    int tailPos = mIndexTableBuffer->getTailPosition();
+    while (tailPos <= posInIndexTable) {
+        if (!mIndexTableBuffer->writeUintAndAdvancePosition(NOT_EXIST, INDEX_SIZE, &tailPos)) {
+            AKLOGE("cannot extend index table. tailPos: %d to: %d", tailPos, posInIndexTable);
+            return false;
+        }
+    }
+    if (contains(id)) {
+        // The entry is already in the content table.
+        const int index = mIndexTableBuffer->readUint(INDEX_SIZE, posInIndexTable);
+        if (!mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index))) {
+            AKLOGE("cannot update value %d. pos: %d, tailPos: %d, mDataSize: %d", value,
+                    getPosInContentTable(id, index), mContentTableBuffer->getTailPosition(),
+                    mDataSize);
+            return false;
+        }
+        return true;
+    }
+    // The entry is not in the content table.
+    // Create new entry in the content table.
+    const int index = getIndexFromContentTablePos(mContentTableBuffer->getTailPosition());
+    if (!mIndexTableBuffer->writeUint(index, INDEX_SIZE, posInIndexTable)) {
+        AKLOGE("cannot write index %d. pos %d", index, posInIndexTable);
+        return false;
+    }
+    // Write a new block that containing the entry to be set.
+    int writingPos = getPosInContentTable(0 /* id */, index);
+    for (int i = 0; i < mBlockSize; ++i) {
+        if (!mContentTableBuffer->writeUintAndAdvancePosition(NOT_EXIST, mDataSize,
+                &writingPos)) {
+            AKLOGE("cannot write content table to extend. writingPos: %d, tailPos: %d, "
+                    "mDataSize: %d", writingPos, mContentTableBuffer->getTailPosition(), mDataSize);
+            return false;
+        }
+    }
+    return mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index));
+}
+
+int SparseTable::getIndexFromContentTablePos(const int contentTablePos) const {
+    return contentTablePos / mDataSize / mBlockSize;
+}
+
+int SparseTable::getPosInIndexTable(const int id) const {
+    return (id / mBlockSize) * INDEX_SIZE;
+}
+
+int SparseTable::getPosInContentTable(const int id, const int index) const {
+    const int offset = id % mBlockSize;
+    return (index * mBlockSize + offset) * mDataSize;
+}
+
+} // namespace latinime
diff --git a/native/jni/src/dictionary/utils/sparse_table.h b/native/jni/src/dictionary/utils/sparse_table.h
new file mode 100644
index 0000000..bd1190e
--- /dev/null
+++ b/native/jni/src/dictionary/utils/sparse_table.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef LATINIME_SPARSE_TABLE_H
+#define LATINIME_SPARSE_TABLE_H
+
+#include <cstdint>
+
+#include "defines.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+
+// TODO: Support multiple content buffers.
+class SparseTable {
+ public:
+    SparseTable(BufferWithExtendableBuffer *const indexTableBuffer,
+            BufferWithExtendableBuffer *const contentTableBuffer, const int blockSize,
+            const int dataSize)
+            : mIndexTableBuffer(indexTableBuffer), mContentTableBuffer(contentTableBuffer),
+              mBlockSize(blockSize), mDataSize(dataSize) {}
+
+    bool contains(const int id) const;
+
+    uint32_t get(const int id) const;
+
+    bool set(const int id, const uint32_t value);
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTable);
+
+    int getIndexFromContentTablePos(const int contentTablePos) const;
+
+    int getPosInIndexTable(const int id) const;
+
+    int getPosInContentTable(const int id, const int index) const;
+
+    static const int NOT_EXIST;
+    static const int INDEX_SIZE;
+
+    BufferWithExtendableBuffer *const mIndexTableBuffer;
+    BufferWithExtendableBuffer *const mContentTableBuffer;
+    const int mBlockSize;
+    const int mDataSize;
+};
+} // namespace latinime
+#endif /* LATINIME_SPARSE_TABLE_H */
diff --git a/native/jni/src/dictionary/utils/trie_map.cpp b/native/jni/src/dictionary/utils/trie_map.cpp
new file mode 100644
index 0000000..0bef8c7
--- /dev/null
+++ b/native/jni/src/dictionary/utils/trie_map.cpp
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#include "dictionary/utils/trie_map.h"
+
+#include "dictionary/utils/dict_file_writing_utils.h"
+
+namespace latinime {
+
+const int TrieMap::INVALID_INDEX = -1;
+const int TrieMap::FIELD0_SIZE = 4;
+const int TrieMap::FIELD1_SIZE = 3;
+const int TrieMap::ENTRY_SIZE = FIELD0_SIZE + FIELD1_SIZE;
+const uint32_t TrieMap::VALUE_FLAG = 0x400000;
+const uint32_t TrieMap::VALUE_MASK = 0x3FFFFF;
+const uint32_t TrieMap::INVALID_VALUE_IN_KEY_VALUE_ENTRY = VALUE_MASK;
+const uint32_t TrieMap::TERMINAL_LINK_FLAG = 0x800000;
+const uint32_t TrieMap::TERMINAL_LINK_MASK = 0x7FFFFF;
+const int TrieMap::NUM_OF_BITS_USED_FOR_ONE_LEVEL = 5;
+const uint32_t TrieMap::LABEL_MASK = 0x1F;
+const int TrieMap::MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL = 1 << NUM_OF_BITS_USED_FOR_ONE_LEVEL;
+const int TrieMap::ROOT_BITMAP_ENTRY_INDEX = 0;
+const int TrieMap::ROOT_BITMAP_ENTRY_POS = MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL * FIELD0_SIZE;
+const TrieMap::Entry TrieMap::EMPTY_BITMAP_ENTRY = TrieMap::Entry(0, 0);
+const int TrieMap::TERMINAL_LINKED_ENTRY_COUNT = 2; // Value entry and bitmap entry.
+const uint64_t TrieMap::MAX_VALUE =
+        (static_cast<uint64_t>(1) << ((FIELD0_SIZE + FIELD1_SIZE) * CHAR_BIT)) - 1;
+const int TrieMap::MAX_BUFFER_SIZE = TERMINAL_LINK_MASK * ENTRY_SIZE;
+
+TrieMap::TrieMap() : mBuffer(MAX_BUFFER_SIZE) {
+    mBuffer.extend(ROOT_BITMAP_ENTRY_POS);
+    writeEntry(EMPTY_BITMAP_ENTRY, ROOT_BITMAP_ENTRY_INDEX);
+}
+
+TrieMap::TrieMap(const ReadWriteByteArrayView buffer)
+        : mBuffer(buffer, BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
+
+void TrieMap::dump(const int from, const int to) const {
+    AKLOGI("BufSize: %d", mBuffer.getTailPosition());
+    for (int i = from; i < to; ++i) {
+        AKLOGI("Entry[%d]: %x, %x", i, readField0(i), readField1(i));
+    }
+    int unusedRegionSize = 0;
+    for (int i = 1; i <= MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL; ++i) {
+        int index = readEmptyTableLink(i);
+        while (index != ROOT_BITMAP_ENTRY_INDEX) {
+            index = readField0(index);
+            unusedRegionSize += i;
+        }
+    }
+    AKLOGI("Unused Size: %d", unusedRegionSize);
+}
+
+int TrieMap::getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIndex) {
+    const Entry bitmapEntry = readEntry(bitmapEntryIndex);
+    const uint32_t unsignedKey = static_cast<uint32_t>(key);
+    const int terminalEntryIndex = getTerminalEntryIndex(
+            unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntry, 0 /* level */);
+    if (terminalEntryIndex == INVALID_INDEX) {
+        // Not found.
+        return INVALID_INDEX;
+    }
+    const Entry terminalEntry = readEntry(terminalEntryIndex);
+    if (terminalEntry.hasTerminalLink()) {
+        return terminalEntry.getValueEntryIndex() + 1;
+    }
+    // Create a value entry and a bitmap entry.
+    const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
+    if (valueEntryIndex == INVALID_INDEX) {
+        return INVALID_INDEX;
+    }
+    if (!writeEntry(Entry(0, terminalEntry.getValue()), valueEntryIndex)) {
+        return INVALID_INDEX;
+    }
+    if (!writeEntry(EMPTY_BITMAP_ENTRY, valueEntryIndex + 1)) {
+        return INVALID_INDEX;
+    }
+    if (!writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, terminalEntryIndex)) {
+        return INVALID_INDEX;
+    }
+    return valueEntryIndex + 1;
+}
+
+const TrieMap::Result TrieMap::get(const int key, const int bitmapEntryIndex) const {
+    const uint32_t unsignedKey = static_cast<uint32_t>(key);
+    return getInternal(unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntryIndex,
+            0 /* level */);
+}
+
+bool TrieMap::put(const int key, const uint64_t value, const int bitmapEntryIndex) {
+    if (value > MAX_VALUE) {
+        return false;
+    }
+    const uint32_t unsignedKey = static_cast<uint32_t>(key);
+    return putInternal(unsignedKey, value, getBitShuffledKey(unsignedKey), bitmapEntryIndex,
+            readEntry(bitmapEntryIndex), 0 /* level */);
+}
+
+bool TrieMap::save(FILE *const file) const {
+    return DictFileWritingUtils::writeBufferToFileTail(file, &mBuffer);
+}
+
+bool TrieMap::remove(const int key, const int bitmapEntryIndex) {
+    const Entry bitmapEntry = readEntry(bitmapEntryIndex);
+    const uint32_t unsignedKey = static_cast<uint32_t>(key);
+    const int terminalEntryIndex = getTerminalEntryIndex(
+            unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntry, 0 /* level */);
+    if (terminalEntryIndex == INVALID_INDEX) {
+        // Not found.
+        return false;
+    }
+    const Entry terminalEntry = readEntry(terminalEntryIndex);
+    if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , terminalEntryIndex)) {
+        return false;
+    }
+    if (terminalEntry.hasTerminalLink()) {
+        const Entry nextLevelBitmapEntry = readEntry(terminalEntry.getValueEntryIndex() + 1);
+        if (!freeTable(terminalEntry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+            return false;
+        }
+        if (!removeInner(nextLevelBitmapEntry)){
+            return false;
+        }
+    }
+    return true;
+}
+
+/**
+ * Iterate next entry in a certain level.
+ *
+ * @param iterationState the iteration state that will be read and updated in this method.
+ * @param outKey the output key
+ * @return Result instance. mIsValid is false when all entries are iterated.
+ */
+const TrieMap::Result TrieMap::iterateNext(std::vector<TableIterationState> *const iterationState,
+        int *const outKey) const {
+    while (!iterationState->empty()) {
+        TableIterationState &state = iterationState->back();
+        if (state.mTableSize <= state.mCurrentIndex) {
+            // Move to parent.
+            iterationState->pop_back();
+        } else {
+            const int entryIndex = state.mTableIndex + state.mCurrentIndex;
+            state.mCurrentIndex += 1;
+            const Entry entry = readEntry(entryIndex);
+            if (entry.isBitmapEntry()) {
+                // Move to child.
+                iterationState->emplace_back(popCount(entry.getBitmap()), entry.getTableIndex());
+            } else if (entry.isValidTerminalEntry()) {
+                if (outKey) {
+                    *outKey = entry.getKey();
+                }
+                if (!entry.hasTerminalLink()) {
+                    return Result(entry.getValue(), true, INVALID_INDEX);
+                }
+                const int valueEntryIndex = entry.getValueEntryIndex();
+                const Entry valueEntry = readEntry(valueEntryIndex);
+                return Result(valueEntry.getValueOfValueEntry(), true, valueEntryIndex + 1);
+            }
+        }
+    }
+    // Visited all entries.
+    return Result(0, false, INVALID_INDEX);
+}
+
+/**
+ * Shuffle bits of the key in the fixed order.
+ *
+ * This method is used as a hash function. This returns different values for different inputs.
+ */
+uint32_t TrieMap::getBitShuffledKey(const uint32_t key) const {
+    uint32_t shuffledKey = 0;
+    for (int i = 0; i < 4; ++i) {
+        const uint32_t keyPiece = (key >> (i * 8)) & 0xFF;
+        shuffledKey ^= ((keyPiece ^ (keyPiece << 7) ^ (keyPiece << 14) ^ (keyPiece << 21))
+                & 0x11111111) << i;
+    }
+    return shuffledKey;
+}
+
+bool TrieMap::writeValue(const uint64_t value, const int terminalEntryIndex) {
+    if (value < VALUE_MASK) {
+        // Write value into the terminal entry.
+        return writeField1(value | VALUE_FLAG, terminalEntryIndex);
+    }
+    // Create value entry and write value.
+    const int valueEntryIndex = allocateTable(TERMINAL_LINKED_ENTRY_COUNT);
+    if (valueEntryIndex == INVALID_INDEX) {
+        return false;
+    }
+    if (!writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex)) {
+        return false;
+    }
+    if (!writeEntry(EMPTY_BITMAP_ENTRY, valueEntryIndex + 1)) {
+        return false;
+    }
+    return writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, terminalEntryIndex);
+}
+
+bool TrieMap::updateValue(const Entry &terminalEntry, const uint64_t value,
+        const int terminalEntryIndex) {
+    if (!terminalEntry.hasTerminalLink()) {
+        return writeValue(value, terminalEntryIndex);
+    }
+    const int valueEntryIndex = terminalEntry.getValueEntryIndex();
+    return writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex);
+}
+
+bool TrieMap::freeTable(const int tableIndex, const int entryCount) {
+    if (!writeField0(readEmptyTableLink(entryCount), tableIndex)) {
+        return false;
+    }
+    return writeEmptyTableLink(tableIndex, entryCount);
+}
+
+/**
+ * Allocate table with entryCount-entries. Reuse freed table if possible.
+ */
+int TrieMap::allocateTable(const int entryCount) {
+    if (entryCount > 0 && entryCount <= MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL) {
+        const int tableIndex = readEmptyTableLink(entryCount);
+        if (tableIndex > 0) {
+            if (!writeEmptyTableLink(readField0(tableIndex), entryCount)) {
+                return INVALID_INDEX;
+            }
+            // Reuse the table.
+            return tableIndex;
+        }
+    }
+    // Allocate memory space at tail position of the buffer.
+    const int mapIndex = getTailEntryIndex();
+    if (!mBuffer.extend(entryCount * ENTRY_SIZE)) {
+        return INVALID_INDEX;
+    }
+    return mapIndex;
+}
+
+int TrieMap::getTerminalEntryIndex(const uint32_t key, const uint32_t hashedKey,
+        const Entry &bitmapEntry, const int level) const {
+    const int label = getLabel(hashedKey, level);
+    if (!exists(bitmapEntry.getBitmap(), label)) {
+        return INVALID_INDEX;
+    }
+    const int entryIndex = bitmapEntry.getTableIndex() + popCount(bitmapEntry.getBitmap(), label);
+    const Entry entry = readEntry(entryIndex);
+    if (entry.isBitmapEntry()) {
+        // Move to the next level.
+        return getTerminalEntryIndex(key, hashedKey, entry, level + 1);
+    }
+    if (!entry.isValidTerminalEntry()) {
+        return INVALID_INDEX;
+    }
+    if (entry.getKey() == key) {
+        // Terminal entry is found.
+        return entryIndex;
+    }
+    return INVALID_INDEX;
+}
+
+/**
+ * Get Result corresponding to the key.
+ *
+ * @param key the key.
+ * @param hashedKey the hashed key.
+ * @param bitmapEntryIndex the index of bitmap entry
+ * @param level current level
+ * @return Result instance corresponding to the key. mIsValid indicates whether the key is in the
+ * map.
+ */
+const TrieMap::Result TrieMap::getInternal(const uint32_t key, const uint32_t hashedKey,
+        const int bitmapEntryIndex, const int level) const {
+    const int terminalEntryIndex = getTerminalEntryIndex(key, hashedKey,
+            readEntry(bitmapEntryIndex), level);
+    if (terminalEntryIndex == INVALID_INDEX) {
+        // Not found.
+        return Result(0, false, INVALID_INDEX);
+    }
+    const Entry terminalEntry = readEntry(terminalEntryIndex);
+    if (!terminalEntry.hasTerminalLink()) {
+        return Result(terminalEntry.getValue(), true, INVALID_INDEX);
+    }
+    const int valueEntryIndex = terminalEntry.getValueEntryIndex();
+    const Entry valueEntry = readEntry(valueEntryIndex);
+    return Result(valueEntry.getValueOfValueEntry(), true, valueEntryIndex + 1);
+}
+
+/**
+ * Put key to value mapping to the map.
+ *
+ * @param key the key.
+ * @param value the value
+ * @param hashedKey the hashed key.
+ * @param bitmapEntryIndex the index of bitmap entry
+ * @param bitmapEntry the bitmap entry
+ * @param level current level
+ * @return whether the key-value has been correctly inserted to the map or not.
+ */
+bool TrieMap::putInternal(const uint32_t key, const uint64_t value, const uint32_t hashedKey,
+        const int bitmapEntryIndex, const Entry &bitmapEntry, const int level) {
+    const int label = getLabel(hashedKey, level);
+    const uint32_t bitmap = bitmapEntry.getBitmap();
+    const int mapIndex = bitmapEntry.getTableIndex();
+    if (!exists(bitmap, label)) {
+        // Current map doesn't contain the label.
+        return addNewEntryByExpandingTable(key, value, mapIndex, bitmap, bitmapEntryIndex, label);
+    }
+    const int entryIndex = mapIndex + popCount(bitmap, label);
+    const Entry entry = readEntry(entryIndex);
+    if (entry.isBitmapEntry()) {
+        // Bitmap entry is found. Go to the next level.
+        return putInternal(key, value, hashedKey, entryIndex, entry, level + 1);
+    }
+    if (!entry.isValidTerminalEntry()) {
+        // Overwrite invalid terminal entry.
+        return writeTerminalEntry(key, value, entryIndex);
+    }
+    if (entry.getKey() == key) {
+        // Terminal entry for the key is found. Update the value.
+        return updateValue(entry, value, entryIndex);
+    }
+    // Conflict with the existing key.
+    return addNewEntryByResolvingConflict(key, value, hashedKey, entry, entryIndex, level);
+}
+
+/**
+ * Resolve a conflict in the current level and add new entry.
+ *
+ * @param key the key
+ * @param value the value
+ * @param hashedKey the hashed key
+ * @param conflictedEntry the existing conflicted entry
+ * @param conflictedEntryIndex the index of existing conflicted entry
+ * @param level current level
+ * @return whether the key-value has been correctly inserted to the map or not.
+ */
+bool TrieMap::addNewEntryByResolvingConflict(const uint32_t key, const uint64_t value,
+        const uint32_t hashedKey, const Entry &conflictedEntry, const int conflictedEntryIndex,
+        const int level) {
+    const int conflictedKeyNextLabel =
+            getLabel(getBitShuffledKey(conflictedEntry.getKey()), level + 1);
+    const int nextLabel = getLabel(hashedKey, level + 1);
+    if (conflictedKeyNextLabel == nextLabel) {
+        // Conflicted again in the next level.
+        const int newTableIndex = allocateTable(1 /* entryCount */);
+        if (newTableIndex == INVALID_INDEX) {
+            return false;
+        }
+        if (!writeEntry(conflictedEntry, newTableIndex)) {
+            return false;
+        }
+        const Entry newBitmapEntry(setExist(0 /* bitmap */, nextLabel), newTableIndex);
+        if (!writeEntry(newBitmapEntry, conflictedEntryIndex)) {
+            return false;
+        }
+        return putInternal(key, value, hashedKey, conflictedEntryIndex, newBitmapEntry, level + 1);
+    }
+    // The conflict has been resolved. Create a table that contains 2 entries.
+    const int newTableIndex = allocateTable(2 /* entryCount */);
+    if (newTableIndex == INVALID_INDEX) {
+        return false;
+    }
+    if (nextLabel < conflictedKeyNextLabel) {
+        if (!writeTerminalEntry(key, value, newTableIndex)) {
+            return false;
+        }
+        if (!writeEntry(conflictedEntry, newTableIndex + 1)) {
+            return false;
+        }
+    } else { // nextLabel > conflictedKeyNextLabel
+        if (!writeEntry(conflictedEntry, newTableIndex)) {
+            return false;
+        }
+        if (!writeTerminalEntry(key, value, newTableIndex + 1)) {
+            return false;
+        }
+    }
+    const uint32_t updatedBitmap =
+            setExist(setExist(0 /* bitmap */, nextLabel), conflictedKeyNextLabel);
+    return writeEntry(Entry(updatedBitmap, newTableIndex), conflictedEntryIndex);
+}
+
+/**
+ * Add new entry to the existing table.
+ */
+bool TrieMap::addNewEntryByExpandingTable(const uint32_t key, const uint64_t value,
+        const int tableIndex, const uint32_t bitmap, const int bitmapEntryIndex, const int label) {
+    // Current map doesn't contain the label.
+    const int entryCount = popCount(bitmap);
+    const int newTableIndex = allocateTable(entryCount + 1);
+    if (newTableIndex == INVALID_INDEX) {
+        return false;
+    }
+    const int newEntryIndexInTable = popCount(bitmap, label);
+    // Copy from existing table to the new table.
+    for (int i = 0; i < entryCount; ++i) {
+        if (!copyEntry(tableIndex + i, newTableIndex + i + (i >= newEntryIndexInTable ? 1 : 0))) {
+            return false;
+        }
+    }
+    // Write new terminal entry.
+    if (!writeTerminalEntry(key, value, newTableIndex + newEntryIndexInTable)) {
+        return false;
+    }
+    // Update bitmap.
+    if (!writeEntry(Entry(setExist(bitmap, label), newTableIndex), bitmapEntryIndex)) {
+        return false;
+    }
+    if (entryCount > 0) {
+        return freeTable(tableIndex, entryCount);
+    }
+    return true;
+}
+
+bool TrieMap::removeInner(const Entry &bitmapEntry) {
+    const int tableSize = popCount(bitmapEntry.getBitmap());
+    if (tableSize <= 0) {
+        // The table is empty. No need to remove any entries.
+        return true;
+    }
+    for (int i = 0; i < tableSize; ++i) {
+        const int entryIndex = bitmapEntry.getTableIndex() + i;
+        const Entry entry = readEntry(entryIndex);
+        if (entry.isBitmapEntry()) {
+            // Delete next bitmap entry recursively.
+            if (!removeInner(entry)) {
+                return false;
+            }
+        } else {
+            // Invalidate terminal entry just in case.
+            if (!writeField1(VALUE_FLAG ^ INVALID_VALUE_IN_KEY_VALUE_ENTRY , entryIndex)) {
+                return false;
+            }
+            if (entry.hasTerminalLink()) {
+                const Entry nextLevelBitmapEntry = readEntry(entry.getValueEntryIndex() + 1);
+                if (!freeTable(entry.getValueEntryIndex(), TERMINAL_LINKED_ENTRY_COUNT)) {
+                    return false;
+                }
+                if (!removeInner(nextLevelBitmapEntry)) {
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+}  // namespace latinime
diff --git a/native/jni/src/dictionary/utils/trie_map.h b/native/jni/src/dictionary/utils/trie_map.h
new file mode 100644
index 0000000..5fc6c26
--- /dev/null
+++ b/native/jni/src/dictionary/utils/trie_map.h
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_TRIE_MAP_H
+#define LATINIME_TRIE_MAP_H
+
+#include <climits>
+#include <cstdint>
+#include <cstdio>
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+
+/**
+ * Trie map derived from Phil Bagwell's Hash Array Mapped Trie.
+ * key is int and value is uint64_t.
+ * This supports multiple level map. Terminal entries can have a bitmap for the next level map.
+ * This doesn't support root map resizing.
+ */
+class TrieMap {
+ public:
+    struct Result {
+        const uint64_t mValue;
+        const bool mIsValid;
+        const int mNextLevelBitmapEntryIndex;
+
+        Result(const uint64_t value, const bool isValid, const int nextLevelBitmapEntryIndex)
+                : mValue(value), mIsValid(isValid),
+                  mNextLevelBitmapEntryIndex(nextLevelBitmapEntryIndex) {}
+    };
+
+    /**
+     * Struct to record iteration state in a table.
+     */
+    struct TableIterationState {
+        int mTableSize;
+        int mTableIndex;
+        int mCurrentIndex;
+
+        TableIterationState(const int tableSize, const int tableIndex)
+                : mTableSize(tableSize), mTableIndex(tableIndex), mCurrentIndex(0) {}
+    };
+
+    class TrieMapRange;
+    class TrieMapIterator {
+     public:
+        class IterationResult {
+         public:
+            IterationResult(const TrieMap *const trieMap, const int key, const uint64_t value,
+                    const int nextLeveBitmapEntryIndex)
+                    : mTrieMap(trieMap), mKey(key), mValue(value),
+                      mNextLevelBitmapEntryIndex(nextLeveBitmapEntryIndex) {}
+
+            const TrieMapRange getEntriesInNextLevel() const {
+                return TrieMapRange(mTrieMap, mNextLevelBitmapEntryIndex);
+            }
+
+            bool hasNextLevelMap() const {
+                return mNextLevelBitmapEntryIndex != INVALID_INDEX;
+            }
+
+            AK_FORCE_INLINE int key() const {
+                return mKey;
+            }
+
+            AK_FORCE_INLINE uint64_t value() const {
+                return mValue;
+            }
+
+            AK_FORCE_INLINE int getNextLevelBitmapEntryIndex() const {
+                return mNextLevelBitmapEntryIndex;
+            }
+
+         private:
+            const TrieMap *const mTrieMap;
+            const int mKey;
+            const uint64_t mValue;
+            const int mNextLevelBitmapEntryIndex;
+        };
+
+        TrieMapIterator(const TrieMap *const trieMap, const int bitmapEntryIndex)
+                : mTrieMap(trieMap), mStateStack(), mBaseBitmapEntryIndex(bitmapEntryIndex),
+                  mKey(0), mValue(0), mIsValid(false), mNextLevelBitmapEntryIndex(INVALID_INDEX) {
+            if (!trieMap || mBaseBitmapEntryIndex == INVALID_INDEX) {
+                return;
+            }
+            const Entry bitmapEntry = mTrieMap->readEntry(mBaseBitmapEntryIndex);
+            mStateStack.emplace_back(
+                    mTrieMap->popCount(bitmapEntry.getBitmap()), bitmapEntry.getTableIndex());
+            this->operator++();
+        }
+
+        const IterationResult operator*() const {
+            return IterationResult(mTrieMap, mKey, mValue, mNextLevelBitmapEntryIndex);
+        }
+
+        bool operator!=(const TrieMapIterator &other) const {
+            // Caveat: This works only for for loops.
+            return mIsValid || other.mIsValid;
+        }
+
+        const TrieMapIterator &operator++() {
+            const Result result = mTrieMap->iterateNext(&mStateStack, &mKey);
+            mValue = result.mValue;
+            mIsValid = result.mIsValid;
+            mNextLevelBitmapEntryIndex = result.mNextLevelBitmapEntryIndex;
+            return *this;
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(TrieMapIterator);
+        DISALLOW_ASSIGNMENT_OPERATOR(TrieMapIterator);
+
+        const TrieMap *const mTrieMap;
+        std::vector<TrieMap::TableIterationState> mStateStack;
+        const int mBaseBitmapEntryIndex;
+        int mKey;
+        uint64_t mValue;
+        bool mIsValid;
+        int mNextLevelBitmapEntryIndex;
+    };
+
+    /**
+     * Class to support iterating entries in TrieMap by range base for loops.
+     */
+    class TrieMapRange {
+     public:
+        TrieMapRange(const TrieMap *const trieMap, const int bitmapEntryIndex)
+                : mTrieMap(trieMap), mBaseBitmapEntryIndex(bitmapEntryIndex) {};
+
+        TrieMapIterator begin() const {
+            return TrieMapIterator(mTrieMap, mBaseBitmapEntryIndex);
+        }
+
+        const TrieMapIterator end() const {
+            return TrieMapIterator(nullptr, INVALID_INDEX);
+        }
+
+     private:
+        DISALLOW_DEFAULT_CONSTRUCTOR(TrieMapRange);
+        DISALLOW_ASSIGNMENT_OPERATOR(TrieMapRange);
+
+        const TrieMap *const mTrieMap;
+        const int mBaseBitmapEntryIndex;
+    };
+
+    static const int INVALID_INDEX;
+    static const uint64_t MAX_VALUE;
+
+    TrieMap();
+    // Construct TrieMap using existing data in the memory region written by save().
+    TrieMap(const ReadWriteByteArrayView buffer);
+    void dump(const int from = 0, const int to = 0) const;
+
+    bool isNearSizeLimit() const {
+        return mBuffer.isNearSizeLimit();
+    }
+
+    int getRootBitmapEntryIndex() const {
+        return ROOT_BITMAP_ENTRY_INDEX;
+    }
+
+    // Returns bitmapEntryIndex. Create the next level map if it doesn't exist.
+    int getNextLevelBitmapEntryIndex(const int key) {
+        return getNextLevelBitmapEntryIndex(key, ROOT_BITMAP_ENTRY_INDEX);
+    }
+
+    int getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIndex);
+
+    const Result getRoot(const int key) const {
+        return get(key, ROOT_BITMAP_ENTRY_INDEX);
+    }
+
+    const Result get(const int key, const int bitmapEntryIndex) const;
+
+    bool putRoot(const int key, const uint64_t value) {
+        return put(key, value, ROOT_BITMAP_ENTRY_INDEX);
+    }
+
+    bool put(const int key, const uint64_t value, const int bitmapEntryIndex);
+
+    const TrieMapRange getEntriesInRootLevel() const {
+        return getEntriesInSpecifiedLevel(ROOT_BITMAP_ENTRY_INDEX);
+    }
+
+    const TrieMapRange getEntriesInSpecifiedLevel(const int bitmapEntryIndex) const {
+        return TrieMapRange(this, bitmapEntryIndex);
+    }
+
+    bool save(FILE *const file) const;
+
+    bool remove(const int key, const int bitmapEntryIndex);
+
+ private:
+    DISALLOW_COPY_AND_ASSIGN(TrieMap);
+
+    /**
+     * Struct represents an entry.
+     *
+     * Entry is one of these entry types. All entries are fixed size and have 2 fields FIELD_0 and
+     * FIELD_1.
+     * 1. bitmap entry. bitmap entry contains bitmap and the link to hash table.
+     *   FIELD_0(bitmap) FIELD_1(LINK_TO_HASH_TABLE)
+     * 2. terminal entry. terminal entry contains hashed key and value or terminal link. terminal
+     * entry have terminal link when the value is not fit to FIELD_1 or there is a next level map
+     * for the key.
+     *   FIELD_0(hashed key) (FIELD_1(VALUE_FLAG VALUE) | FIELD_1(TERMINAL_LINK_FLAG TERMINAL_LINK))
+     * 3. value entry. value entry represents a value. Upper order bytes are stored in FIELD_0 and
+     * lower order bytes are stored in FIELD_1.
+     *   FIELD_0(value (upper order bytes)) FIELD_1(value (lower order bytes))
+     */
+    struct Entry {
+        const uint32_t mData0;
+        const uint32_t mData1;
+
+        Entry(const uint32_t data0, const uint32_t data1) : mData0(data0), mData1(data1) {}
+
+        AK_FORCE_INLINE bool isBitmapEntry() const {
+            return (mData1 & VALUE_FLAG) == 0 && (mData1 & TERMINAL_LINK_FLAG) == 0;
+        }
+
+        AK_FORCE_INLINE bool hasTerminalLink() const {
+            return (mData1 & TERMINAL_LINK_FLAG) != 0;
+        }
+
+        // For terminal entry.
+        AK_FORCE_INLINE uint32_t getKey() const {
+            return mData0;
+        }
+
+        // For terminal entry.
+        AK_FORCE_INLINE uint32_t getValue() const {
+            return mData1 & VALUE_MASK;
+        }
+
+        // For terminal entry.
+        AK_FORCE_INLINE bool isValidTerminalEntry() const {
+            return hasTerminalLink() || ((mData1 & VALUE_MASK) != INVALID_VALUE_IN_KEY_VALUE_ENTRY);
+        }
+
+        // For terminal entry.
+        AK_FORCE_INLINE uint32_t getValueEntryIndex() const {
+            return mData1 & TERMINAL_LINK_MASK;
+        }
+
+        // For bitmap entry.
+        AK_FORCE_INLINE uint32_t getBitmap() const {
+            return mData0;
+        }
+
+        // For bitmap entry.
+        AK_FORCE_INLINE int getTableIndex() const {
+            return static_cast<int>(mData1);
+        }
+
+        // For value entry.
+        AK_FORCE_INLINE uint64_t getValueOfValueEntry() const {
+            return ((static_cast<uint64_t>(mData0) << (FIELD1_SIZE * CHAR_BIT)) ^ mData1);
+        }
+    };
+
+    BufferWithExtendableBuffer mBuffer;
+
+    static const int FIELD0_SIZE;
+    static const int FIELD1_SIZE;
+    static const int ENTRY_SIZE;
+    static const uint32_t VALUE_FLAG;
+    static const uint32_t VALUE_MASK;
+    static const uint32_t INVALID_VALUE_IN_KEY_VALUE_ENTRY;
+    static const uint32_t TERMINAL_LINK_FLAG;
+    static const uint32_t TERMINAL_LINK_MASK;
+    static const int NUM_OF_BITS_USED_FOR_ONE_LEVEL;
+    static const uint32_t LABEL_MASK;
+    static const int MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL;
+    static const int ROOT_BITMAP_ENTRY_INDEX;
+    static const int ROOT_BITMAP_ENTRY_POS;
+    static const Entry EMPTY_BITMAP_ENTRY;
+    static const int TERMINAL_LINKED_ENTRY_COUNT;
+    static const int MAX_BUFFER_SIZE;
+
+    uint32_t getBitShuffledKey(const uint32_t key) const;
+    bool writeValue(const uint64_t value, const int terminalEntryIndex);
+    bool updateValue(const Entry &terminalEntry, const uint64_t value,
+            const int terminalEntryIndex);
+    bool freeTable(const int tableIndex, const int entryCount);
+    int allocateTable(const int entryCount);
+    int getTerminalEntryIndex(const uint32_t key, const uint32_t hashedKey,
+            const Entry &bitmapEntry, const int level) const;
+    const Result getInternal(const uint32_t key, const uint32_t hashedKey,
+            const int bitmapEntryIndex, const int level) const;
+    bool putInternal(const uint32_t key, const uint64_t value, const uint32_t hashedKey,
+            const int bitmapEntryIndex, const Entry &bitmapEntry, const int level);
+    bool addNewEntryByResolvingConflict(const uint32_t key, const uint64_t value,
+            const uint32_t hashedKey, const Entry &conflictedEntry, const int conflictedEntryIndex,
+            const int level);
+    bool addNewEntryByExpandingTable(const uint32_t key, const uint64_t value,
+            const int tableIndex, const uint32_t bitmap, const int bitmapEntryIndex,
+            const int label);
+    const Result iterateNext(std::vector<TableIterationState> *const iterationState,
+            int *const outKey) const;
+
+    AK_FORCE_INLINE const Entry readEntry(const int entryIndex) const {
+        return Entry(readField0(entryIndex), readField1(entryIndex));
+    }
+
+    // Returns whether an entry for the index is existing by testing if the index-th bit in the
+    // bitmap is set or not.
+    AK_FORCE_INLINE bool exists(const uint32_t bitmap, const int index) const {
+        return (bitmap & (1 << index)) != 0;
+    }
+
+    // Set index-th bit in the bitmap.
+    AK_FORCE_INLINE uint32_t setExist(const uint32_t bitmap, const int index) const {
+        return bitmap | (1 << index);
+    }
+
+    // Count set bits before index in the bitmap.
+    AK_FORCE_INLINE int popCount(const uint32_t bitmap, const int index) const {
+        return popCount(bitmap & ((1 << index) - 1));
+    }
+
+    // Count set bits in the bitmap.
+    AK_FORCE_INLINE int popCount(const uint32_t bitmap) const {
+        return __builtin_popcount(bitmap);
+        // int v = bitmap - ((bitmap >> 1) & 0x55555555);
+        // v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
+        // return (((v + (v >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+    }
+
+    AK_FORCE_INLINE int getLabel(const uint32_t hashedKey, const int level) const {
+        return (hashedKey >> (level * NUM_OF_BITS_USED_FOR_ONE_LEVEL)) & LABEL_MASK;
+    }
+
+    AK_FORCE_INLINE uint32_t readField0(const int entryIndex) const {
+        return mBuffer.readUint(FIELD0_SIZE, ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE);
+    }
+
+    AK_FORCE_INLINE uint32_t readField1(const int entryIndex) const {
+        return mBuffer.readUint(FIELD1_SIZE,
+                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE + FIELD0_SIZE);
+    }
+
+    AK_FORCE_INLINE int readEmptyTableLink(const int entryCount) const {
+        return mBuffer.readUint(FIELD1_SIZE, (entryCount - 1) * FIELD1_SIZE);
+    }
+
+    AK_FORCE_INLINE bool writeEmptyTableLink(const int tableIndex, const int entryCount) {
+        return mBuffer.writeUint(tableIndex, FIELD1_SIZE, (entryCount - 1) * FIELD1_SIZE);
+    }
+
+    AK_FORCE_INLINE bool writeField0(const uint32_t data, const int entryIndex) {
+        return mBuffer.writeUint(data, FIELD0_SIZE,
+                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE);
+    }
+
+    AK_FORCE_INLINE bool writeField1(const uint32_t data, const int entryIndex) {
+        return mBuffer.writeUint(data, FIELD1_SIZE,
+                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE + FIELD0_SIZE);
+    }
+
+    AK_FORCE_INLINE bool writeEntry(const Entry &entry, const int entryIndex) {
+        return writeField0(entry.mData0, entryIndex) && writeField1(entry.mData1, entryIndex);
+    }
+
+    AK_FORCE_INLINE bool writeTerminalEntry(const uint32_t key, const uint64_t value,
+            const int entryIndex) {
+        return writeField0(key, entryIndex) && writeValue(value, entryIndex);
+    }
+
+    AK_FORCE_INLINE bool copyEntry(const int originalEntryIndex, const int newEntryIndex) {
+        return writeEntry(readEntry(originalEntryIndex), newEntryIndex);
+    }
+
+    AK_FORCE_INLINE int getTailEntryIndex() const {
+        return (mBuffer.getTailPosition() - ROOT_BITMAP_ENTRY_POS) / ENTRY_SIZE;
+    }
+
+    bool removeInner(const Entry &bitmapEntry);
+};
+
+} // namespace latinime
+#endif /* LATINIME_TRIE_MAP_H */
diff --git a/native/jni/src/suggest/core/dicnode/dic_node.h b/native/jni/src/suggest/core/dicnode/dic_node.h
index d1b2c87..5214077 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node.h
@@ -26,6 +26,7 @@
 #include "suggest/core/dictionary/error_type_utils.h"
 #include "suggest/core/layout/proximity_info_state.h"
 #include "utils/char_utils.h"
+#include "utils/int_array_view.h"
 
 #if DEBUG_DICT
 #define LOGI_SHOW_ADD_COST_PROP \
@@ -103,10 +104,10 @@
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
     }
 
-    // Init for root with prevWordsPtNodePos which is used for n-gram
-    void initAsRoot(const int rootPtNodeArrayPos, const int *const prevWordsPtNodePos) {
+    // Init for root with prevWordIds which is used for n-gram
+    void initAsRoot(const int rootPtNodeArrayPos, const WordIdArrayView prevWordIds) {
         mIsCachedForNextSuggestion = false;
-        mDicNodeProperties.init(rootPtNodeArrayPos, prevWordsPtNodePos);
+        mDicNodeProperties.init(rootPtNodeArrayPos, prevWordIds);
         mDicNodeState.init();
         PROF_NODE_RESET(mProfiler);
     }
@@ -114,12 +115,11 @@
     // Init for root with previous word
     void initAsRootWithPreviousWord(const DicNode *const dicNode, const int rootPtNodeArrayPos) {
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
-        int newPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        newPrevWordsPtNodePos[0] = dicNode->mDicNodeProperties.getPtNodePos();
-        for (size_t i = 1; i < NELEMS(newPrevWordsPtNodePos); ++i) {
-            newPrevWordsPtNodePos[i] = dicNode->getPrevWordsTerminalPtNodePos()[i - 1];
-        }
-        mDicNodeProperties.init(rootPtNodeArrayPos, newPrevWordsPtNodePos);
+        WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> newPrevWordIds;
+        newPrevWordIds[0] = dicNode->mDicNodeProperties.getWordId();
+        dicNode->getPrevWordIds().limit(newPrevWordIds.size() - 1)
+                .copyToArray(&newPrevWordIds, 1 /* offset */);
+        mDicNodeProperties.init(rootPtNodeArrayPos, WordIdArrayView::fromArray(newPrevWordIds));
         mDicNodeState.initAsRootWithPreviousWord(&dicNode->mDicNodeState,
                 dicNode->mDicNodeProperties.getDepth());
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
@@ -135,19 +135,16 @@
         PROF_NODE_COPY(&parentDicNode->mProfiler, mProfiler);
     }
 
-    void initAsChild(const DicNode *const dicNode, const int ptNodePos,
-            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
-            const bool hasChildren, const bool isBlacklistedOrNotAWord,
-            const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
+    void initAsChild(const DicNode *const dicNode, const int childrenPtNodeArrayPos,
+            const int wordId, const CodePointArrayView mergedCodePoints) {
         uint16_t newDepth = static_cast<uint16_t>(dicNode->getNodeCodePointCount() + 1);
         mIsCachedForNextSuggestion = dicNode->mIsCachedForNextSuggestion;
         const uint16_t newLeavingDepth = static_cast<uint16_t>(
-                dicNode->mDicNodeProperties.getLeavingDepth() + mergedNodeCodePointCount);
-        mDicNodeProperties.init(ptNodePos, childrenPtNodeArrayPos, mergedNodeCodePoints[0],
-                probability, isTerminal, hasChildren, isBlacklistedOrNotAWord, newDepth,
-                newLeavingDepth, dicNode->mDicNodeProperties.getPrevWordsTerminalPtNodePos());
-        mDicNodeState.init(&dicNode->mDicNodeState, mergedNodeCodePointCount,
-                mergedNodeCodePoints);
+                dicNode->mDicNodeProperties.getLeavingDepth() + mergedCodePoints.size());
+        mDicNodeProperties.init(childrenPtNodeArrayPos, mergedCodePoints[0],
+                wordId, newDepth, newLeavingDepth, dicNode->mDicNodeProperties.getPrevWordIds());
+        mDicNodeState.init(&dicNode->mDicNodeState, mergedCodePoints.size(),
+                mergedCodePoints.data());
         PROF_NODE_COPY(&dicNode->mProfiler, mProfiler);
     }
 
@@ -179,9 +176,6 @@
     // Check if the current word and the previous word can be considered as a valid multiple word
     // suggestion.
     bool isValidMultipleWordSuggestion() const {
-        if (isBlacklistedOrNotAWord()) {
-            return false;
-        }
         // Treat suggestion as invalid if the current and the previous word are single character
         // words.
         const int prevWordLen = mDicNodeState.mDicNodeStateOutput.getPrevWordsLength()
@@ -204,13 +198,12 @@
     }
 
     // Used to get n-gram probability in DicNodeUtils.
-    int getPtNodePos() const {
-        return mDicNodeProperties.getPtNodePos();
+    int getWordId() const {
+        return mDicNodeProperties.getWordId();
     }
 
-    // TODO: Use view class to return PtNodePos array.
-    const int *getPrevWordsTerminalPtNodePos() const {
-        return mDicNodeProperties.getPrevWordsTerminalPtNodePos();
+    const WordIdArrayView getPrevWordIds() const {
+        return mDicNodeProperties.getPrevWordIds();
     }
 
     // Used in DicNodeUtils
@@ -218,10 +211,6 @@
         return mDicNodeProperties.getChildrenPtNodeArrayPos();
     }
 
-    int getProbability() const {
-        return mDicNodeProperties.getProbability();
-    }
-
     AK_FORCE_INLINE bool isTerminalDicNode() const {
         const bool isTerminalPtNode = mDicNodeProperties.isTerminal();
         const int currentDicNodeDepth = getNodeCodePointCount();
@@ -306,8 +295,9 @@
     }
 
     // Used to prune nodes
-    float getCompoundDistance(const float languageWeight) const {
-        return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(languageWeight);
+    float getCompoundDistance(const float weightOfLangModelVsSpatialModel) const {
+        return mDicNodeState.mDicNodeStateScoring.getCompoundDistance(
+                weightOfLangModelVsSpatialModel);
     }
 
     AK_FORCE_INLINE const int *getOutputWordBuf() const {
@@ -404,10 +394,6 @@
         return mDicNodeState.mDicNodeStateScoring.getContainedErrorTypes();
     }
 
-    bool isBlacklistedOrNotAWord() const {
-        return mDicNodeProperties.isBlacklistedOrNotAWord();
-    }
-
     inline uint16_t getNodeCodePointCount() const {
         return mDicNodeProperties.getDepth();
     }
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
index 69ea674..a20252c 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.cpp
@@ -16,10 +16,9 @@
 
 #include "suggest/core/dicnode/dic_node_utils.h"
 
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/core/dictionary/multi_bigram_map.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 
 namespace latinime {
 
@@ -29,8 +28,8 @@
 
 /* static */ void DicNodeUtils::initAsRoot(
         const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-        const int *const prevWordsPtNodePos, DicNode *const newRootDicNode) {
-    newRootDicNode->initAsRoot(dictionaryStructurePolicy->getRootPosition(), prevWordsPtNodePos);
+        const WordIdArrayView prevWordIds, DicNode *const newRootDicNode) {
+    newRootDicNode->initAsRoot(dictionaryStructurePolicy->getRootPosition(), prevWordIds);
 }
 
 /*static */ void DicNodeUtils::initAsRootWithPreviousWord(
@@ -73,25 +72,17 @@
     if (dicNode->hasMultipleWords() && !dicNode->isValidMultipleWordSuggestion()) {
         return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
     }
-    const int probability = getBigramNodeProbability(dictionaryStructurePolicy, dicNode,
-            multiBigramMap);
+    const WordAttributes wordAttributes = dictionaryStructurePolicy->getWordAttributesInContext(
+            dicNode->getPrevWordIds(), dicNode->getWordId(), multiBigramMap);
+    if (wordAttributes.getProbability() == NOT_A_PROBABILITY
+            || (dicNode->hasMultipleWords()
+                    && (wordAttributes.isBlacklisted() || wordAttributes.isNotAWord()))) {
+        return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
+    }
     // TODO: This equation to calculate the improbability looks unreasonable.  Investigate this.
-    const float cost = static_cast<float>(MAX_PROBABILITY - probability)
+    const float cost = static_cast<float>(MAX_PROBABILITY - wordAttributes.getProbability())
             / static_cast<float>(MAX_PROBABILITY);
     return cost;
 }
 
-/* static */ int DicNodeUtils::getBigramNodeProbability(
-        const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-        const DicNode *const dicNode, MultiBigramMap *const multiBigramMap) {
-    const int unigramProbability = dicNode->getProbability();
-    if (multiBigramMap) {
-        const int *const prevWordsPtNodePos = dicNode->getPrevWordsTerminalPtNodePos();
-        return multiBigramMap->getBigramProbability(dictionaryStructurePolicy,
-                prevWordsPtNodePos, dicNode->getPtNodePos(), unigramProbability);
-    }
-    return dictionaryStructurePolicy->getProbability(unigramProbability,
-            NOT_A_PROBABILITY);
-}
-
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_utils.h b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
index 00e80c6..b891a84 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_utils.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_utils.h
@@ -18,6 +18,7 @@
 #define LATINIME_DIC_NODE_UTILS_H
 
 #include "defines.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -30,7 +31,7 @@
  public:
     static void initAsRoot(
             const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-            const int *const prevWordPtNodePos, DicNode *const newRootDicNode);
+            const WordIdArrayView prevWordIds, DicNode *const newRootDicNode);
     static void initAsRootWithPreviousWord(
             const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
             const DicNode *const prevWordLastDicNode, DicNode *const newRootDicNode);
@@ -46,10 +47,6 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(DicNodeUtils);
     // Max number of bigrams to look up
     static const int MAX_BIGRAMS_CONSIDERED_PER_CONTEXT = 500;
-
-    static int getBigramNodeProbability(
-            const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-            const DicNode *const dicNode, MultiBigramMap *const multiBigramMap);
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_UTILS_H
diff --git a/native/jni/src/suggest/core/dicnode/dic_node_vector.h b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
index 54cde19..e6b7589 100644
--- a/native/jni/src/suggest/core/dicnode/dic_node_vector.h
+++ b/native/jni/src/suggest/core/dicnode/dic_node_vector.h
@@ -21,6 +21,7 @@
 
 #include "defines.h"
 #include "suggest/core/dicnode/dic_node.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -58,15 +59,11 @@
         mDicNodes.back().initAsPassingChild(dicNode);
     }
 
-    void pushLeavingChild(const DicNode *const dicNode, const int ptNodePos,
-            const int childrenPtNodeArrayPos, const int probability, const bool isTerminal,
-            const bool hasChildren, const bool isBlacklistedOrNotAWord,
-            const uint16_t mergedNodeCodePointCount, const int *const mergedNodeCodePoints) {
+    void pushLeavingChild(const DicNode *const dicNode, const int childrenPtNodeArrayPos,
+            const int wordId, const CodePointArrayView mergedCodePoints) {
         ASSERT(!mLock);
         mDicNodes.emplace_back();
-        mDicNodes.back().initAsChild(dicNode, ptNodePos, childrenPtNodeArrayPos, probability,
-                isTerminal, hasChildren, isBlacklistedOrNotAWord, mergedNodeCodePointCount,
-                mergedNodeCodePoints);
+        mDicNodes.back().initAsChild(dicNode, childrenPtNodeArrayPos, wordId, mergedCodePoints);
     }
 
     DicNode *operator[](const int id) {
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
index 8202176..1b796b5 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_properties.h
@@ -18,8 +18,10 @@
 #define LATINIME_DIC_NODE_PROPERTIES_H
 
 #include <cstdint>
+#include <cstdlib>
 
 #include "defines.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -29,84 +31,61 @@
 class DicNodeProperties {
  public:
     AK_FORCE_INLINE DicNodeProperties()
-            : mPtNodePos(NOT_A_DICT_POS), mChildrenPtNodeArrayPos(NOT_A_DICT_POS),
-              mProbability(NOT_A_PROBABILITY), mDicNodeCodePoint(NOT_A_CODE_POINT),
-              mIsTerminal(false), mHasChildrenPtNodes(false),
-              mIsBlacklistedOrNotAWord(false), mDepth(0), mLeavingDepth(0) {}
+            : mChildrenPtNodeArrayPos(NOT_A_DICT_POS), mDicNodeCodePoint(NOT_A_CODE_POINT),
+              mWordId(NOT_A_WORD_ID), mDepth(0), mLeavingDepth(0), mPrevWordCount(0) {}
 
     ~DicNodeProperties() {}
 
     // Should be called only once per DicNode is initialized.
-    void init(const int pos, const int childrenPos, const int nodeCodePoint, const int probability,
-            const bool isTerminal, const bool hasChildren, const bool isBlacklistedOrNotAWord,
-            const uint16_t depth, const uint16_t leavingDepth, const int *const prevWordsNodePos) {
-        mPtNodePos = pos;
+    void init(const int childrenPos, const int nodeCodePoint, const int wordId,
+            const uint16_t depth, const uint16_t leavingDepth, const WordIdArrayView prevWordIds) {
         mChildrenPtNodeArrayPos = childrenPos;
         mDicNodeCodePoint = nodeCodePoint;
-        mProbability = probability;
-        mIsTerminal = isTerminal;
-        mHasChildrenPtNodes = hasChildren;
-        mIsBlacklistedOrNotAWord = isBlacklistedOrNotAWord;
+        mWordId = wordId;
         mDepth = depth;
         mLeavingDepth = leavingDepth;
-        memmove(mPrevWordsTerminalPtNodePos, prevWordsNodePos, sizeof(mPrevWordsTerminalPtNodePos));
+        prevWordIds.copyToArray(&mPrevWordIds, 0 /* offset */);
+        mPrevWordCount = prevWordIds.size();
     }
 
     // Init for root with prevWordsPtNodePos which is used for n-gram
-    void init(const int rootPtNodeArrayPos, const int *const prevWordsNodePos) {
-        mPtNodePos = NOT_A_DICT_POS;
+    void init(const int rootPtNodeArrayPos, const WordIdArrayView prevWordIds) {
         mChildrenPtNodeArrayPos = rootPtNodeArrayPos;
         mDicNodeCodePoint = NOT_A_CODE_POINT;
-        mProbability = NOT_A_PROBABILITY;
-        mIsTerminal = false;
-        mHasChildrenPtNodes = true;
-        mIsBlacklistedOrNotAWord = false;
+        mWordId = NOT_A_WORD_ID;
         mDepth = 0;
         mLeavingDepth = 0;
-        memmove(mPrevWordsTerminalPtNodePos, prevWordsNodePos, sizeof(mPrevWordsTerminalPtNodePos));
+        prevWordIds.copyToArray(&mPrevWordIds, 0 /* offset */);
+        mPrevWordCount = prevWordIds.size();
     }
 
     void initByCopy(const DicNodeProperties *const dicNodeProp) {
-        mPtNodePos = dicNodeProp->mPtNodePos;
         mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
         mDicNodeCodePoint = dicNodeProp->mDicNodeCodePoint;
-        mProbability = dicNodeProp->mProbability;
-        mIsTerminal = dicNodeProp->mIsTerminal;
-        mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
-        mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
+        mWordId = dicNodeProp->mWordId;
         mDepth = dicNodeProp->mDepth;
         mLeavingDepth = dicNodeProp->mLeavingDepth;
-        memmove(mPrevWordsTerminalPtNodePos, dicNodeProp->mPrevWordsTerminalPtNodePos,
-                sizeof(mPrevWordsTerminalPtNodePos));
+        const WordIdArrayView prevWordIdArrayView = dicNodeProp->getPrevWordIds();
+        prevWordIdArrayView.copyToArray(&mPrevWordIds, 0 /* offset */);
+        mPrevWordCount = prevWordIdArrayView.size();
     }
 
     // Init as passing child
     void init(const DicNodeProperties *const dicNodeProp, const int codePoint) {
-        mPtNodePos = dicNodeProp->mPtNodePos;
         mChildrenPtNodeArrayPos = dicNodeProp->mChildrenPtNodeArrayPos;
         mDicNodeCodePoint = codePoint; // Overwrite the node char of a passing child
-        mProbability = dicNodeProp->mProbability;
-        mIsTerminal = dicNodeProp->mIsTerminal;
-        mHasChildrenPtNodes = dicNodeProp->mHasChildrenPtNodes;
-        mIsBlacklistedOrNotAWord = dicNodeProp->mIsBlacklistedOrNotAWord;
+        mWordId = dicNodeProp->mWordId;
         mDepth = dicNodeProp->mDepth + 1; // Increment the depth of a passing child
         mLeavingDepth = dicNodeProp->mLeavingDepth;
-        memmove(mPrevWordsTerminalPtNodePos, dicNodeProp->mPrevWordsTerminalPtNodePos,
-                sizeof(mPrevWordsTerminalPtNodePos));
-    }
-
-    int getPtNodePos() const {
-        return mPtNodePos;
+        const WordIdArrayView prevWordIdArrayView = dicNodeProp->getPrevWordIds();
+        prevWordIdArrayView.copyToArray(&mPrevWordIds, 0 /* offset */);
+        mPrevWordCount = prevWordIdArrayView.size();
     }
 
     int getChildrenPtNodeArrayPos() const {
         return mChildrenPtNodeArrayPos;
     }
 
-    int getProbability() const {
-        return mProbability;
-    }
-
     int getDicNodeCodePoint() const {
         return mDicNodeCodePoint;
     }
@@ -121,35 +100,32 @@
     }
 
     bool isTerminal() const {
-        return mIsTerminal;
+        return mWordId != NOT_A_WORD_ID;
     }
 
     bool hasChildren() const {
-        return mHasChildrenPtNodes || mDepth != mLeavingDepth;
+        return (mChildrenPtNodeArrayPos != NOT_A_DICT_POS) || mDepth != mLeavingDepth;
     }
 
-    bool isBlacklistedOrNotAWord() const {
-        return mIsBlacklistedOrNotAWord;
+    const WordIdArrayView getPrevWordIds() const {
+        return WordIdArrayView::fromArray(mPrevWordIds).limit(mPrevWordCount);
     }
 
-    const int *getPrevWordsTerminalPtNodePos() const {
-        return mPrevWordsTerminalPtNodePos;
+    int getWordId() const {
+        return mWordId;
     }
 
  private:
     // Caution!!!
     // Use a default copy constructor and an assign operator because shallow copies are ok
     // for this class
-    int mPtNodePos;
     int mChildrenPtNodeArrayPos;
-    int mProbability;
     int mDicNodeCodePoint;
-    bool mIsTerminal;
-    bool mHasChildrenPtNodes;
-    bool mIsBlacklistedOrNotAWord;
+    int mWordId;
     uint16_t mDepth;
     uint16_t mLeavingDepth;
-    int mPrevWordsTerminalPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> mPrevWordIds;
+    size_t mPrevWordCount;
 };
 } // namespace latinime
 #endif // LATINIME_DIC_NODE_PROPERTIES_H
diff --git a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
index c19d48e..3a54c25 100644
--- a/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
+++ b/native/jni/src/suggest/core/dicnode/internal/dic_node_state_scoring.h
@@ -103,8 +103,10 @@
         return getCompoundDistance(1.0f);
     }
 
-    float getCompoundDistance(const float languageWeight) const {
-        return mSpatialDistance + mLanguageDistance * languageWeight;
+    float getCompoundDistance(
+            const float weightOfLangModelVsSpatialModel) const {
+        return mSpatialDistance
+                + mLanguageDistance * weightOfLangModelVsSpatialModel;
     }
 
     float getNormalizedCompoundDistance() const {
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h
deleted file mode 100644
index 178b065..0000000
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_bigrams_iterator.h
+++ /dev/null
@@ -1,69 +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.
- */
-
-#ifndef LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
-#define LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-
-namespace latinime {
-
-class BinaryDictionaryBigramsIterator {
- public:
-    // Empty iterator.
-    BinaryDictionaryBigramsIterator()
-           : mBigramsStructurePolicy(nullptr), mPos(NOT_A_DICT_POS),
-             mBigramPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY), mHasNext(false) {}
-
-    BinaryDictionaryBigramsIterator(
-            const DictionaryBigramsStructurePolicy *const bigramsStructurePolicy, const int pos)
-            : mBigramsStructurePolicy(bigramsStructurePolicy), mPos(pos),
-              mBigramPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY),
-              mHasNext(pos != NOT_A_DICT_POS) {}
-
-    BinaryDictionaryBigramsIterator(BinaryDictionaryBigramsIterator &&bigramsIterator)
-            : mBigramsStructurePolicy(bigramsIterator.mBigramsStructurePolicy),
-              mPos(bigramsIterator.mPos), mBigramPos(bigramsIterator.mBigramPos),
-              mProbability(bigramsIterator.mProbability), mHasNext(bigramsIterator.mHasNext) {}
-
-    AK_FORCE_INLINE bool hasNext() const {
-        return mHasNext;
-    }
-
-    AK_FORCE_INLINE void next() {
-        mBigramsStructurePolicy->getNextBigram(&mBigramPos, &mProbability, &mHasNext, &mPos);
-    }
-
-    AK_FORCE_INLINE int getProbability() const {
-        return mProbability;
-    }
-
-    AK_FORCE_INLINE int getBigramPos() const {
-        return mBigramPos;
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(BinaryDictionaryBigramsIterator);
-
-    const DictionaryBigramsStructurePolicy *const mBigramsStructurePolicy;
-    int mPos;
-    int mBigramPos;
-    int mProbability;
-    bool mHasNext;
-};
-} // namespace latinime
-#endif // LATINIME_BINARY_DICTIONARY_BIGRAMS_ITERATOR_H
diff --git a/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h b/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h
deleted file mode 100644
index 558e0a5..0000000
--- a/native/jni/src/suggest/core/dictionary/binary_dictionary_shortcut_iterator.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
-#define LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-
-namespace latinime {
-
-class BinaryDictionaryShortcutIterator {
- public:
-    BinaryDictionaryShortcutIterator(
-            const DictionaryShortcutsStructurePolicy *const shortcutStructurePolicy,
-            const int shortcutPos)
-            : mShortcutStructurePolicy(shortcutStructurePolicy),
-              mPos(shortcutStructurePolicy->getStartPos(shortcutPos)),
-              mHasNextShortcutTarget(shortcutPos != NOT_A_DICT_POS) {}
-
-    AK_FORCE_INLINE bool hasNextShortcutTarget() const {
-        return mHasNextShortcutTarget;
-    }
-
-    // Gets the shortcut target itself as an int string and put it to outTarget, put its length
-    // to outTargetLength, put whether it is whitelist to outIsWhitelist.
-    AK_FORCE_INLINE void nextShortcutTarget(
-            const int maxDepth, int *const outTarget, int *const outTargetLength,
-            bool *const outIsWhitelist) {
-        mShortcutStructurePolicy->getNextShortcut(maxDepth, outTarget, outTargetLength,
-                outIsWhitelist, &mHasNextShortcutTarget, &mPos);
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryDictionaryShortcutIterator);
-
-    const DictionaryShortcutsStructurePolicy *const mShortcutStructurePolicy;
-    int mPos;
-    bool mHasNextShortcutTarget;
-};
-} // namespace latinime
-#endif // LATINIME_BINARY_DICTIONARY_SHORTCUT_ITERATOR_H
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp
index d625739..5c9a139 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp
@@ -19,15 +19,16 @@
 #include "suggest/core/dictionary/dictionary.h"
 
 #include "defines.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/property/ngram_context.h"
 #include "suggest/core/dictionary/dictionary_utils.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
 #include "suggest/core/result/suggestion_results.h"
 #include "suggest/core/session/dic_traverse_session.h"
-#include "suggest/core/session/prev_words_info.h"
 #include "suggest/core/suggest.h"
 #include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
 #include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
+#include "utils/int_array_view.h"
 #include "utils/log_utils.h"
 #include "utils/time_keeper.h"
 
@@ -45,88 +46,87 @@
 
 void Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
         int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
-        int inputSize, const PrevWordsInfo *const prevWordsInfo,
-        const SuggestOptions *const suggestOptions, const float languageWeight,
+        int inputSize, const NgramContext *const ngramContext,
+        const SuggestOptions *const suggestOptions, const float weightOfLangModelVsSpatialModel,
         SuggestionResults *const outSuggestionResults) const {
     TimeKeeper::setCurrentTime();
-    traverseSession->init(this, prevWordsInfo, suggestOptions);
+    traverseSession->init(this, ngramContext, suggestOptions);
     const auto &suggest = suggestOptions->isGesture() ? mGestureSuggest : mTypingSuggest;
     suggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
             ycoordinates, times, pointerIds, inputCodePoints, inputSize,
-            languageWeight, outSuggestionResults);
-    if (DEBUG_DICT) {
-        outSuggestionResults->dumpSuggestions();
-    }
+            weightOfLangModelVsSpatialModel, outSuggestionResults);
 }
 
 Dictionary::NgramListenerForPrediction::NgramListenerForPrediction(
-        const PrevWordsInfo *const prevWordsInfo, SuggestionResults *const suggestionResults,
+        const NgramContext *const ngramContext, const WordIdArrayView prevWordIds,
+        SuggestionResults *const suggestionResults,
         const DictionaryStructureWithBufferPolicy *const dictStructurePolicy)
-    : mPrevWordsInfo(prevWordsInfo), mSuggestionResults(suggestionResults),
-      mDictStructurePolicy(dictStructurePolicy) {}
+    : mNgramContext(ngramContext), mPrevWordIds(prevWordIds),
+      mSuggestionResults(suggestionResults), mDictStructurePolicy(dictStructurePolicy) {}
 
 void Dictionary::NgramListenerForPrediction::onVisitEntry(const int ngramProbability,
-        const int targetPtNodePos) {
-    if (targetPtNodePos == NOT_A_DICT_POS) {
+        const int targetWordId) {
+    if (targetWordId == NOT_A_WORD_ID) {
         return;
     }
-    if (mPrevWordsInfo->isNthPrevWordBeginningOfSentence(1 /* n */)
+    if (mNgramContext->isNthPrevWordBeginningOfSentence(1 /* n */)
             && ngramProbability == NOT_A_PROBABILITY) {
         return;
     }
     int targetWordCodePoints[MAX_WORD_LENGTH];
-    int unigramProbability = 0;
-    const int codePointCount = mDictStructurePolicy->
-            getCodePointsAndProbabilityAndReturnCodePointCount(targetPtNodePos,
-                    MAX_WORD_LENGTH, targetWordCodePoints, &unigramProbability);
+    const int codePointCount = mDictStructurePolicy->getCodePointsAndReturnCodePointCount(
+            targetWordId, MAX_WORD_LENGTH, targetWordCodePoints);
     if (codePointCount <= 0) {
         return;
     }
-    const int probability = mDictStructurePolicy->getProbability(
-            unigramProbability, ngramProbability);
-    mSuggestionResults->addPrediction(targetWordCodePoints, codePointCount, probability);
+    const WordAttributes wordAttributes = mDictStructurePolicy->getWordAttributesInContext(
+            mPrevWordIds, targetWordId, nullptr /* multiBigramMap */);
+    if (wordAttributes.getProbability() == NOT_A_PROBABILITY) {
+        return;
+    }
+    mSuggestionResults->addPrediction(targetWordCodePoints, codePointCount,
+            wordAttributes.getProbability());
 }
 
-void Dictionary::getPredictions(const PrevWordsInfo *const prevWordsInfo,
+void Dictionary::getPredictions(const NgramContext *const ngramContext,
         SuggestionResults *const outSuggestionResults) const {
     TimeKeeper::setCurrentTime();
-    NgramListenerForPrediction listener(prevWordsInfo, outSuggestionResults,
-            mDictionaryStructureWithBufferPolicy.get());
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(
-            mDictionaryStructureWithBufferPolicy.get(), prevWordsPtNodePos,
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(
+            mDictionaryStructureWithBufferPolicy.get(), &prevWordIdArray,
             true /* tryLowerCaseSearch */);
-    mDictionaryStructureWithBufferPolicy->iterateNgramEntries(prevWordsPtNodePos, &listener);
+    NgramListenerForPrediction listener(ngramContext, prevWordIds, outSuggestionResults,
+            mDictionaryStructureWithBufferPolicy.get());
+    mDictionaryStructureWithBufferPolicy->iterateNgramEntries(prevWordIds, &listener);
 }
 
-int Dictionary::getProbability(const int *word, int length) const {
-    return getNgramProbability(nullptr /* prevWordsInfo */, word, length);
+int Dictionary::getProbability(const CodePointArrayView codePoints) const {
+    return getNgramProbability(nullptr /* ngramContext */, codePoints);
 }
 
-int Dictionary::getMaxProbabilityOfExactMatches(const int *word, int length) const {
+int Dictionary::getMaxProbabilityOfExactMatches(const CodePointArrayView codePoints) const {
     TimeKeeper::setCurrentTime();
     return DictionaryUtils::getMaxProbabilityOfExactMatches(
-            mDictionaryStructureWithBufferPolicy.get(), word, length);
+            mDictionaryStructureWithBufferPolicy.get(), codePoints);
 }
 
-int Dictionary::getNgramProbability(const PrevWordsInfo *const prevWordsInfo, const int *word,
-        int length) const {
+int Dictionary::getNgramProbability(const NgramContext *const ngramContext,
+        const CodePointArrayView codePoints) const {
     TimeKeeper::setCurrentTime();
-    int nextWordPos = mDictionaryStructureWithBufferPolicy->getTerminalPtNodePositionOfWord(word,
-            length, false /* forceLowerCaseSearch */);
-    if (NOT_A_DICT_POS == nextWordPos) return NOT_A_PROBABILITY;
-    if (!prevWordsInfo) {
-        return getDictionaryStructurePolicy()->getProbabilityOfPtNode(
-                nullptr /* prevWordsPtNodePos */, nextWordPos);
+    const int wordId = mDictionaryStructureWithBufferPolicy->getWordId(codePoints,
+            false /* forceLowerCaseSearch */);
+    if (wordId == NOT_A_WORD_ID) return NOT_A_PROBABILITY;
+    if (!ngramContext) {
+        return getDictionaryStructurePolicy()->getProbabilityOfWord(WordIdArrayView(), wordId);
     }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(
-            mDictionaryStructureWithBufferPolicy.get(), prevWordsPtNodePos,
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = ngramContext->getPrevWordIds(
+            mDictionaryStructureWithBufferPolicy.get(), &prevWordIdArray,
             true /* tryLowerCaseSearch */);
-    return getDictionaryStructurePolicy()->getProbabilityOfPtNode(prevWordsPtNodePos, nextWordPos);
+    return getDictionaryStructurePolicy()->getProbabilityOfWord(prevWordIds, wordId);
 }
 
-bool Dictionary::addUnigramEntry(const int *const word, const int length,
+bool Dictionary::addUnigramEntry(const CodePointArrayView codePoints,
         const UnigramProperty *const unigramProperty) {
     if (unigramProperty->representsBeginningOfSentence()
             && !mDictionaryStructureWithBufferPolicy->getHeaderStructurePolicy()
@@ -135,24 +135,31 @@
         return false;
     }
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->addUnigramEntry(word, length, unigramProperty);
+    return mDictionaryStructureWithBufferPolicy->addUnigramEntry(codePoints, unigramProperty);
 }
 
-bool Dictionary::removeUnigramEntry(const int *const codePoints, const int codePointCount) {
+bool Dictionary::removeUnigramEntry(const CodePointArrayView codePoints) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->removeUnigramEntry(codePoints, codePointCount);
+    return mDictionaryStructureWithBufferPolicy->removeUnigramEntry(codePoints);
 }
 
-bool Dictionary::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const BigramProperty *const bigramProperty) {
+bool Dictionary::addNgramEntry(const NgramProperty *const ngramProperty) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->addNgramEntry(prevWordsInfo, bigramProperty);
+    return mDictionaryStructureWithBufferPolicy->addNgramEntry(ngramProperty);
 }
 
-bool Dictionary::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const int *const word, const int length) {
+bool Dictionary::removeNgramEntry(const NgramContext *const ngramContext,
+        const CodePointArrayView codePoints) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->removeNgramEntry(prevWordsInfo, word, length);
+    return mDictionaryStructureWithBufferPolicy->removeNgramEntry(ngramContext, codePoints);
+}
+
+bool Dictionary::updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+        const CodePointArrayView codePoints, const bool isValidWord,
+        const HistoricalInfo historicalInfo) {
+    TimeKeeper::setCurrentTime();
+    return mDictionaryStructureWithBufferPolicy->updateEntriesForWordWithNgramContext(ngramContext,
+            codePoints, isValidWord, historicalInfo);
 }
 
 bool Dictionary::flush(const char *const filePath) {
@@ -177,11 +184,9 @@
             maxResultLength);
 }
 
-const WordProperty Dictionary::getWordProperty(const int *const codePoints,
-        const int codePointCount) {
+const WordProperty Dictionary::getWordProperty(const CodePointArrayView codePoints) {
     TimeKeeper::setCurrentTime();
-    return mDictionaryStructureWithBufferPolicy->getWordProperty(
-            codePoints, codePointCount);
+    return mDictionaryStructureWithBufferPolicy->getWordProperty(codePoints);
 }
 
 int Dictionary::getNextWordAndNextToken(const int token, int *const outCodePoints,
diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h
index 732d3b1..9e224eb 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary.h
@@ -21,17 +21,19 @@
 
 #include "defines.h"
 #include "jni.h"
-#include "suggest/core/dictionary/ngram_listener.h"
-#include "suggest/core/dictionary/property/word_property.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/interface/ngram_listener.h"
+#include "dictionary/property/historical_info.h"
+#include "dictionary/property/word_property.h"
 #include "suggest/core/suggest_interface.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
 class DictionaryStructureWithBufferPolicy;
 class DicTraverseSession;
-class PrevWordsInfo;
+class NgramContext;
 class ProximityInfo;
 class SuggestionResults;
 class SuggestOptions;
@@ -58,36 +60,40 @@
     static const int KIND_FLAG_POSSIBLY_OFFENSIVE = 0x80000000;
     static const int KIND_FLAG_EXACT_MATCH = 0x40000000;
     static const int KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION = 0x20000000;
+    static const int KIND_FLAG_APPROPRIATE_FOR_AUTOCORRECTION = 0x10000000;
 
     Dictionary(JNIEnv *env, DictionaryStructureWithBufferPolicy::StructurePolicyPtr
             dictionaryStructureWithBufferPolicy);
 
     void getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
             int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
-            int inputSize, const PrevWordsInfo *const prevWordsInfo,
-            const SuggestOptions *const suggestOptions, const float languageWeight,
+            int inputSize, const NgramContext *const ngramContext,
+            const SuggestOptions *const suggestOptions, const float weightOfLangModelVsSpatialModel,
             SuggestionResults *const outSuggestionResults) const;
 
-    void getPredictions(const PrevWordsInfo *const prevWordsInfo,
+    void getPredictions(const NgramContext *const ngramContext,
             SuggestionResults *const outSuggestionResults) const;
 
-    int getProbability(const int *word, int length) const;
+    int getProbability(const CodePointArrayView codePoints) const;
 
-    int getMaxProbabilityOfExactMatches(const int *word, int length) const;
+    int getMaxProbabilityOfExactMatches(const CodePointArrayView codePoints) const;
 
-    int getNgramProbability(const PrevWordsInfo *const prevWordsInfo,
-            const int *word, int length) const;
+    int getNgramProbability(const NgramContext *const ngramContext,
+            const CodePointArrayView codePoints) const;
 
-    bool addUnigramEntry(const int *const codePoints, const int codePointCount,
+    bool addUnigramEntry(const CodePointArrayView codePoints,
             const UnigramProperty *const unigramProperty);
 
-    bool removeUnigramEntry(const int *const codePoints, const int codePointCount);
+    bool removeUnigramEntry(const CodePointArrayView codePoints);
 
-    bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const BigramProperty *const bigramProperty);
+    bool addNgramEntry(const NgramProperty *const ngramProperty);
 
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word,
-            const int length);
+    bool removeNgramEntry(const NgramContext *const ngramContext,
+            const CodePointArrayView codePoints);
+
+    bool updateEntriesForWordWithNgramContext(const NgramContext *const ngramContext,
+            const CodePointArrayView codePoints, const bool isValidWord,
+            const HistoricalInfo historicalInfo);
 
     bool flush(const char *const filePath);
 
@@ -98,7 +104,7 @@
     void getProperty(const char *const query, const int queryLength, char *const outResult,
             const int maxResultLength);
 
-    const WordProperty getWordProperty(const int *const codePoints, const int codePointCount);
+    const WordProperty getWordProperty(const CodePointArrayView codePoints);
 
     // Method to iterate all words in the dictionary.
     // The returned token has to be used to get the next word. If token is 0, this method newly
@@ -117,15 +123,16 @@
 
     class NgramListenerForPrediction : public NgramListener {
      public:
-        NgramListenerForPrediction(const PrevWordsInfo *const prevWordsInfo,
-                SuggestionResults *const suggestionResults,
+        NgramListenerForPrediction(const NgramContext *const ngramContext,
+                const WordIdArrayView prevWordIds, SuggestionResults *const suggestionResults,
                 const DictionaryStructureWithBufferPolicy *const dictStructurePolicy);
-        virtual void onVisitEntry(const int ngramProbability, const int targetPtNodePos);
+        virtual void onVisitEntry(const int ngramProbability, const int targetWordId);
 
      private:
         DISALLOW_IMPLICIT_CONSTRUCTORS(NgramListenerForPrediction);
 
-        const PrevWordsInfo *const mPrevWordsInfo;
+        const NgramContext *const mNgramContext;
+        const WordIdArrayView mPrevWordIds;
         SuggestionResults *const mSuggestionResults;
         const DictionaryStructureWithBufferPolicy *const mDictStructurePolicy;
     };
diff --git a/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp b/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
index b94966c..7de5500 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/dictionary_utils.cpp
@@ -16,39 +16,40 @@
 
 #include "suggest/core/dictionary/dictionary_utils.h"
 
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/property/ngram_context.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_priority_queue.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
 #include "suggest/core/dictionary/dictionary.h"
 #include "suggest/core/dictionary/digraph_utils.h"
-#include "suggest/core/session/prev_words_info.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
 /* static */ int DictionaryUtils::getMaxProbabilityOfExactMatches(
         const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-        const int *const codePoints, const int codePointCount) {
+        const CodePointArrayView codePoints) {
     std::vector<DicNode> current;
     std::vector<DicNode> next;
 
-    // No prev words information.
-    PrevWordsInfo emptyPrevWordsInfo;
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    emptyPrevWordsInfo.getPrevWordsTerminalPtNodePos(dictionaryStructurePolicy,
-            prevWordsPtNodePos, false /* tryLowerCaseSearch */);
+    // No ngram context.
+    NgramContext emptyNgramContext;
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> prevWordIdArray;
+    const WordIdArrayView prevWordIds = emptyNgramContext.getPrevWordIds(
+            dictionaryStructurePolicy, &prevWordIdArray, false /* tryLowerCaseSearch */);
     current.emplace_back();
-    DicNodeUtils::initAsRoot(dictionaryStructurePolicy, prevWordsPtNodePos, &current.front());
-    for (int i = 0; i < codePointCount; ++i) {
+    DicNodeUtils::initAsRoot(dictionaryStructurePolicy, prevWordIds, &current.front());
+    for (const int codePoint : codePoints) {
         // The base-lower input is used to ignore case errors and accent errors.
-        const int codePoint = CharUtils::toBaseLowerCase(codePoints[i]);
+        const int baseLowerCodePoint = CharUtils::toBaseLowerCase(codePoint);
         for (const DicNode &dicNode : current) {
-            if (dicNode.isInDigraph() && dicNode.getNodeCodePoint() == codePoint) {
+            if (dicNode.isInDigraph() && dicNode.getNodeCodePoint() == baseLowerCodePoint) {
                 next.emplace_back(dicNode);
                 next.back().advanceDigraphIndex();
                 continue;
             }
-            processChildDicNodes(dictionaryStructurePolicy, codePoint, &dicNode, &next);
+            processChildDicNodes(dictionaryStructurePolicy, baseLowerCodePoint, &dicNode, &next);
         }
         current.clear();
         current.swap(next);
@@ -59,8 +60,11 @@
         if (!dicNode.isTerminalDicNode()) {
             continue;
         }
+        const WordAttributes wordAttributes =
+                dictionaryStructurePolicy->getWordAttributesInContext(dicNode.getPrevWordIds(),
+                        dicNode.getWordId(), nullptr /* multiBigramMap */);
         // dicNode can contain case errors, accent errors, intentional omissions or digraphs.
-        maxProbability = std::max(maxProbability, dicNode.getProbability());
+        maxProbability = std::max(maxProbability, wordAttributes.getProbability());
     }
     return maxProbability;
 }
diff --git a/native/jni/src/suggest/core/dictionary/dictionary_utils.h b/native/jni/src/suggest/core/dictionary/dictionary_utils.h
index 358ebf6..4dd21c9 100644
--- a/native/jni/src/suggest/core/dictionary/dictionary_utils.h
+++ b/native/jni/src/suggest/core/dictionary/dictionary_utils.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "defines.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -30,7 +31,7 @@
  public:
     static int getMaxProbabilityOfExactMatches(
             const DictionaryStructureWithBufferPolicy *const dictionaryStructurePolicy,
-            const int *const codePoints, const int codePointCount);
+            const CodePointArrayView codePoints);
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryUtils);
diff --git a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
index bb2ce50..4d68f62 100644
--- a/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/digraph_utils.cpp
@@ -19,7 +19,7 @@
 #include <cstdlib>
 
 #include "defines.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
 #include "utils/char_utils.h"
 
 namespace latinime {
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
index b6bf7a9..61093e1 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.cpp
@@ -19,17 +19,20 @@
 namespace latinime {
 
 const ErrorTypeUtils::ErrorType ErrorTypeUtils::NOT_AN_ERROR = 0x0;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_CASE_ERROR = 0x1;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR = 0x2;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x4;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x8;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x10;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x20;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x40;
-const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_CASE = 0x1;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT = 0x2;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_MISSING_EXPLICIT_ACCENT = 0x4;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT = 0x8;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::MATCH_WITH_DIGRAPH = 0x10;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::INTENTIONAL_OMISSION = 0x20;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::EDIT_CORRECTION = 0x40;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::PROXIMITY_CORRECTION = 0x80;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::COMPLETION = 0x100;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::NEW_WORD = 0x200;
 
 const ErrorTypeUtils::ErrorType ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH =
-        NOT_AN_ERROR | MATCH_WITH_CASE_ERROR | MATCH_WITH_ACCENT_ERROR | MATCH_WITH_DIGRAPH;
+        NOT_AN_ERROR | MATCH_WITH_WRONG_CASE | MATCH_WITH_MISSING_ACCENT | MATCH_WITH_DIGRAPH;
+const ErrorTypeUtils::ErrorType ErrorTypeUtils::ERRORS_TREATED_AS_A_PERFECT_MATCH = NOT_AN_ERROR;
 
 const ErrorTypeUtils::ErrorType
         ErrorTypeUtils::ERRORS_TREATED_AS_AN_EXACT_MATCH_WITH_INTENTIONAL_OMISSION =
diff --git a/native/jni/src/suggest/core/dictionary/error_type_utils.h b/native/jni/src/suggest/core/dictionary/error_type_utils.h
index e3e76b2..75111ba 100644
--- a/native/jni/src/suggest/core/dictionary/error_type_utils.h
+++ b/native/jni/src/suggest/core/dictionary/error_type_utils.h
@@ -30,8 +30,10 @@
     typedef uint32_t ErrorType;
 
     static const ErrorType NOT_AN_ERROR;
-    static const ErrorType MATCH_WITH_CASE_ERROR;
-    static const ErrorType MATCH_WITH_ACCENT_ERROR;
+    static const ErrorType MATCH_WITH_WRONG_CASE;
+    static const ErrorType MATCH_WITH_MISSING_ACCENT;
+    static const ErrorType MATCH_WITH_MISSING_EXPLICIT_ACCENT;
+    static const ErrorType MATCH_WITH_WRONG_ACCENT;
     static const ErrorType MATCH_WITH_DIGRAPH;
     // Treat error as an intentional omission when the CorrectionType is omission and the node can
     // be intentional omission.
@@ -51,11 +53,19 @@
         return (containedErrorTypes & ~ERRORS_TREATED_AS_AN_EXACT_MATCH) == 0;
     }
 
+    static bool isPerfectMatch(const ErrorType containedErrorTypes) {
+        return (containedErrorTypes & ~ERRORS_TREATED_AS_A_PERFECT_MATCH) == 0;
+    }
+
     static bool isExactMatchWithIntentionalOmission(const ErrorType containedErrorTypes) {
         return (containedErrorTypes
                 & ~ERRORS_TREATED_AS_AN_EXACT_MATCH_WITH_INTENTIONAL_OMISSION) == 0;
     }
 
+    static bool isMissingExplicitAccent(const ErrorType errorType) {
+        return (errorType & MATCH_WITH_MISSING_EXPLICIT_ACCENT) != 0;
+    }
+
     static bool isEditCorrectionError(const ErrorType errorType) {
         return (errorType & EDIT_CORRECTION) != 0;
     }
@@ -72,6 +82,7 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(ErrorTypeUtils);
 
     static const ErrorType ERRORS_TREATED_AS_AN_EXACT_MATCH;
+    static const ErrorType ERRORS_TREATED_AS_A_PERFECT_MATCH;
     static const ErrorType ERRORS_TREATED_AS_AN_EXACT_MATCH_WITH_INTENTIONAL_OMISSION;
 };
 } // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp b/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
deleted file mode 100644
index 91f33a8..0000000
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.cpp
+++ /dev/null
@@ -1,107 +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.
- */
-
-#include "suggest/core/dictionary/multi_bigram_map.h"
-
-#include <cstddef>
-#include <unordered_map>
-
-namespace latinime {
-
-// Max number of bigram maps (previous word contexts) to be cached. Increasing this number
-// could improve bigram lookup speed for multi-word suggestions, but at the cost of more memory
-// usage. Also, there are diminishing returns since the most frequently used bigrams are
-// typically near the beginning of the input and are thus the first ones to be cached. Note
-// that these bigrams are reset for each new composing word.
-const size_t MultiBigramMap::MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP = 25;
-
-// Most common previous word contexts currently have 100 bigrams
-const int MultiBigramMap::BigramMap::DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP = 100;
-
-// Look up the bigram probability for the given word pair from the cached bigram maps.
-// Also caches the bigrams if there is space remaining and they have not been cached already.
-int MultiBigramMap::getBigramProbability(
-        const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordsPtNodePos, const int nextWordPosition,
-        const int unigramProbability) {
-    if (!prevWordsPtNodePos || prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
-        return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
-    }
-    std::unordered_map<int, BigramMap>::const_iterator mapPosition =
-            mBigramMaps.find(prevWordsPtNodePos[0]);
-    if (mapPosition != mBigramMaps.end()) {
-        return mapPosition->second.getBigramProbability(structurePolicy, nextWordPosition,
-                unigramProbability);
-    }
-    if (mBigramMaps.size() < MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP) {
-        addBigramsForWordPosition(structurePolicy, prevWordsPtNodePos);
-        return mBigramMaps[prevWordsPtNodePos[0]].getBigramProbability(structurePolicy,
-                nextWordPosition, unigramProbability);
-    }
-    return readBigramProbabilityFromBinaryDictionary(structurePolicy, prevWordsPtNodePos,
-            nextWordPosition, unigramProbability);
-}
-
-void MultiBigramMap::BigramMap::init(
-        const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordsPtNodePos) {
-    structurePolicy->iterateNgramEntries(prevWordsPtNodePos, this /* listener */);
-}
-
-int MultiBigramMap::BigramMap::getBigramProbability(
-        const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int nextWordPosition, const int unigramProbability) const {
-    int bigramProbability = NOT_A_PROBABILITY;
-    if (mBloomFilter.isInFilter(nextWordPosition)) {
-        const std::unordered_map<int, int>::const_iterator bigramProbabilityIt =
-                mBigramMap.find(nextWordPosition);
-        if (bigramProbabilityIt != mBigramMap.end()) {
-            bigramProbability = bigramProbabilityIt->second;
-        }
-    }
-    return structurePolicy->getProbability(unigramProbability, bigramProbability);
-}
-
-void MultiBigramMap::BigramMap::onVisitEntry(const int ngramProbability,
-        const int targetPtNodePos) {
-    if (targetPtNodePos == NOT_A_DICT_POS) {
-        return;
-    }
-    mBigramMap[targetPtNodePos] = ngramProbability;
-    mBloomFilter.setInFilter(targetPtNodePos);
-}
-
-void MultiBigramMap::addBigramsForWordPosition(
-        const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordsPtNodePos) {
-    if (prevWordsPtNodePos) {
-        mBigramMaps[prevWordsPtNodePos[0]].init(structurePolicy, prevWordsPtNodePos);
-    }
-}
-
-int MultiBigramMap::readBigramProbabilityFromBinaryDictionary(
-        const DictionaryStructureWithBufferPolicy *const structurePolicy,
-        const int *const prevWordsPtNodePos, const int nextWordPosition,
-        const int unigramProbability) {
-    const int bigramProbability = structurePolicy->getProbabilityOfPtNode(prevWordsPtNodePos,
-            nextWordPosition);
-    if (bigramProbability != NOT_A_PROBABILITY) {
-        return bigramProbability;
-    }
-    return structurePolicy->getProbability(unigramProbability, NOT_A_PROBABILITY);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h b/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
deleted file mode 100644
index ad36dde..0000000
--- a/native/jni/src/suggest/core/dictionary/multi_bigram_map.h
+++ /dev/null
@@ -1,86 +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.
- */
-
-#ifndef LATINIME_MULTI_BIGRAM_MAP_H
-#define LATINIME_MULTI_BIGRAM_MAP_H
-
-#include <cstddef>
-#include <unordered_map>
-
-#include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
-#include "suggest/core/dictionary/bloom_filter.h"
-#include "suggest/core/dictionary/ngram_listener.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-
-namespace latinime {
-
-// Class for caching bigram maps for multiple previous word contexts. This is useful since the
-// algorithm needs to look up the set of bigrams for every word pair that occurs in every
-// multi-word suggestion.
-class MultiBigramMap {
- public:
-    MultiBigramMap() : mBigramMaps() {}
-    ~MultiBigramMap() {}
-
-    // Look up the bigram probability for the given word pair from the cached bigram maps.
-    // Also caches the bigrams if there is space remaining and they have not been cached already.
-    int getBigramProbability(const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordsPtNodePos, const int nextWordPosition,
-            const int unigramProbability);
-
-    void clear() {
-        mBigramMaps.clear();
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(MultiBigramMap);
-
-    class BigramMap : public NgramListener {
-     public:
-        BigramMap() : mBigramMap(DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP), mBloomFilter() {}
-        // Copy constructor needed for std::unordered_map.
-        BigramMap(const BigramMap &bigramMap)
-                : mBigramMap(bigramMap.mBigramMap), mBloomFilter(bigramMap.mBloomFilter) {}
-        virtual ~BigramMap() {}
-
-        void init(const DictionaryStructureWithBufferPolicy *const structurePolicy,
-                const int *const prevWordsPtNodePos);
-        int getBigramProbability(
-                const DictionaryStructureWithBufferPolicy *const structurePolicy,
-                const int nextWordPosition, const int unigramProbability) const;
-        virtual void onVisitEntry(const int ngramProbability, const int targetPtNodePos);
-
-     private:
-        static const int DEFAULT_HASH_MAP_SIZE_FOR_EACH_BIGRAM_MAP;
-        std::unordered_map<int, int> mBigramMap;
-        BloomFilter mBloomFilter;
-    };
-
-    void addBigramsForWordPosition(
-            const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordsPtNodePos);
-
-    int readBigramProbabilityFromBinaryDictionary(
-            const DictionaryStructureWithBufferPolicy *const structurePolicy,
-            const int *const prevWordsPtNodePos, const int nextWordPosition,
-            const int unigramProbability);
-
-    static const size_t MAX_CACHED_PREV_WORDS_IN_BIGRAM_MAP;
-    std::unordered_map<int, BigramMap> mBigramMaps;
-};
-} // namespace latinime
-#endif // LATINIME_MULTI_BIGRAM_MAP_H
diff --git a/native/jni/src/suggest/core/dictionary/ngram_listener.h b/native/jni/src/suggest/core/dictionary/ngram_listener.h
deleted file mode 100644
index 88b88ba..0000000
--- a/native/jni/src/suggest/core/dictionary/ngram_listener.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_NGRAM_LISTENER_H
-#define LATINIME_NGRAM_LISTENER_H
-
-#include "defines.h"
-
-namespace latinime {
-
-/**
- * Interface to iterate ngram entries.
- */
-class NgramListener {
- public:
-    virtual void onVisitEntry(const int ngramProbability, const int targetPtNodePos) = 0;
-    virtual ~NgramListener() {};
-
- protected:
-    NgramListener() {}
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(NgramListener);
-
-};
-} // namespace latinime
-#endif /* LATINIME_NGRAM_LISTENER_H */
diff --git a/native/jni/src/suggest/core/dictionary/property/bigram_property.h b/native/jni/src/suggest/core/dictionary/property/bigram_property.h
deleted file mode 100644
index 343af14..0000000
--- a/native/jni/src/suggest/core/dictionary/property/bigram_property.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef LATINIME_BIGRAM_PROPERTY_H
-#define LATINIME_BIGRAM_PROPERTY_H
-
-#include <vector>
-
-#include "defines.h"
-
-namespace latinime {
-
-// TODO: Change to NgramProperty.
-class BigramProperty {
- public:
-    BigramProperty(const std::vector<int> *const targetCodePoints,
-            const int probability, const int timestamp, const int level, const int count)
-            : mTargetCodePoints(*targetCodePoints), mProbability(probability),
-              mTimestamp(timestamp), mLevel(level), mCount(count) {}
-
-    const std::vector<int> *getTargetCodePoints() const {
-        return &mTargetCodePoints;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    int getTimestamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
-    }
-
- private:
-    // Default copy constructor and assign operator are used for using in std::vector.
-    DISALLOW_DEFAULT_CONSTRUCTOR(BigramProperty);
-
-    // TODO: Make members const.
-    std::vector<int> mTargetCodePoints;
-    int mProbability;
-    int mTimestamp;
-    int mLevel;
-    int mCount;
-};
-} // namespace latinime
-#endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/core/dictionary/property/unigram_property.h b/native/jni/src/suggest/core/dictionary/property/unigram_property.h
deleted file mode 100644
index 902eb00..0000000
--- a/native/jni/src/suggest/core/dictionary/property/unigram_property.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef LATINIME_UNIGRAM_PROPERTY_H
-#define LATINIME_UNIGRAM_PROPERTY_H
-
-#include <vector>
-
-#include "defines.h"
-
-namespace latinime {
-
-class UnigramProperty {
- public:
-    class ShortcutProperty {
-     public:
-        ShortcutProperty(const std::vector<int> *const targetCodePoints, const int probability)
-                : mTargetCodePoints(*targetCodePoints), mProbability(probability) {}
-
-        const std::vector<int> *getTargetCodePoints() const {
-            return &mTargetCodePoints;
-        }
-
-        int getProbability() const {
-            return mProbability;
-        }
-
-     private:
-        // Default copy constructor and assign operator are used for using in std::vector.
-        DISALLOW_DEFAULT_CONSTRUCTOR(ShortcutProperty);
-
-        // TODO: Make members const.
-        std::vector<int> mTargetCodePoints;
-        int mProbability;
-    };
-
-    UnigramProperty()
-            : mRepresentsBeginningOfSentence(false), mIsNotAWord(false), mIsBlacklisted(false),
-              mProbability(NOT_A_PROBABILITY), mTimestamp(NOT_A_TIMESTAMP), mLevel(0), mCount(0),
-              mShortcuts() {}
-
-    UnigramProperty(const bool representsBeginningOfSentence, const bool isNotAWord,
-            const bool isBlacklisted, const int probability, const int timestamp, const int level,
-            const int count, const std::vector<ShortcutProperty> *const shortcuts)
-            : mRepresentsBeginningOfSentence(representsBeginningOfSentence),
-              mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted), mProbability(probability),
-              mTimestamp(timestamp), mLevel(level), mCount(count), mShortcuts(*shortcuts) {}
-
-    bool representsBeginningOfSentence() const {
-        return mRepresentsBeginningOfSentence;
-    }
-
-    bool isNotAWord() const {
-        return mIsNotAWord;
-    }
-
-    bool isBlacklisted() const {
-        return mIsBlacklisted;
-    }
-
-    bool hasShortcuts() const {
-        return !mShortcuts.empty();
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    int getTimestamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
-    }
-
-    const std::vector<ShortcutProperty> &getShortcuts() const {
-        return mShortcuts;
-    }
-
- private:
-    // Default copy constructor is used for using as a return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(UnigramProperty);
-
-    // TODO: Make members const.
-    bool mRepresentsBeginningOfSentence;
-    bool mIsNotAWord;
-    bool mIsBlacklisted;
-    int mProbability;
-    // Historical information
-    int mTimestamp;
-    int mLevel;
-    int mCount;
-    std::vector<ShortcutProperty> mShortcuts;
-};
-} // namespace latinime
-#endif // LATINIME_UNIGRAM_PROPERTY_H
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.cpp b/native/jni/src/suggest/core/dictionary/property/word_property.cpp
deleted file mode 100644
index 5bdd560..0000000
--- a/native/jni/src/suggest/core/dictionary/property/word_property.cpp
+++ /dev/null
@@ -1,84 +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.
- */
-
-#include "suggest/core/dictionary/property/word_property.h"
-
-#include "utils/jni_data_utils.h"
-
-namespace latinime {
-
-void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
-        jbooleanArray outFlags, jintArray outProbabilityInfo, jobject outBigramTargets,
-        jobject outBigramProbabilities, jobject outShortcutTargets,
-        jobject outShortcutProbabilities) const {
-    JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
-            MAX_WORD_LENGTH /* maxLength */, mCodePoints.data(), mCodePoints.size(),
-            false /* needsNullTermination */);
-    jboolean flags[] = {mUnigramProperty.isNotAWord(), mUnigramProperty.isBlacklisted(),
-            !mBigrams.empty(), mUnigramProperty.hasShortcuts(),
-            mUnigramProperty.representsBeginningOfSentence()};
-    env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
-    int probabilityInfo[] = {mUnigramProperty.getProbability(), mUnigramProperty.getTimestamp(),
-            mUnigramProperty.getLevel(), mUnigramProperty.getCount()};
-    env->SetIntArrayRegion(outProbabilityInfo, 0 /* start */, NELEMS(probabilityInfo),
-            probabilityInfo);
-
-    jclass integerClass = env->FindClass("java/lang/Integer");
-    jmethodID intToIntegerConstructorId = env->GetMethodID(integerClass, "<init>", "(I)V");
-    jclass arrayListClass = env->FindClass("java/util/ArrayList");
-    jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
-
-    // Output bigrams.
-    for (const auto &bigramProperty : mBigrams) {
-        const std::vector<int> *const word1CodePoints = bigramProperty.getTargetCodePoints();
-        jintArray bigramWord1CodePointArray = env->NewIntArray(word1CodePoints->size());
-        JniDataUtils::outputCodePoints(env, bigramWord1CodePointArray, 0 /* start */,
-                word1CodePoints->size(), word1CodePoints->data(), word1CodePoints->size(),
-                false /* needsNullTermination */);
-        env->CallBooleanMethod(outBigramTargets, addMethodId, bigramWord1CodePointArray);
-        env->DeleteLocalRef(bigramWord1CodePointArray);
-
-        int bigramProbabilityInfo[] = {bigramProperty.getProbability(),
-                bigramProperty.getTimestamp(), bigramProperty.getLevel(),
-                bigramProperty.getCount()};
-        jintArray bigramProbabilityInfoArray = env->NewIntArray(NELEMS(bigramProbabilityInfo));
-        env->SetIntArrayRegion(bigramProbabilityInfoArray, 0 /* start */,
-                NELEMS(bigramProbabilityInfo), bigramProbabilityInfo);
-        env->CallBooleanMethod(outBigramProbabilities, addMethodId, bigramProbabilityInfoArray);
-        env->DeleteLocalRef(bigramProbabilityInfoArray);
-    }
-
-    // Output shortcuts.
-    for (const auto &shortcut : mUnigramProperty.getShortcuts()) {
-        const std::vector<int> *const targetCodePoints = shortcut.getTargetCodePoints();
-        jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
-        env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
-                targetCodePoints->size(), targetCodePoints->data());
-        JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
-                targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
-                false /* needsNullTermination */);
-        env->CallBooleanMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
-        env->DeleteLocalRef(shortcutTargetCodePointArray);
-        jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
-                shortcut.getProbability());
-        env->CallBooleanMethod(outShortcutProbabilities, addMethodId, integerProbability);
-        env->DeleteLocalRef(integerProbability);
-    }
-    env->DeleteLocalRef(integerClass);
-    env->DeleteLocalRef(arrayListClass);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.h b/native/jni/src/suggest/core/dictionary/property/word_property.h
deleted file mode 100644
index aa3e0b6..0000000
--- a/native/jni/src/suggest/core/dictionary/property/word_property.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef LATINIME_WORD_PROPERTY_H
-#define LATINIME_WORD_PROPERTY_H
-
-#include <vector>
-
-#include "defines.h"
-#include "jni.h"
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/core/dictionary/property/unigram_property.h"
-
-namespace latinime {
-
-// This class is used for returning information belonging to a word to java side.
-class WordProperty {
- public:
-    // Default constructor is used to create an instance that indicates an invalid word.
-    WordProperty()
-            : mCodePoints(), mUnigramProperty(), mBigrams() {}
-
-    WordProperty(const std::vector<int> *const codePoints,
-            const UnigramProperty *const unigramProperty,
-            const std::vector<BigramProperty> *const bigrams)
-            : mCodePoints(*codePoints), mUnigramProperty(*unigramProperty), mBigrams(*bigrams) {}
-
-    void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
-            jintArray outProbabilityInfo, jobject outBigramTargets, jobject outBigramProbabilities,
-            jobject outShortcutTargets, jobject outShortcutProbabilities) const;
-
-    const UnigramProperty *getUnigramProperty() const {
-        return &mUnigramProperty;
-    }
-
-    const std::vector<BigramProperty> *getBigramProperties() const {
-        return &mBigrams;
-    }
-
- private:
-    // Default copy constructor is used for using as a return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(WordProperty);
-
-    const std::vector<int> mCodePoints;
-    const UnigramProperty mUnigramProperty;
-    const std::vector<BigramProperty> mBigrams;
-};
-} // namespace latinime
-#endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
index 34b8b37..8b39f7d 100644
--- a/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
+++ b/native/jni/src/suggest/core/layout/additional_proximity_chars.cpp
@@ -19,7 +19,7 @@
 namespace latinime {
 // TODO: Stop using hardcoded additional proximity characters.
 // TODO: Have proximity character informations in each language's binary dictionary.
-const char *AdditionalProximityChars::LOCALE_EN_US = "en";
+const int AdditionalProximityChars::LOCALE_EN_US[LOCALE_EN_US_SIZE] = { 'e', 'n' };
 
 const int AdditionalProximityChars::EN_US_ADDITIONAL_A[EN_US_ADDITIONAL_A_SIZE] = {
     'e', 'i', 'o', 'u'
diff --git a/native/jni/src/suggest/core/layout/additional_proximity_chars.h b/native/jni/src/suggest/core/layout/additional_proximity_chars.h
index a88fd6c..2260be9 100644
--- a/native/jni/src/suggest/core/layout/additional_proximity_chars.h
+++ b/native/jni/src/suggest/core/layout/additional_proximity_chars.h
@@ -18,6 +18,7 @@
 #define LATINIME_ADDITIONAL_PROXIMITY_CHARS_H
 
 #include <cstring>
+#include <vector>
 
 #include "defines.h"
 
@@ -26,7 +27,8 @@
 class AdditionalProximityChars {
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(AdditionalProximityChars);
-    static const char *LOCALE_EN_US;
+    static const int LOCALE_EN_US_SIZE = 2;
+    static const int LOCALE_EN_US[LOCALE_EN_US_SIZE];
     static const int EN_US_ADDITIONAL_A_SIZE = 4;
     static const int EN_US_ADDITIONAL_A[];
     static const int EN_US_ADDITIONAL_E_SIZE = 4;
@@ -38,15 +40,22 @@
     static const int EN_US_ADDITIONAL_U_SIZE = 4;
     static const int EN_US_ADDITIONAL_U[];
 
-    AK_FORCE_INLINE static bool isEnLocale(const char *localeStr) {
-        const size_t LOCALE_EN_US_SIZE = strlen(LOCALE_EN_US);
-        return localeStr && strlen(localeStr) >= LOCALE_EN_US_SIZE
-                && strncmp(localeStr, LOCALE_EN_US, LOCALE_EN_US_SIZE) == 0;
+    AK_FORCE_INLINE static bool isEnLocale(const std::vector<int> *locale) {
+        const int NCHARS = NELEMS(LOCALE_EN_US);
+        if (locale->size() < NCHARS) {
+            return false;
+        }
+        for (int i = 0; i < NCHARS; ++i) {
+            if ((*locale)[i] != LOCALE_EN_US[i]) {
+                return false;
+            }
+        }
+        return true;
     }
 
  public:
-    static int getAdditionalCharsSize(const char *const localeStr, const int c) {
-        if (!isEnLocale(localeStr)) {
+    static int getAdditionalCharsSize(const std::vector<int> *locale, const int c) {
+        if (!isEnLocale(locale)) {
             return 0;
         }
         switch (c) {
@@ -65,8 +74,8 @@
         }
     }
 
-    static const int *getAdditionalChars(const char *const localeStr, const int c) {
-        if (!isEnLocale(localeStr)) {
+    static const int *getAdditionalChars(const std::vector<int> *locale, const int c) {
+        if (!isEnLocale(locale)) {
             return 0;
         }
         switch (c) {
diff --git a/native/jni/src/suggest/core/layout/geometry_utils.h b/native/jni/src/suggest/core/layout/geometry_utils.h
index b667df6..000fcd4 100644
--- a/native/jni/src/suggest/core/layout/geometry_utils.h
+++ b/native/jni/src/suggest/core/layout/geometry_utils.h
@@ -38,13 +38,15 @@
     }
 
     static AK_FORCE_INLINE float getAngleDiff(const float a1, const float a2) {
-        const float deltaA = fabsf(a1 - a2);
-        const float diff = ROUND_FLOAT_10000(deltaA);
-        if (diff > M_PI_F) {
-            const float normalizedDiff = 2.0f * M_PI_F - diff;
-            return ROUND_FLOAT_10000(normalizedDiff);
+        static const float M_2PI_F = M_PI * 2.0f;
+        float delta = fabsf(a1 - a2);
+        if (delta > M_2PI_F) {
+            delta -= (M_2PI_F * static_cast<int>(delta / M_2PI_F));
         }
-        return diff;
+        if (delta > M_PI_F) {
+            delta = M_2PI_F - delta;
+        }
+        return ROUND_FLOAT_10000(delta);
     }
 
     static AK_FORCE_INLINE int getDistanceInt(const int x1, const int y1, const int x2,
diff --git a/native/jni/src/suggest/core/layout/proximity_info.cpp b/native/jni/src/suggest/core/layout/proximity_info.cpp
index 4c75a18..933a5e1 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info.cpp
@@ -49,13 +49,13 @@
     }
 }
 
-ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr,
-        const int keyboardWidth, const int keyboardHeight, const int gridWidth,
-        const int gridHeight, const int mostCommonKeyWidth, const int mostCommonKeyHeight,
-        const jintArray proximityChars, const int keyCount, const jintArray keyXCoordinates,
-        const jintArray keyYCoordinates, const jintArray keyWidths, const jintArray keyHeights,
-        const jintArray keyCharCodes, const jfloatArray sweetSpotCenterXs,
-        const jfloatArray sweetSpotCenterYs, const jfloatArray sweetSpotRadii)
+ProximityInfo::ProximityInfo(JNIEnv *env, const int keyboardWidth, const int keyboardHeight,
+        const int gridWidth, const int gridHeight, const int mostCommonKeyWidth,
+        const int mostCommonKeyHeight, const jintArray proximityChars, const int keyCount,
+        const jintArray keyXCoordinates, const jintArray keyYCoordinates,
+        const jintArray keyWidths, const jintArray keyHeights, const jintArray keyCharCodes,
+        const jfloatArray sweetSpotCenterXs, const jfloatArray sweetSpotCenterYs,
+        const jfloatArray sweetSpotRadii)
         : GRID_WIDTH(gridWidth), GRID_HEIGHT(gridHeight), MOST_COMMON_KEY_WIDTH(mostCommonKeyWidth),
           MOST_COMMON_KEY_WIDTH_SQUARE(mostCommonKeyWidth * mostCommonKeyWidth),
           NORMALIZED_SQUARED_MOST_COMMON_KEY_HYPOTENUSE(1.0f +
@@ -82,13 +82,6 @@
     if (DEBUG_PROXIMITY_INFO) {
         AKLOGI("Create proximity info array %d", proximityCharsLength);
     }
-    const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
-    if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
-        AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
-        ASSERT(false);
-    }
-    memset(mLocaleStr, 0, sizeof(mLocaleStr));
-    env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
     safeGetOrFillZeroIntArrayRegion(env, proximityChars, proximityCharsLength,
             mProximityCharsArray);
     safeGetOrFillZeroIntArrayRegion(env, keyXCoordinates, KEY_COUNT, mKeyXCoordinates);
diff --git a/native/jni/src/suggest/core/layout/proximity_info.h b/native/jni/src/suggest/core/layout/proximity_info.h
index d4e4537..f7c9076 100644
--- a/native/jni/src/suggest/core/layout/proximity_info.h
+++ b/native/jni/src/suggest/core/layout/proximity_info.h
@@ -18,6 +18,7 @@
 #define LATINIME_PROXIMITY_INFO_H
 
 #include <unordered_map>
+#include <vector>
 
 #include "defines.h"
 #include "jni.h"
@@ -27,9 +28,9 @@
 
 class ProximityInfo {
  public:
-    ProximityInfo(JNIEnv *env, const jstring localeJStr,
-            const int keyboardWidth, const int keyboardHeight, const int gridWidth,
-            const int gridHeight, const int mostCommonKeyWidth, const int mostCommonKeyHeight,
+    ProximityInfo(JNIEnv *env, const int keyboardWidth, const int keyboardHeight,
+            const int gridWidth, const int gridHeight,
+            const int mostCommonKeyWidth, const int mostCommonKeyHeight,
             const jintArray proximityChars, const int keyCount, const jintArray keyXCoordinates,
             const jintArray keyYCoordinates, const jintArray keyWidths, const jintArray keyHeights,
             const jintArray keyCharCodes, const jfloatArray sweetSpotCenterXs,
@@ -71,11 +72,11 @@
 
     AK_FORCE_INLINE void initializeProximities(const int *const inputCodes,
             const int *const inputXCoordinates, const int *const inputYCoordinates,
-            const int inputSize, int *allInputCodes) const {
+            const int inputSize, int *allInputCodes, const std::vector<int> *locale) const {
         ProximityInfoUtils::initializeProximities(inputCodes, inputXCoordinates, inputYCoordinates,
                 inputSize, mKeyXCoordinates, mKeyYCoordinates, mKeyWidths, mKeyHeights,
                 mProximityCharsArray, CELL_HEIGHT, CELL_WIDTH, GRID_WIDTH, MOST_COMMON_KEY_WIDTH,
-                KEY_COUNT, mLocaleStr, &mLowerCodePointToKeyMap, allInputCodes);
+                KEY_COUNT, locale, &mLowerCodePointToKeyMap, allInputCodes);
     }
 
     AK_FORCE_INLINE int getKeyIndexOf(const int c) const {
@@ -103,9 +104,6 @@
     const int KEYBOARD_HEIGHT;
     const float KEYBOARD_HYPOTENUSE;
     const bool HAS_TOUCH_POSITION_CORRECTION_DATA;
-    // Assuming locale strings such as en_US, sr-Latn etc.
-    static const int MAX_LOCALE_STRING_LENGTH = 10;
-    char mLocaleStr[MAX_LOCALE_STRING_LENGTH];
     int *mProximityCharsArray;
     int mKeyXCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
     int mKeyYCoordinates[MAX_KEY_COUNT_IN_A_KEYBOARD];
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.cpp b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
index 91469e2..d43a002 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state.cpp
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.cpp
@@ -42,7 +42,7 @@
 void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
         const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
         const int *const xCoordinates, const int *const yCoordinates, const int *const times,
-        const int *const pointerIds, const bool isGeometric) {
+        const int *const pointerIds, const bool isGeometric, const std::vector<int> *locale) {
     ASSERT(isGeometric || (inputSize < MAX_WORD_LENGTH));
     mIsContinuousSuggestionPossible = (mHasBeenUpdatedByGeometricInput != isGeometric) ?
             false : ProximityInfoStateUtils::checkAndReturnIsContinuousSuggestionPossible(
@@ -66,7 +66,7 @@
 
     if (!isGeometric && pointerId == 0) {
         mProximityInfo->initializeProximities(inputCodes, xCoordinates, yCoordinates,
-                inputSize, mInputProximities);
+                inputSize, mInputProximities, locale);
     }
 
     ///////////////////////
diff --git a/native/jni/src/suggest/core/layout/proximity_info_state.h b/native/jni/src/suggest/core/layout/proximity_info_state.h
index e6180fe..a2d6635 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_state.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_state.h
@@ -37,7 +37,8 @@
     void initInputParams(const int pointerId, const float maxPointToKeyLength,
             const ProximityInfo *proximityInfo, const int *const inputCodes,
             const int inputSize, const int *xCoordinates, const int *yCoordinates,
-            const int *const times, const int *const pointerIds, const bool isGeometric);
+            const int *const times, const int *const pointerIds, const bool isGeometric,
+            const std::vector<int> *locale);
 
     /////////////////////////////////////////
     // Defined here                        //
diff --git a/native/jni/src/suggest/core/layout/proximity_info_utils.h b/native/jni/src/suggest/core/layout/proximity_info_utils.h
index 178aada..79d0615 100644
--- a/native/jni/src/suggest/core/layout/proximity_info_utils.h
+++ b/native/jni/src/suggest/core/layout/proximity_info_utils.h
@@ -19,6 +19,7 @@
 
 #include <cmath>
 #include <unordered_map>
+#include <vector>
 
 #include "defines.h"
 #include "suggest/core/layout/additional_proximity_chars.h"
@@ -51,7 +52,7 @@
             const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
             const int *const proximityCharsArray, const int cellHeight, const int cellWidth,
             const int gridWidth, const int mostCommonKeyWidth, const int keyCount,
-            const char *const localeStr,
+            const std::vector<int> *locale,
             const std::unordered_map<int, int> *const codeToKeyMap, int *inputProximities) {
         // Initialize
         // - mInputCodes
@@ -64,7 +65,7 @@
             int *proximities = &inputProximities[i * MAX_PROXIMITY_CHARS_SIZE];
             calculateProximities(keyXCoordinates, keyYCoordinates, keyWidths, keyHeights,
                     proximityCharsArray, cellHeight, cellWidth, gridWidth, mostCommonKeyWidth,
-                    keyCount, x, y, primaryKey, localeStr, codeToKeyMap, proximities);
+                    keyCount, x, y, primaryKey, locale, codeToKeyMap, proximities);
         }
 
         if (DEBUG_PROXIMITY_CHARS) {
@@ -143,7 +144,7 @@
             const int *const keyYCoordinates, const int *const keyWidths, const int *keyHeights,
             const int *const proximityCharsArray, const int cellHeight, const int cellWidth,
             const int gridWidth, const int mostCommonKeyWidth, const int keyCount,
-            const int x, const int y, const int primaryKey, const char *const localeStr,
+            const int x, const int y, const int primaryKey, const std::vector<int> *locale,
             const std::unordered_map<int, int> *const codeToKeyMap, int *proximities) {
         const int mostCommonKeyWidthSquare = mostCommonKeyWidth * mostCommonKeyWidth;
         int insertPos = 0;
@@ -177,7 +178,7 @@
                 }
             }
             const int additionalProximitySize =
-                    AdditionalProximityChars::getAdditionalCharsSize(localeStr, primaryKey);
+                    AdditionalProximityChars::getAdditionalCharsSize(locale, primaryKey);
             if (additionalProximitySize > 0) {
                 proximities[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
                 if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
@@ -188,7 +189,7 @@
                 }
 
                 const int *additionalProximityChars =
-                        AdditionalProximityChars::getAdditionalChars(localeStr, primaryKey);
+                        AdditionalProximityChars::getAdditionalChars(locale, primaryKey);
                 for (int j = 0; j < additionalProximitySize; ++j) {
                     const int ac = additionalProximityChars[j];
                     int k = 0;
diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
deleted file mode 100644
index e91f076..0000000
--- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h
+++ /dev/null
@@ -1,119 +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.
- */
-
-#ifndef LATINIME_DICTIONARY_STRUCTURE_POLICY_H
-#define LATINIME_DICTIONARY_STRUCTURE_POLICY_H
-
-#include <memory>
-
-#include "defines.h"
-#include "suggest/core/dictionary/property/word_property.h"
-
-namespace latinime {
-
-class DicNode;
-class DicNodeVector;
-class DictionaryHeaderStructurePolicy;
-class DictionaryShortcutsStructurePolicy;
-class NgramListener;
-class PrevWordsInfo;
-class UnigramProperty;
-
-/*
- * This class abstracts the structure of dictionaries.
- * Implement this policy to support additional dictionaries.
- */
-class DictionaryStructureWithBufferPolicy {
- public:
-    typedef std::unique_ptr<DictionaryStructureWithBufferPolicy> StructurePolicyPtr;
-
-    virtual ~DictionaryStructureWithBufferPolicy() {}
-
-    virtual int getRootPosition() const = 0;
-
-    virtual void createAndGetAllChildDicNodes(const DicNode *const dicNode,
-            DicNodeVector *const childDicNodes) const = 0;
-
-    virtual int getCodePointsAndProbabilityAndReturnCodePointCount(
-            const int nodePos, const int maxCodePointCount, int *const outCodePoints,
-            int *const outUnigramProbability) const = 0;
-
-    virtual int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const = 0;
-
-    virtual int getProbability(const int unigramProbability,
-            const int bigramProbability) const = 0;
-
-    virtual int getProbabilityOfPtNode(const int *const prevWordsPtNodePos,
-            const int nodePos) const = 0;
-
-    virtual void iterateNgramEntries(const int *const prevWordsPtNodePos,
-            NgramListener *const listener) const = 0;
-
-    virtual int getShortcutPositionOfPtNode(const int nodePos) const = 0;
-
-    virtual const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const = 0;
-
-    virtual const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const = 0;
-
-    // Returns whether the update was success or not.
-    virtual bool addUnigramEntry(const int *const word, const int length,
-            const UnigramProperty *const unigramProperty) = 0;
-
-    // Returns whether the update was success or not.
-    virtual bool removeUnigramEntry(const int *const word, const int length) = 0;
-
-    // Returns whether the update was success or not.
-    virtual bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const BigramProperty *const bigramProperty) = 0;
-
-    // Returns whether the update was success or not.
-    virtual bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const int *const word, const int length) = 0;
-
-    // Returns whether the flush was success or not.
-    virtual bool flush(const char *const filePath) = 0;
-
-    // Returns whether the GC and flush were success or not.
-    virtual bool flushWithGC(const char *const filePath) = 0;
-
-    virtual bool needsToRunGC(const bool mindsBlockByGC) const = 0;
-
-    // Currently, this method is used only for testing. You may want to consider creating new
-    // dedicated method instead of this if you want to use this in the production.
-    virtual void getProperty(const char *const query, const int queryLength, char *const outResult,
-            const int maxResultLength) = 0;
-
-    // Used for testing.
-    virtual const WordProperty getWordProperty(const int *const codePonts,
-            const int codePointCount) const = 0;
-
-    // Method to iterate all words in the dictionary.
-    // The returned token has to be used to get the next word. If token is 0, this method newly
-    // starts iterating the dictionary.
-    virtual int getNextWordAndNextToken(const int token, int *const outCodePoints,
-            int *const outCodePointCount) = 0;
-
-    virtual bool isCorrupted() const = 0;
-
- protected:
-    DictionaryStructureWithBufferPolicy() {}
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(DictionaryStructureWithBufferPolicy);
-};
-} // namespace latinime
-#endif /* LATINIME_DICTIONARY_STRUCTURE_POLICY_H */
diff --git a/native/jni/src/suggest/core/policy/scoring.h b/native/jni/src/suggest/core/policy/scoring.h
index 9e75cac..b9dda83 100644
--- a/native/jni/src/suggest/core/policy/scoring.h
+++ b/native/jni/src/suggest/core/policy/scoring.h
@@ -30,11 +30,13 @@
  public:
     virtual int calculateFinalScore(const float compoundDistance, const int inputSize,
             const ErrorTypeUtils::ErrorType containedErrorTypes, const bool forceCommit,
-            const bool boostExactMatches) const = 0;
+            const bool boostExactMatches, const bool hasProbabilityZero) const = 0;
     virtual void getMostProbableString(const DicTraverseSession *const traverseSession,
-            const float languageWeight, SuggestionResults *const outSuggestionResults) const = 0;
-    virtual float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
-            DicNode *const terminals, const int size) const = 0;
+            const float weightOfLangModelVsSpatialModel,
+            SuggestionResults *const outSuggestionResults) const = 0;
+    virtual float getAdjustedWeightOfLangModelVsSpatialModel(
+            DicTraverseSession *const traverseSession, DicNode *const terminals,
+            const int size) const = 0;
     virtual float getDoubleLetterDemotionDistanceCost(
             const DicNode *const terminalDicNode) const = 0;
     virtual bool autoCorrectsToMultiWordSuggestionIfTop() const = 0;
diff --git a/native/jni/src/suggest/core/policy/traversal.h b/native/jni/src/suggest/core/policy/traversal.h
index 8ddaa05..5b6616d 100644
--- a/native/jni/src/suggest/core/policy/traversal.h
+++ b/native/jni/src/suggest/core/policy/traversal.h
@@ -44,11 +44,12 @@
     virtual bool needsToTraverseAllUserInput() const = 0;
     virtual float getMaxSpatialDistance() const = 0;
     virtual int getDefaultExpandDicNodeSize() const = 0;
-    virtual int getMaxCacheSize(const int inputSize) const = 0;
+    virtual int getMaxCacheSize(const int inputSize, const float weightForLocale) const = 0;
     virtual int getTerminalCacheSize() const = 0;
     virtual bool isPossibleOmissionChildNode(const DicTraverseSession *const traverseSession,
             const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
-    virtual bool isGoodToTraverseNextWord(const DicNode *const dicNode) const = 0;
+    virtual bool isGoodToTraverseNextWord(const DicNode *const dicNode,
+            const int probability) const = 0;
 
  protected:
     Traversal() {}
diff --git a/native/jni/src/suggest/core/policy/weighting.cpp b/native/jni/src/suggest/core/policy/weighting.cpp
index c202b81..450203d 100644
--- a/native/jni/src/suggest/core/policy/weighting.cpp
+++ b/native/jni/src/suggest/core/policy/weighting.cpp
@@ -110,12 +110,16 @@
         return weighting->getOmissionCost(parentDicNode, dicNode);
     case CT_ADDITIONAL_PROXIMITY:
         // only used for typing
-        return weighting->getAdditionalProximityCost();
+        // TODO: Quit calling getMatchedCost().
+        return weighting->getAdditionalProximityCost()
+                + weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
     case CT_SUBSTITUTION:
         // only used for typing
-        return weighting->getSubstitutionCost();
+        // TODO: Quit calling getMatchedCost().
+        return weighting->getSubstitutionCost()
+                + weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
     case CT_NEW_WORD_SPACE_OMISSION:
-        return weighting->getNewWordSpatialCost(traverseSession, dicNode, inputStateG);
+        return weighting->getSpaceOmissionCost(traverseSession, dicNode, inputStateG);
     case CT_MATCH:
         return weighting->getMatchedCost(traverseSession, dicNode, inputStateG);
     case CT_COMPLETION:
@@ -176,9 +180,9 @@
         case CT_OMISSION:
             return 0;
         case CT_ADDITIONAL_PROXIMITY:
-            return 0; /* 0 because CT_MATCH will be called */
+            return 1;
         case CT_SUBSTITUTION:
-            return 0; /* 0 because CT_MATCH will be called */
+            return 1;
         case CT_NEW_WORD_SPACE_OMISSION:
             return 0;
         case CT_MATCH:
diff --git a/native/jni/src/suggest/core/policy/weighting.h b/native/jni/src/suggest/core/policy/weighting.h
index bd6b3cf..863c4ea 100644
--- a/native/jni/src/suggest/core/policy/weighting.h
+++ b/native/jni/src/suggest/core/policy/weighting.h
@@ -57,7 +57,7 @@
             const DicTraverseSession *const traverseSession,
             const DicNode *const parentDicNode, const DicNode *const dicNode) const = 0;
 
-    virtual float getNewWordSpatialCost(const DicTraverseSession *const traverseSession,
+    virtual float getSpaceOmissionCost(const DicTraverseSession *const traverseSession,
             const DicNode *const dicNode, DicNode_InputStateG *const inputStateG) const = 0;
 
     virtual float getNewWordBigramLanguageCost(
diff --git a/native/jni/src/suggest/core/result/suggestion_results.cpp b/native/jni/src/suggest/core/result/suggestion_results.cpp
index 4c10bd0..3756d10 100644
--- a/native/jni/src/suggest/core/result/suggestion_results.cpp
+++ b/native/jni/src/suggest/core/result/suggestion_results.cpp
@@ -23,7 +23,7 @@
 void SuggestionResults::outputSuggestions(JNIEnv *env, jintArray outSuggestionCount,
         jintArray outputCodePointsArray, jintArray outScoresArray, jintArray outSpaceIndicesArray,
         jintArray outTypesArray, jintArray outAutoCommitFirstWordConfidenceArray,
-        jfloatArray outLanguageWeight) {
+        jfloatArray outWeightOfLangModelVsSpatialModel) {
     int outputIndex = 0;
     while (!mSuggestedWords.empty()) {
         const SuggestedWord &suggestedWord = mSuggestedWords.top();
@@ -44,7 +44,8 @@
         mSuggestedWords.pop();
     }
     JniDataUtils::putIntToArray(env, outSuggestionCount, 0 /* index */, outputIndex);
-    JniDataUtils::putFloatToArray(env, outLanguageWeight, 0 /* index */, mLanguageWeight);
+    JniDataUtils::putFloatToArray(env, outWeightOfLangModelVsSpatialModel, 0 /* index */,
+            mWeightOfLangModelVsSpatialModel);
 }
 
 void SuggestionResults::addPrediction(const int *const codePoints, const int codePointCount,
@@ -89,7 +90,7 @@
 }
 
 void SuggestionResults::dumpSuggestions() const {
-    AKLOGE("language weight: %f", mLanguageWeight);
+    AKLOGE("weight of language model vs spatial model: %f", mWeightOfLangModelVsSpatialModel);
     std::vector<SuggestedWord> suggestedWords;
     auto copyOfSuggestedWords = mSuggestedWords;
     while (!copyOfSuggestedWords.empty()) {
diff --git a/native/jni/src/suggest/core/result/suggestion_results.h b/native/jni/src/suggest/core/result/suggestion_results.h
index 8e845e2..738c78a 100644
--- a/native/jni/src/suggest/core/result/suggestion_results.h
+++ b/native/jni/src/suggest/core/result/suggestion_results.h
@@ -29,13 +29,15 @@
 class SuggestionResults {
  public:
     explicit SuggestionResults(const int maxSuggestionCount)
-            : mMaxSuggestionCount(maxSuggestionCount), mLanguageWeight(NOT_A_LANGUAGE_WEIGHT),
+            : mMaxSuggestionCount(maxSuggestionCount),
+              mWeightOfLangModelVsSpatialModel(NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL),
               mSuggestedWords() {}
 
     // Returns suggestion count.
     void outputSuggestions(JNIEnv *env, jintArray outSuggestionCount, jintArray outCodePointsArray,
             jintArray outScoresArray, jintArray outSpaceIndicesArray, jintArray outTypesArray,
-            jintArray outAutoCommitFirstWordConfidenceArray, jfloatArray outLanguageWeight);
+            jintArray outAutoCommitFirstWordConfidenceArray,
+            jfloatArray outWeightOfLangModelVsSpatialModel);
     void addPrediction(const int *const codePoints, const int codePointCount, const int score);
     void addSuggestion(const int *const codePoints, const int codePointCount,
             const int score, const int type, const int indexToPartialCommit,
@@ -43,8 +45,8 @@
     void getSortedScores(int *const outScores) const;
     void dumpSuggestions() const;
 
-    void setLanguageWeight(const float languageWeight) {
-        mLanguageWeight = languageWeight;
+    void setWeightOfLangModelVsSpatialModel(const float weightOfLangModelVsSpatialModel) {
+        mWeightOfLangModelVsSpatialModel = weightOfLangModelVsSpatialModel;
     }
 
     int getSuggestionCount() const {
@@ -55,7 +57,7 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(SuggestionResults);
 
     const int mMaxSuggestionCount;
-    float mLanguageWeight;
+    float mWeightOfLangModelVsSpatialModel;
     std::priority_queue<
             SuggestedWord, std::vector<SuggestedWord>, SuggestedWord::Comparator> mSuggestedWords;
 };
diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
index 0b99b75..7c37241 100644
--- a/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
+++ b/native/jni/src/suggest/core/result/suggestions_output_utils.cpp
@@ -19,9 +19,9 @@
 #include <algorithm>
 #include <vector>
 
+#include "dictionary/utils/binary_dictionary_shortcut_iterator.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_utils.h"
-#include "suggest/core/dictionary/binary_dictionary_shortcut_iterator.h"
 #include "suggest/core/dictionary/error_type_utils.h"
 #include "suggest/core/policy/scoring.h"
 #include "suggest/core/result/suggestion_results.h"
@@ -34,7 +34,8 @@
 
 /* static */ void SuggestionsOutputUtils::outputSuggestions(
         const Scoring *const scoringPolicy, DicTraverseSession *traverseSession,
-        const float languageWeight, SuggestionResults *const outSuggestionResults) {
+        const float weightOfLangModelVsSpatialModel,
+        SuggestionResults *const outSuggestionResults) {
 #if DEBUG_EVALUATE_MOST_PROBABLE_STRING
     const int terminalSize = 0;
 #else
@@ -44,12 +45,15 @@
     for (int index = terminalSize - 1; index >= 0; --index) {
         traverseSession->getDicTraverseCache()->popTerminal(&terminals[index]);
     }
-    // Compute a language weight when an invalid language weight is passed.
-    // NOT_A_LANGUAGE_WEIGHT (-1) is assumed as an invalid language weight.
-    const float languageWeightToOutputSuggestions = (languageWeight < 0.0f) ?
-            scoringPolicy->getAdjustedLanguageWeight(
-                    traverseSession, terminals.data(), terminalSize) : languageWeight;
-    outSuggestionResults->setLanguageWeight(languageWeightToOutputSuggestions);
+    // Compute a weight of language model when an invalid weight is passed.
+    // NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL (-1) is taken as an invalid value.
+    const float weightOfLangModelVsSpatialModelToOutputSuggestions =
+            (weightOfLangModelVsSpatialModel < 0.0f)
+            ? scoringPolicy->getAdjustedWeightOfLangModelVsSpatialModel(traverseSession,
+                    terminals.data(), terminalSize)
+            : weightOfLangModelVsSpatialModel;
+    outSuggestionResults->setWeightOfLangModelVsSpatialModel(
+            weightOfLangModelVsSpatialModelToOutputSuggestions);
     // Force autocorrection for obvious long multi-word suggestions when the top suggestion is
     // a long multiple words suggestion.
     // TODO: Implement a smarter auto-commit method for handling multi-word suggestions.
@@ -65,16 +69,62 @@
     // Output suggestion results here
     for (auto &terminalDicNode : terminals) {
         outputSuggestionsOfDicNode(scoringPolicy, traverseSession, &terminalDicNode,
-                languageWeightToOutputSuggestions, boostExactMatches, forceCommitMultiWords,
-                outputSecondWordFirstLetterInputIndex, outSuggestionResults);
+                weightOfLangModelVsSpatialModelToOutputSuggestions, boostExactMatches,
+                forceCommitMultiWords, outputSecondWordFirstLetterInputIndex, outSuggestionResults);
     }
-    scoringPolicy->getMostProbableString(traverseSession, languageWeightToOutputSuggestions,
-            outSuggestionResults);
+    scoringPolicy->getMostProbableString(traverseSession,
+            weightOfLangModelVsSpatialModelToOutputSuggestions, outSuggestionResults);
+}
+
+/* static */ bool SuggestionsOutputUtils::shouldBlockWord(
+        const SuggestOptions *const suggestOptions, const DicNode *const terminalDicNode,
+        const WordAttributes wordAttributes, const bool isLastWord) {
+    const bool currentWordExactMatch =
+            ErrorTypeUtils::isExactMatch(terminalDicNode->getContainedErrorTypes());
+    // When we have to block offensive words, non-exact matched offensive words should not be
+    // output.
+    const bool shouldBlockOffensiveWords = suggestOptions->blockOffensiveWords();
+
+    const bool isBlockedOffensiveWord = shouldBlockOffensiveWords &&
+            wordAttributes.isPossiblyOffensive();
+
+    // This function is called in two situations:
+    //
+    // 1) At the end of a search, in which case terminalDicNode will point to the last DicNode
+    //    of the search, and isLastWord will be true.
+    //                    "fuck"
+    //                        |
+    //                        \ terminalDicNode (isLastWord=true, currentWordExactMatch=true)
+    //    In this case, if the current word is an exact match, we will always let the word
+    //    through, even if the user is blocking offensive words (it's exactly what they typed!)
+    //
+    // 2) In the middle of the search, when we hit a terminal node, to decide whether or not
+    //    to start a new search at root, to try to match the rest of the input. In this case,
+    //    terminalDicNode will point to the terminal node we just hit, and isLastWord will be
+    //    false.
+    //                    "fuckvthis"
+    //                        |
+    //                        \ terminalDicNode (isLastWord=false, currentWordExactMatch=true)
+    //
+    // In this case, we should NOT allow the match through (correcting "fuckthis" to "fuck this"
+    // when offensive words are blocked would be a bad idea).
+    //
+    // In the case of a multi-word correction where the offensive word is typed last (eg.
+    // for the input "allfuck"), this function will be called with isLastWord==true, but
+    // currentWordExactMatch==false. So we are OK in this case as well.
+    //                    "allfuck"
+    //                           |
+    //                           \ terminalDicNode (isLastWord=true, currentWordExactMatch=false)
+    if (isLastWord && currentWordExactMatch) {
+        return false;
+    } else {
+        return isBlockedOffensiveWord;
+    }
 }
 
 /* static */ void SuggestionsOutputUtils::outputSuggestionsOfDicNode(
         const Scoring *const scoringPolicy, DicTraverseSession *traverseSession,
-        const DicNode *const terminalDicNode, const float languageWeight,
+        const DicNode *const terminalDicNode, const float weightOfLangModelVsSpatialModel,
         const bool boostExactMatches, const bool forceCommitMultiWords,
         const bool outputSecondWordFirstLetterInputIndex,
         SuggestionResults *const outSuggestionResults) {
@@ -83,34 +133,32 @@
     }
     const float doubleLetterCost =
             scoringPolicy->getDoubleLetterDemotionDistanceCost(terminalDicNode);
-    const float compoundDistance = terminalDicNode->getCompoundDistance(languageWeight)
-            + doubleLetterCost;
-    const bool isPossiblyOffensiveWord =
-            traverseSession->getDictionaryStructurePolicy()->getProbability(
-                    terminalDicNode->getProbability(), NOT_A_PROBABILITY) <= 0;
+    const float compoundDistance =
+            terminalDicNode->getCompoundDistance(weightOfLangModelVsSpatialModel)
+                    + doubleLetterCost;
+    const WordAttributes wordAttributes = traverseSession->getDictionaryStructurePolicy()
+            ->getWordAttributesInContext(terminalDicNode->getPrevWordIds(),
+                    terminalDicNode->getWordId(), nullptr /* multiBigramMap */);
     const bool isExactMatch =
             ErrorTypeUtils::isExactMatch(terminalDicNode->getContainedErrorTypes());
     const bool isExactMatchWithIntentionalOmission =
             ErrorTypeUtils::isExactMatchWithIntentionalOmission(
                     terminalDicNode->getContainedErrorTypes());
-    const bool isFirstCharUppercase = terminalDicNode->isFirstCharUppercase();
-    // Heuristic: We exclude probability=0 first-char-uppercase words from exact match.
-    // (e.g. "AMD" and "and")
-    const bool isSafeExactMatch = isExactMatch
-            && !(isPossiblyOffensiveWord && isFirstCharUppercase);
+    // TODO: Decide whether the word should be auto-corrected or not here.
+    const bool isAppropriateForAutoCorrection = !ErrorTypeUtils::isMissingExplicitAccent(
+            terminalDicNode->getContainedErrorTypes());
     const int outputTypeFlags =
-            (isPossiblyOffensiveWord ? Dictionary::KIND_FLAG_POSSIBLY_OFFENSIVE : 0)
-            | ((isSafeExactMatch && boostExactMatches) ? Dictionary::KIND_FLAG_EXACT_MATCH : 0)
+            (wordAttributes.isPossiblyOffensive() ? Dictionary::KIND_FLAG_POSSIBLY_OFFENSIVE : 0)
+            | ((isExactMatch && boostExactMatches) ? Dictionary::KIND_FLAG_EXACT_MATCH : 0)
             | (isExactMatchWithIntentionalOmission ?
-                    Dictionary::KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION : 0);
-
+                    Dictionary::KIND_FLAG_EXACT_MATCH_WITH_INTENTIONAL_OMISSION : 0)
+            | (isAppropriateForAutoCorrection ?
+                    Dictionary::KIND_FLAG_APPROPRIATE_FOR_AUTOCORRECTION : 0);
     // Entries that are blacklisted or do not represent a word should not be output.
-    const bool isValidWord = !terminalDicNode->isBlacklistedOrNotAWord();
-    // When we have to block offensive words, non-exact matched offensive words should not be
-    // output.
-    const bool blockOffensiveWords = traverseSession->getSuggestOptions()->blockOffensiveWords();
-    const bool isBlockedOffensiveWord = blockOffensiveWords && isPossiblyOffensiveWord
-            && !isSafeExactMatch;
+    const bool isValidWord = !(wordAttributes.isBlacklisted() || wordAttributes.isNotAWord());
+
+    const bool shouldBlockThisWord = shouldBlockWord(traverseSession->getSuggestOptions(),
+            terminalDicNode, wordAttributes, true /* isLastWord */);
 
     // Increase output score of top typing suggestion to ensure autocorrection.
     // TODO: Better integration with java side autocorrection logic.
@@ -118,11 +166,11 @@
             compoundDistance, traverseSession->getInputSize(),
             terminalDicNode->getContainedErrorTypes(),
             (forceCommitMultiWords && terminalDicNode->hasMultipleWords()),
-            boostExactMatches);
+            boostExactMatches, wordAttributes.getProbability() == 0);
 
     // Don't output invalid or blocked offensive words. However, we still need to submit their
     // shortcuts if any.
-    if (isValidWord && !isBlockedOffensiveWord) {
+    if (isValidWord && !shouldBlockThisWord) {
         int codePoints[MAX_WORD_LENGTH];
         terminalDicNode->outputResult(codePoints);
         const int indexToPartialCommit = outputSecondWordFirstLetterInputIndex ?
@@ -139,10 +187,9 @@
     // Shortcut is not supported for multiple words suggestions.
     // TODO: Check shortcuts during traversal for multiple words suggestions.
     if (!terminalDicNode->hasMultipleWords()) {
-        BinaryDictionaryShortcutIterator shortcutIt(
-                traverseSession->getDictionaryStructurePolicy()->getShortcutsStructurePolicy(),
-                traverseSession->getDictionaryStructurePolicy()
-                        ->getShortcutPositionOfPtNode(terminalDicNode->getPtNodePos()));
+        BinaryDictionaryShortcutIterator shortcutIt =
+                traverseSession->getDictionaryStructurePolicy()->getShortcutIterator(
+                        terminalDicNode->getWordId());
         const bool sameAsTyped = scoringPolicy->sameAsTyped(traverseSession, terminalDicNode);
         outputShortcuts(&shortcutIt, finalScore, sameAsTyped, outSuggestionResults);
     }
diff --git a/native/jni/src/suggest/core/result/suggestions_output_utils.h b/native/jni/src/suggest/core/result/suggestions_output_utils.h
index b099b47..bcb75a4 100644
--- a/native/jni/src/suggest/core/result/suggestions_output_utils.h
+++ b/native/jni/src/suggest/core/result/suggestions_output_utils.h
@@ -18,6 +18,7 @@
 #define LATINIME_SUGGESTIONS_OUTPUT_UTILS
 
 #include "defines.h"
+#include "dictionary/property/word_attributes.h"
 
 namespace latinime {
 
@@ -25,15 +26,23 @@
 class DicNode;
 class DicTraverseSession;
 class Scoring;
+class SuggestOptions;
 class SuggestionResults;
 
 class SuggestionsOutputUtils {
  public:
     /**
+     * Returns true if we should block the incoming word, in the context of the user's
+     * preferences to include or not include possibly offensive words
+     */
+    static bool shouldBlockWord(const SuggestOptions *const suggestOptions,
+            const DicNode *const terminalDicNode, const WordAttributes wordAttributes,
+            const bool isLastWord);
+    /**
      * Outputs the final list of suggestions (i.e., terminal nodes).
      */
     static void outputSuggestions(const Scoring *const scoringPolicy,
-            DicTraverseSession *traverseSession, const float languageWeight,
+            DicTraverseSession *traverseSession, const float weightOfLangModelVsSpatialModel,
             SuggestionResults *const outSuggestionResults);
 
  private:
@@ -44,7 +53,7 @@
 
     static void outputSuggestionsOfDicNode(const Scoring *const scoringPolicy,
             DicTraverseSession *traverseSession, const DicNode *const terminalDicNode,
-            const float languageWeight, const bool boostExactMatches,
+            const float weightOfLangModelVsSpatialModel, const bool boostExactMatches,
             const bool forceCommitMultiWords, const bool outputSecondWordFirstLetterInputIndex,
             SuggestionResults *const outSuggestionResults);
     static void outputShortcuts(BinaryDictionaryShortcutIterator *const shortcutIt,
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.cpp b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
index f1e411f..d7dd5a0 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.cpp
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.cpp
@@ -17,10 +17,10 @@
 #include "suggest/core/session/dic_traverse_session.h"
 
 #include "defines.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/property/ngram_context.h"
 #include "suggest/core/dictionary/dictionary.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/core/session/prev_words_info.h"
 
 namespace latinime {
 
@@ -30,13 +30,13 @@
         256 * 1024;
 
 void DicTraverseSession::init(const Dictionary *const dictionary,
-        const PrevWordsInfo *const prevWordsInfo, const SuggestOptions *const suggestOptions) {
+        const NgramContext *const ngramContext, const SuggestOptions *const suggestOptions) {
     mDictionary = dictionary;
     mMultiWordCostMultiplier = getDictionaryStructurePolicy()->getHeaderStructurePolicy()
             ->getMultiWordCostMultiplier();
     mSuggestOptions = suggestOptions;
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(
-            getDictionaryStructurePolicy(), mPrevWordsPtNodePos, true /* tryLowerCaseSearch */);
+    mPrevWordIdCount = ngramContext->getPrevWordIds(getDictionaryStructurePolicy(),
+            &mPrevWordIdArray, true /* tryLowerCaseSearch */).size();
 }
 
 void DicTraverseSession::setupForGetSuggestions(const ProximityInfo *pInfo,
@@ -69,8 +69,12 @@
     for (int i = 0; i < maxPointerCount; ++i) {
         mProximityInfoStates[i].initInputParams(i, maxSpatialDistance, getProximityInfo(),
                 inputCodePoints, inputSize, inputXs, inputYs, times, pointerIds,
-                maxPointerCount == MAX_POINTER_COUNT_G
-                /* TODO: this is a hack. fix proximity info state */);
+                // Right now the line below is trying to figure out whether this is a gesture by
+                // looking at the pointer count and assuming whatever is above the cutoff is
+                // a gesture and whatever is below is type. This is hacky and incorrect, we
+                // should pass the correct information instead.
+                maxPointerCount == MAX_POINTER_COUNT_G,
+                getDictionaryStructurePolicy()->getHeaderStructurePolicy()->getLocale());
         mInputSize += mProximityInfoStates[i].size();
     }
 }
diff --git a/native/jni/src/suggest/core/session/dic_traverse_session.h b/native/jni/src/suggest/core/session/dic_traverse_session.h
index 5a51a11..f5fcfdd 100644
--- a/native/jni/src/suggest/core/session/dic_traverse_session.h
+++ b/native/jni/src/suggest/core/session/dic_traverse_session.h
@@ -20,16 +20,17 @@
 #include <vector>
 
 #include "defines.h"
+#include "dictionary/utils/multi_bigram_map.h"
 #include "jni.h"
 #include "suggest/core/dicnode/dic_nodes_cache.h"
-#include "suggest/core/dictionary/multi_bigram_map.h"
 #include "suggest/core/layout/proximity_info_state.h"
+#include "utils/int_array_view.h"
 
 namespace latinime {
 
 class Dictionary;
 class DictionaryStructureWithBufferPolicy;
-class PrevWordsInfo;
+class NgramContext;
 class ProximityInfo;
 class SuggestOptions;
 
@@ -50,20 +51,17 @@
     }
 
     AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
-            : mProximityInfo(nullptr), mDictionary(nullptr), mSuggestOptions(nullptr),
-              mDicNodesCache(usesLargeCache), mMultiBigramMap(), mInputSize(0), mMaxPointerCount(1),
-              mMultiWordCostMultiplier(1.0f) {
+            : mPrevWordIdCount(0), mProximityInfo(nullptr), mDictionary(nullptr),
+              mSuggestOptions(nullptr), mDicNodesCache(usesLargeCache), mMultiBigramMap(),
+              mInputSize(0), mMaxPointerCount(1), mMultiWordCostMultiplier(1.0f) {
         // NOTE: mProximityInfoStates is an array of instances.
         // No need to initialize it explicitly here.
-        for (size_t i = 0; i < NELEMS(mPrevWordsPtNodePos); ++i) {
-            mPrevWordsPtNodePos[i] = NOT_A_DICT_POS;
-        }
     }
 
     // Non virtual inline destructor -- never inherit this class
     AK_FORCE_INLINE ~DicTraverseSession() {}
 
-    void init(const Dictionary *dictionary, const PrevWordsInfo *const prevWordsInfo,
+    void init(const Dictionary *dictionary, const NgramContext *const ngramContext,
             const SuggestOptions *const suggestOptions);
     // TODO: Remove and merge into init
     void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
@@ -79,7 +77,9 @@
     //--------------------
     const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
     const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
-    const int *getPrevWordsPtNodePos() const { return mPrevWordsPtNodePos; }
+    const WordIdArrayView getPrevWordIds() const {
+        return WordIdArrayView::fromArray(mPrevWordIdArray).limit(mPrevWordIdCount);
+    }
     DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
     MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
     const ProximityInfoState *getProximityInfoState(int id) const {
@@ -166,7 +166,8 @@
             const int *const inputYs, const int *const times, const int *const pointerIds,
             const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
 
-    int mPrevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
+    WordIdArray<MAX_PREV_WORD_COUNT_FOR_N_GRAM> mPrevWordIdArray;
+    size_t mPrevWordIdCount;
     const ProximityInfo *mProximityInfo;
     const Dictionary *mDictionary;
     const SuggestOptions *mSuggestOptions;
diff --git a/native/jni/src/suggest/core/session/prev_words_info.h b/native/jni/src/suggest/core/session/prev_words_info.h
deleted file mode 100644
index e44e876..0000000
--- a/native/jni/src/suggest/core/session/prev_words_info.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef LATINIME_PREV_WORDS_INFO_H
-#define LATINIME_PREV_WORDS_INFO_H
-
-#include "defines.h"
-#include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "utils/char_utils.h"
-
-namespace latinime {
-
-// TODO: Support n-gram.
-class PrevWordsInfo {
- public:
-    // No prev word information.
-    PrevWordsInfo() {
-        clear();
-    }
-
-    PrevWordsInfo(PrevWordsInfo &&prevWordsInfo) {
-        for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
-            mPrevWordCodePointCount[i] = prevWordsInfo.mPrevWordCodePointCount[i];
-            memmove(mPrevWordCodePoints[i], prevWordsInfo.mPrevWordCodePoints[i],
-                    sizeof(mPrevWordCodePoints[i][0]) * mPrevWordCodePointCount[i]);
-            mIsBeginningOfSentence[i] = prevWordsInfo.mIsBeginningOfSentence[i];
-        }
-    }
-
-    // Construct from previous words.
-    PrevWordsInfo(const int prevWordCodePoints[][MAX_WORD_LENGTH],
-            const int *const prevWordCodePointCount, const bool *const isBeginningOfSentence,
-            const size_t prevWordCount) {
-        clear();
-        for (size_t i = 0; i < std::min(NELEMS(mPrevWordCodePoints), prevWordCount); ++i) {
-            if (prevWordCodePointCount[i] < 0 || prevWordCodePointCount[i] > MAX_WORD_LENGTH) {
-                continue;
-            }
-            memmove(mPrevWordCodePoints[i], prevWordCodePoints[i],
-                    sizeof(mPrevWordCodePoints[i][0]) * prevWordCodePointCount[i]);
-            mPrevWordCodePointCount[i] = prevWordCodePointCount[i];
-            mIsBeginningOfSentence[i] = isBeginningOfSentence[i];
-        }
-    }
-
-    // Construct from a previous word.
-    PrevWordsInfo(const int *const prevWordCodePoints, const int prevWordCodePointCount,
-            const bool isBeginningOfSentence) {
-        clear();
-        if (prevWordCodePointCount > MAX_WORD_LENGTH || !prevWordCodePoints) {
-            return;
-        }
-        memmove(mPrevWordCodePoints[0], prevWordCodePoints,
-                sizeof(mPrevWordCodePoints[0][0]) * prevWordCodePointCount);
-        mPrevWordCodePointCount[0] = prevWordCodePointCount;
-        mIsBeginningOfSentence[0] = isBeginningOfSentence;
-    }
-
-    bool isValid() const {
-        if (mPrevWordCodePointCount[0] > 0) {
-            return true;
-        }
-        if (mIsBeginningOfSentence[0]) {
-            return true;
-        }
-        return false;
-    }
-
-    void getPrevWordsTerminalPtNodePos(
-            const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
-            int *const outPrevWordsTerminalPtNodePos, const bool tryLowerCaseSearch) const {
-        for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
-            outPrevWordsTerminalPtNodePos[i] = getTerminalPtNodePosOfWord(dictStructurePolicy,
-                    mPrevWordCodePoints[i], mPrevWordCodePointCount[i],
-                    mIsBeginningOfSentence[i], tryLowerCaseSearch);
-        }
-    }
-
-    // n is 1-indexed.
-    const int *getNthPrevWordCodePoints(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
-            return nullptr;
-        }
-        return mPrevWordCodePoints[n - 1];
-    }
-
-    // n is 1-indexed.
-    int getNthPrevWordCodePointCount(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
-            return 0;
-        }
-        return mPrevWordCodePointCount[n - 1];
-    }
-
-    // n is 1-indexed.
-    bool isNthPrevWordBeginningOfSentence(const int n) const {
-        if (n <= 0 || n > MAX_PREV_WORD_COUNT_FOR_N_GRAM) {
-            return false;
-        }
-        return mIsBeginningOfSentence[n - 1];
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(PrevWordsInfo);
-
-    static int getTerminalPtNodePosOfWord(
-            const DictionaryStructureWithBufferPolicy *const dictStructurePolicy,
-            const int *const wordCodePoints, const int wordCodePointCount,
-            const bool isBeginningOfSentence, const bool tryLowerCaseSearch) {
-        if (!dictStructurePolicy || !wordCodePoints || wordCodePointCount > MAX_WORD_LENGTH) {
-            return NOT_A_DICT_POS;
-        }
-        int codePoints[MAX_WORD_LENGTH];
-        int codePointCount = wordCodePointCount;
-        memmove(codePoints, wordCodePoints, sizeof(int) * codePointCount);
-        if (isBeginningOfSentence) {
-            codePointCount = CharUtils::attachBeginningOfSentenceMarker(codePoints,
-                    codePointCount, MAX_WORD_LENGTH);
-            if (codePointCount <= 0) {
-                return NOT_A_DICT_POS;
-            }
-        }
-        const int wordPtNodePos = dictStructurePolicy->getTerminalPtNodePositionOfWord(
-                codePoints, codePointCount, false /* forceLowerCaseSearch */);
-        if (wordPtNodePos != NOT_A_DICT_POS || !tryLowerCaseSearch) {
-            // Return the position when when the word was found or doesn't try lower case
-            // search.
-            return wordPtNodePos;
-        }
-        // Check bigrams for lower-cased previous word if original was not found. Useful for
-        // auto-capitalized words like "The [current_word]".
-        return dictStructurePolicy->getTerminalPtNodePositionOfWord(
-                codePoints, codePointCount, true /* forceLowerCaseSearch */);
-    }
-
-    void clear() {
-        for (size_t i = 0; i < NELEMS(mPrevWordCodePoints); ++i) {
-            mPrevWordCodePointCount[i] = 0;
-            mIsBeginningOfSentence[i] = false;
-        }
-    }
-
-    int mPrevWordCodePoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH];
-    int mPrevWordCodePointCount[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    bool mIsBeginningOfSentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-};
-} // namespace latinime
-#endif // LATINIME_PREV_WORDS_INFO_H
diff --git a/native/jni/src/suggest/core/suggest.cpp b/native/jni/src/suggest/core/suggest.cpp
index 0cd305f..52fa5a5 100644
--- a/native/jni/src/suggest/core/suggest.cpp
+++ b/native/jni/src/suggest/core/suggest.cpp
@@ -16,17 +16,20 @@
 
 #include "suggest/core/suggest.h"
 
+#include "dictionary/interface/dictionary_structure_with_buffer_policy.h"
+#include "dictionary/property/word_attributes.h"
 #include "suggest/core/dicnode/dic_node.h"
 #include "suggest/core/dicnode/dic_node_priority_queue.h"
 #include "suggest/core/dicnode/dic_node_vector.h"
 #include "suggest/core/dictionary/dictionary.h"
 #include "suggest/core/dictionary/digraph_utils.h"
 #include "suggest/core/layout/proximity_info.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/policy/weighting.h"
 #include "suggest/core/result/suggestions_output_utils.h"
 #include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/core/suggest_options.h"
+#include "utils/profiler.h"
 
 namespace latinime {
 
@@ -44,10 +47,10 @@
  */
 void Suggest::getSuggestions(ProximityInfo *pInfo, void *traverseSession,
         int *inputXs, int *inputYs, int *times, int *pointerIds, int *inputCodePoints,
-        int inputSize, const float languageWeight,
+        int inputSize, const float weightOfLangModelVsSpatialModel,
         SuggestionResults *const outSuggestionResults) const {
-    PROF_OPEN;
-    PROF_START(0);
+    PROF_INIT;
+    PROF_TIMER_START(0);
     const float maxSpatialDistance = TRAVERSAL->getMaxSpatialDistance();
     DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
     tSession->setupForGetSuggestions(pInfo, inputCodePoints, inputSize, inputXs, inputYs, times,
@@ -55,8 +58,8 @@
     // TODO: Add the way to evaluate cache
 
     initializeSearch(tSession);
-    PROF_END(0);
-    PROF_START(1);
+    PROF_TIMER_END(0);
+    PROF_TIMER_START(1);
 
     // keep expanding search dicNodes until all have terminated.
     while (tSession->getDicTraverseCache()->activeSize() > 0) {
@@ -64,12 +67,11 @@
         tSession->getDicTraverseCache()->advanceActiveDicNodes();
         tSession->getDicTraverseCache()->advanceInputIndex(inputSize);
     }
-    PROF_END(1);
-    PROF_START(2);
+    PROF_TIMER_END(1);
+    PROF_TIMER_START(2);
     SuggestionsOutputUtils::outputSuggestions(
-            SCORING, tSession, languageWeight, outSuggestionResults);
-    PROF_END(2);
-    PROF_CLOSE;
+            SCORING, tSession, weightOfLangModelVsSpatialModel, outSuggestionResults);
+    PROF_TIMER_END(2);
 }
 
 /**
@@ -87,12 +89,13 @@
         traverseSession->getDicTraverseCache()->continueSearch();
     } else {
         // Restart recognition at the root.
-        traverseSession->resetCache(TRAVERSAL->getMaxCacheSize(traverseSession->getInputSize()),
+        traverseSession->resetCache(TRAVERSAL->getMaxCacheSize(traverseSession->getInputSize(),
+                traverseSession->getSuggestOptions()->weightForLocale()),
                 TRAVERSAL->getTerminalCacheSize());
         // Create a new dic node here
         DicNode rootNode;
         DicNodeUtils::initAsRoot(traverseSession->getDictionaryStructurePolicy(),
-                traverseSession->getPrevWordsPtNodePos(), &rootNode);
+                traverseSession->getPrevWordIds(), &rootNode);
         traverseSession->getDicTraverseCache()->copyPushActive(&rootNode);
     }
 }
@@ -157,8 +160,7 @@
             // TODO: Remove. Do not prune node here.
             const bool allowsErrorCorrections = TRAVERSAL->allowsErrorCorrections(&dicNode);
             // Process for handling space substitution (e.g., hevis => he is)
-            if (allowsErrorCorrections
-                    && TRAVERSAL->isSpaceSubstitutionTerminal(traverseSession, &dicNode)) {
+            if (TRAVERSAL->isSpaceSubstitutionTerminal(traverseSession, &dicNode)) {
                 createNextWordDicNode(traverseSession, &dicNode, true /* spaceSubstitution */);
             }
 
@@ -281,7 +283,6 @@
     // not treat the node as a terminal. There is no need to pass the bigram map in these cases.
     Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_ADDITIONAL_PROXIMITY,
             traverseSession, dicNode, childDicNode, 0 /* multiBigramMap */);
-    weightChildNode(traverseSession, childDicNode);
     processExpandedDicNode(traverseSession, childDicNode);
 }
 
@@ -289,7 +290,6 @@
         DicNode *dicNode, DicNode *childDicNode) const {
     Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_SUBSTITUTION, traverseSession,
             dicNode, childDicNode, 0 /* multiBigramMap */);
-    weightChildNode(traverseSession, childDicNode);
     processExpandedDicNode(traverseSession, childDicNode);
 }
 
@@ -400,7 +400,7 @@
     if (dicNode->isCompletion(inputSize)) {
         Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_COMPLETION, traverseSession,
                 0 /* parentDicNode */, dicNode, 0 /* multiBigramMap */);
-    } else { // completion
+    } else {
         Weighting::addCostAndForwardInputIndex(WEIGHTING, CT_MATCH, traverseSession,
                 0 /* parentDicNode */, dicNode, 0 /* multiBigramMap */);
     }
@@ -412,7 +412,16 @@
  */
 void Suggest::createNextWordDicNode(DicTraverseSession *traverseSession, DicNode *dicNode,
         const bool spaceSubstitution) const {
-    if (!TRAVERSAL->isGoodToTraverseNextWord(dicNode)) {
+    const WordAttributes wordAttributes =
+            traverseSession->getDictionaryStructurePolicy()->getWordAttributesInContext(
+                    dicNode->getPrevWordIds(), dicNode->getWordId(),
+                    traverseSession->getMultiBigramMap());
+    if (SuggestionsOutputUtils::shouldBlockWord(traverseSession->getSuggestOptions(),
+            dicNode, wordAttributes, false /* isLastWord */)) {
+        return;
+    }
+
+    if (!TRAVERSAL->isGoodToTraverseNextWord(dicNode, wordAttributes.getProbability())) {
         return;
     }
 
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
index 788e031..65d5918 100644
--- a/native/jni/src/suggest/core/suggest.h
+++ b/native/jni/src/suggest/core/suggest.h
@@ -49,7 +49,8 @@
     AK_FORCE_INLINE virtual ~Suggest() {}
     void getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
             int *times, int *pointerIds, int *inputCodePoints, int inputSize,
-            const float languageWeight, SuggestionResults *const outSuggestionResults) const;
+            const float weightOfLangModelVsSpatialModel,
+            SuggestionResults *const outSuggestionResults) const;
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(Suggest);
diff --git a/native/jni/src/suggest/core/suggest_interface.h b/native/jni/src/suggest/core/suggest_interface.h
index a6e5aef..a05aa9c 100644
--- a/native/jni/src/suggest/core/suggest_interface.h
+++ b/native/jni/src/suggest/core/suggest_interface.h
@@ -28,7 +28,8 @@
  public:
     virtual void getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs,
             int *inputYs, int *times, int *pointerIds, int *inputCodePoints, int inputSize,
-            const float languageWeight, SuggestionResults *const suggestionResults) const = 0;
+            const float weightOfLangModelVsSpatialModel,
+            SuggestionResults *const suggestionResults) const = 0;
     SuggestInterface() {}
     virtual ~SuggestInterface() {}
  private:
diff --git a/native/jni/src/suggest/core/suggest_options.h b/native/jni/src/suggest/core/suggest_options.h
index d456680..4d33129 100644
--- a/native/jni/src/suggest/core/suggest_options.h
+++ b/native/jni/src/suggest/core/suggest_options.h
@@ -42,6 +42,12 @@
         return getBoolOption(SPACE_AWARE_GESTURE_ENABLED);
     }
 
+    AK_FORCE_INLINE float weightForLocale() const {
+        // The weight is in thousands and we want the real value, so we divide by 1000.
+        // NativeSuggestOptions#setWeightForLocale does the opposite processing in Java.
+        return static_cast<float>(getIntOption(WEIGHT_FOR_LOCALE_IN_THOUSANDS)) / 1000.0f;
+    }
+
     AK_FORCE_INLINE bool getAdditionalFeaturesBoolOption(const int key) const {
         return getBoolOption(key + ADDITIONAL_FEATURES_OPTIONS);
     }
@@ -55,9 +61,10 @@
     static const int USE_FULL_EDIT_DISTANCE = 1;
     static const int BLOCK_OFFENSIVE_WORDS = 2;
     static const int SPACE_AWARE_GESTURE_ENABLED = 3;
+    static const int WEIGHT_FOR_LOCALE_IN_THOUSANDS = 4;
     // Additional features options are stored after the other options and used as setting values of
     // experimental features.
-    static const int ADDITIONAL_FEATURES_OPTIONS = 4;
+    static const int ADDITIONAL_FEATURES_OPTIONS = 5;
 
     const int *const mOptions;
     const int mLength;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
deleted file mode 100644
index 6ed65d9..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.cpp
+++ /dev/null
@@ -1,160 +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.
- */
-
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-
-#include <algorithm>
-
-namespace latinime {
-
-// Note that these are corresponding definitions in Java side in DictionaryHeader.
-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::DATE_KEY = "date";
-const char *const HeaderPolicy::LAST_DECAYED_TIME_KEY = "LAST_DECAYED_TIME";
-const char *const HeaderPolicy::UNIGRAM_COUNT_KEY = "UNIGRAM_COUNT";
-const char *const HeaderPolicy::BIGRAM_COUNT_KEY = "BIGRAM_COUNT";
-const char *const HeaderPolicy::EXTENDED_REGION_SIZE_KEY = "EXTENDED_REGION_SIZE";
-// Historical info is information that is needed to support decaying such as timestamp, level and
-// count.
-const char *const HeaderPolicy::HAS_HISTORICAL_INFO_KEY = "HAS_HISTORICAL_INFO";
-const char *const HeaderPolicy::LOCALE_KEY = "locale"; // match Java declaration
-const char *const HeaderPolicy::FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY =
-        "FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP";
-const char *const HeaderPolicy::FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY =
-        "FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID";
-const char *const HeaderPolicy::FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY =
-        "FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS";
-
-const char *const HeaderPolicy::MAX_UNIGRAM_COUNT_KEY = "MAX_UNIGRAM_COUNT";
-const char *const HeaderPolicy::MAX_BIGRAM_COUNT_KEY = "MAX_BIGRAM_COUNT";
-
-const int HeaderPolicy::DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE = 100;
-const float HeaderPolicy::MULTIPLE_WORD_COST_MULTIPLIER_SCALE = 100.0f;
-const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP = 2;
-const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID = 3;
-// 30 days
-const int HeaderPolicy::DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS =
-        30 * 24 * 60 * 60;
-
-const int HeaderPolicy::DEFAULT_MAX_UNIGRAM_COUNT = 10000;
-const int HeaderPolicy::DEFAULT_MAX_BIGRAM_COUNT = 10000;
-
-// Used for logging. Question mark is used to indicate that the key is not found.
-void HeaderPolicy::readHeaderValueOrQuestionMark(const char *const key, int *outValue,
-        int outValueSize) const {
-    if (outValueSize <= 0) return;
-    if (outValueSize == 1) {
-        outValue[0] = '\0';
-        return;
-    }
-    std::vector<int> keyCodePointVector;
-    HeaderReadWriteUtils::insertCharactersIntoVector(key, &keyCodePointVector);
-    DictionaryHeaderStructurePolicy::AttributeMap::const_iterator it =
-            mAttributeMap.find(keyCodePointVector);
-    if (it == mAttributeMap.end()) {
-        // The key was not found.
-        outValue[0] = '?';
-        outValue[1] = '\0';
-        return;
-    }
-    const int terminalIndex = std::min(static_cast<int>(it->second.size()), outValueSize - 1);
-    for (int i = 0; i < terminalIndex; ++i) {
-        outValue[i] = it->second[i];
-    }
-    outValue[terminalIndex] = '\0';
-}
-
-const std::vector<int> HeaderPolicy::readLocale() const {
-    return HeaderReadWriteUtils::readCodePointVectorAttributeValue(&mAttributeMap, LOCALE_KEY);
-}
-
-float HeaderPolicy::readMultipleWordCostMultiplier() const {
-    const int demotionRate = HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-            MULTIPLE_WORDS_DEMOTION_RATE_KEY, DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE);
-    if (demotionRate <= 0) {
-        return static_cast<float>(MAX_VALUE_FOR_WEIGHTING);
-    }
-    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::fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
-        const int unigramCount, const int bigramCount,
-        const int extendedRegionSize, BufferWithExtendableBuffer *const outBuffer) const {
-    int writingPos = 0;
-    DictionaryHeaderStructurePolicy::AttributeMap attributeMapToWrite(mAttributeMap);
-    fillInHeader(updatesLastDecayedTime, unigramCount, bigramCount,
-            extendedRegionSize, &attributeMapToWrite);
-    if (!HeaderReadWriteUtils::writeDictionaryVersion(outBuffer, mDictFormatVersion,
-            &writingPos)) {
-        return false;
-    }
-    if (!HeaderReadWriteUtils::writeDictionaryFlags(outBuffer, mDictionaryFlags,
-            &writingPos)) {
-        return false;
-    }
-    // Temporarily writes a dummy header size.
-    int headerSizeFieldPos = writingPos;
-    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(outBuffer, 0 /* size */,
-            &writingPos)) {
-        return false;
-    }
-    if (!HeaderReadWriteUtils::writeHeaderAttributes(outBuffer, &attributeMapToWrite,
-            &writingPos)) {
-        return false;
-    }
-    // Writes the actual header size.
-    if (!HeaderReadWriteUtils::writeDictionaryHeaderSize(outBuffer, writingPos,
-            &headerSizeFieldPos)) {
-        return false;
-    }
-    return true;
-}
-
-void HeaderPolicy::fillInHeader(const bool updatesLastDecayedTime, const int unigramCount,
-        const int bigramCount, const int extendedRegionSize,
-        DictionaryHeaderStructurePolicy::AttributeMap *outAttributeMap) const {
-    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, UNIGRAM_COUNT_KEY, unigramCount);
-    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, BIGRAM_COUNT_KEY, bigramCount);
-    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, EXTENDED_REGION_SIZE_KEY,
-            extendedRegionSize);
-    // Set the current time as the generation time.
-    HeaderReadWriteUtils::setIntAttribute(outAttributeMap, DATE_KEY,
-            TimeKeeper::peekCurrentTime());
-    HeaderReadWriteUtils::setCodePointVectorAttribute(outAttributeMap, LOCALE_KEY, mLocale);
-    if (updatesLastDecayedTime) {
-        // Set current time as the last updated time.
-        HeaderReadWriteUtils::setIntAttribute(outAttributeMap, LAST_DECAYED_TIME_KEY,
-                TimeKeeper::peekCurrentTime());
-    }
-}
-
-/* static */ DictionaryHeaderStructurePolicy::AttributeMap
-        HeaderPolicy::createAttributeMapAndReadAllAttributes(const uint8_t *const dictBuf) {
-    DictionaryHeaderStructurePolicy::AttributeMap attributeMap;
-    HeaderReadWriteUtils::fetchAllHeaderAttributes(dictBuf, &attributeMap);
-    return attributeMap;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h b/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
deleted file mode 100644
index 87cf0cd..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_policy.h
+++ /dev/null
@@ -1,307 +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.
- */
-
-#ifndef LATINIME_HEADER_POLICY_H
-#define LATINIME_HEADER_POLICY_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "utils/char_utils.h"
-#include "utils/time_keeper.h"
-
-namespace latinime {
-
-class HeaderPolicy : public DictionaryHeaderStructurePolicy {
- public:
-    // Reads information from existing dictionary buffer.
-    HeaderPolicy(const uint8_t *const dictBuf, const FormatUtils::FORMAT_VERSION formatVersion)
-            : mDictFormatVersion(formatVersion),
-              mDictionaryFlags(HeaderReadWriteUtils::getFlags(dictBuf)),
-              mSize(HeaderReadWriteUtils::getHeaderSize(dictBuf)),
-              mAttributeMap(createAttributeMapAndReadAllAttributes(dictBuf)),
-              mLocale(readLocale()),
-              mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
-              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
-              mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
-                      IS_DECAYING_DICT_KEY, false /* defaultValue */)),
-              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
-              mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      LAST_DECAYED_TIME_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
-              mUnigramCount(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      UNIGRAM_COUNT_KEY, 0 /* defaultValue */)),
-              mBigramCount(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      BIGRAM_COUNT_KEY, 0 /* defaultValue */)),
-              mExtendedRegionSize(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      EXTENDED_REGION_SIZE_KEY, 0 /* defaultValue */)),
-              mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue(
-                      &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)),
-              mForgettingCurveOccurrencesToLevelUp(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY,
-                      DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP)),
-              mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY,
-                      DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)),
-              mForgettingCurveDurationToLevelDown(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY,
-                      DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS)),
-              mMaxUnigramCount(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, MAX_UNIGRAM_COUNT_KEY, DEFAULT_MAX_UNIGRAM_COUNT)),
-              mMaxBigramCount(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, MAX_BIGRAM_COUNT_KEY, DEFAULT_MAX_BIGRAM_COUNT)) {}
-
-    // Constructs header information using an attribute map.
-    HeaderPolicy(const FormatUtils::FORMAT_VERSION dictFormatVersion,
-            const std::vector<int> &locale,
-            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap)
-            : mDictFormatVersion(dictFormatVersion),
-              mDictionaryFlags(HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
-                      attributeMap)), mSize(0), mAttributeMap(*attributeMap), mLocale(locale),
-              mMultiWordCostMultiplier(readMultipleWordCostMultiplier()),
-              mRequiresGermanUmlautProcessing(readRequiresGermanUmlautProcessing()),
-              mIsDecayingDict(HeaderReadWriteUtils::readBoolAttributeValue(&mAttributeMap,
-                      IS_DECAYING_DICT_KEY, false /* defaultValue */)),
-              mDate(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
-              mLastDecayedTime(HeaderReadWriteUtils::readIntAttributeValue(&mAttributeMap,
-                      DATE_KEY, TimeKeeper::peekCurrentTime() /* defaultValue */)),
-              mUnigramCount(0), mBigramCount(0), mExtendedRegionSize(0),
-              mHasHistoricalInfoOfWords(HeaderReadWriteUtils::readBoolAttributeValue(
-                      &mAttributeMap, HAS_HISTORICAL_INFO_KEY, false /* defaultValue */)),
-              mForgettingCurveOccurrencesToLevelUp(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY,
-                      DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP)),
-              mForgettingCurveProbabilityValuesTableId(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY,
-                      DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID)),
-              mForgettingCurveDurationToLevelDown(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY,
-                      DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS)),
-              mMaxUnigramCount(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, MAX_UNIGRAM_COUNT_KEY, DEFAULT_MAX_UNIGRAM_COUNT)),
-              mMaxBigramCount(HeaderReadWriteUtils::readIntAttributeValue(
-                      &mAttributeMap, MAX_BIGRAM_COUNT_KEY, DEFAULT_MAX_BIGRAM_COUNT)) {}
-
-    // Copy header information
-    HeaderPolicy(const HeaderPolicy *const headerPolicy)
-            : mDictFormatVersion(headerPolicy->mDictFormatVersion),
-              mDictionaryFlags(headerPolicy->mDictionaryFlags), mSize(headerPolicy->mSize),
-              mAttributeMap(headerPolicy->mAttributeMap), mLocale(headerPolicy->mLocale),
-              mMultiWordCostMultiplier(headerPolicy->mMultiWordCostMultiplier),
-              mRequiresGermanUmlautProcessing(headerPolicy->mRequiresGermanUmlautProcessing),
-              mIsDecayingDict(headerPolicy->mIsDecayingDict),
-              mDate(headerPolicy->mDate), mLastDecayedTime(headerPolicy->mLastDecayedTime),
-              mUnigramCount(headerPolicy->mUnigramCount), mBigramCount(headerPolicy->mBigramCount),
-              mExtendedRegionSize(headerPolicy->mExtendedRegionSize),
-              mHasHistoricalInfoOfWords(headerPolicy->mHasHistoricalInfoOfWords),
-              mForgettingCurveOccurrencesToLevelUp(
-                      headerPolicy->mForgettingCurveOccurrencesToLevelUp),
-              mForgettingCurveProbabilityValuesTableId(
-                      headerPolicy->mForgettingCurveProbabilityValuesTableId),
-              mForgettingCurveDurationToLevelDown(
-                      headerPolicy->mForgettingCurveDurationToLevelDown),
-              mMaxUnigramCount(headerPolicy->mMaxUnigramCount),
-              mMaxBigramCount(headerPolicy->mMaxBigramCount) {}
-
-    // Temporary dummy header.
-    HeaderPolicy()
-            : mDictFormatVersion(FormatUtils::UNKNOWN_VERSION), mDictionaryFlags(0), mSize(0),
-              mAttributeMap(), mLocale(CharUtils::EMPTY_STRING), mMultiWordCostMultiplier(0.0f),
-              mRequiresGermanUmlautProcessing(false), mIsDecayingDict(false),
-              mDate(0), mLastDecayedTime(0), mUnigramCount(0), mBigramCount(0),
-              mExtendedRegionSize(0), mHasHistoricalInfoOfWords(false),
-              mForgettingCurveOccurrencesToLevelUp(0), mForgettingCurveProbabilityValuesTableId(0),
-              mForgettingCurveDurationToLevelDown(0), mMaxUnigramCount(0), mMaxBigramCount(0) {}
-
-    ~HeaderPolicy() {}
-
-    virtual int getFormatVersionNumber() const {
-        // Conceptually this converts the symbolic value we use in the code into the
-        // hardcoded of the bytes in the file. But we want the constants to be the
-        // same so we use them for both here.
-        switch (mDictFormatVersion) {
-            case FormatUtils::VERSION_2:
-                return FormatUtils::VERSION_2;
-            case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-                return FormatUtils::VERSION_4_ONLY_FOR_TESTING;
-            case FormatUtils::VERSION_4:
-                return FormatUtils::VERSION_4;
-            case FormatUtils::VERSION_4_DEV:
-                return FormatUtils::VERSION_4_DEV;
-            default:
-                return FormatUtils::UNKNOWN_VERSION;
-        }
-    }
-
-    AK_FORCE_INLINE bool isValid() const {
-        // Decaying dictionary must have historical information.
-        if (!mIsDecayingDict) {
-            return true;
-        }
-        if (mHasHistoricalInfoOfWords) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    AK_FORCE_INLINE int getSize() const {
-        return mSize;
-    }
-
-    AK_FORCE_INLINE float getMultiWordCostMultiplier() const {
-        return mMultiWordCostMultiplier;
-    }
-
-    AK_FORCE_INLINE bool isDecayingDict() const {
-        return mIsDecayingDict;
-    }
-
-    AK_FORCE_INLINE bool requiresGermanUmlautProcessing() const {
-        return mRequiresGermanUmlautProcessing;
-    }
-
-    AK_FORCE_INLINE int getDate() const {
-        return mDate;
-    }
-
-    AK_FORCE_INLINE int getLastDecayedTime() const {
-        return mLastDecayedTime;
-    }
-
-    AK_FORCE_INLINE int getUnigramCount() const {
-        return mUnigramCount;
-    }
-
-    AK_FORCE_INLINE int getBigramCount() const {
-        return mBigramCount;
-    }
-
-    AK_FORCE_INLINE int getExtendedRegionSize() const {
-        return mExtendedRegionSize;
-    }
-
-    AK_FORCE_INLINE bool hasHistoricalInfoOfWords() const {
-        return mHasHistoricalInfoOfWords;
-    }
-
-    AK_FORCE_INLINE bool shouldBoostExactMatches() const {
-        // TODO: Investigate better ways to handle exact matches for personalized dictionaries.
-        return !isDecayingDict();
-    }
-
-    const DictionaryHeaderStructurePolicy::AttributeMap *getAttributeMap() const {
-        return &mAttributeMap;
-    }
-
-    AK_FORCE_INLINE int getForgettingCurveOccurrencesToLevelUp() const {
-        return mForgettingCurveOccurrencesToLevelUp;
-    }
-
-    AK_FORCE_INLINE int getForgettingCurveProbabilityValuesTableId() const {
-        return mForgettingCurveProbabilityValuesTableId;
-    }
-
-    AK_FORCE_INLINE int getForgettingCurveDurationToLevelDown() const {
-        return mForgettingCurveDurationToLevelDown;
-    }
-
-    AK_FORCE_INLINE int getMaxUnigramCount() const {
-        return mMaxUnigramCount;
-    }
-
-    AK_FORCE_INLINE int getMaxBigramCount() const {
-        return mMaxBigramCount;
-    }
-
-    void readHeaderValueOrQuestionMark(const char *const key,
-            int *outValue, int outValueSize) const;
-
-    bool fillInAndWriteHeaderToBuffer(const bool updatesLastDecayedTime,
-            const int unigramCount, const int bigramCount,
-            const int extendedRegionSize, BufferWithExtendableBuffer *const outBuffer) const;
-
-    void fillInHeader(const bool updatesLastDecayedTime,
-            const int unigramCount, const int bigramCount, const int extendedRegionSize,
-            DictionaryHeaderStructurePolicy::AttributeMap *outAttributeMap) const;
-
-    AK_FORCE_INLINE const std::vector<int> *getLocale() const {
-        return &mLocale;
-    }
-
-    bool supportsBeginningOfSentence() const {
-        return mDictFormatVersion >= FormatUtils::VERSION_4;
-    }
-
- private:
-    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 DATE_KEY;
-    static const char *const LAST_DECAYED_TIME_KEY;
-    static const char *const UNIGRAM_COUNT_KEY;
-    static const char *const BIGRAM_COUNT_KEY;
-    static const char *const EXTENDED_REGION_SIZE_KEY;
-    static const char *const HAS_HISTORICAL_INFO_KEY;
-    static const char *const LOCALE_KEY;
-    static const char *const FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP_KEY;
-    static const char *const FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID_KEY;
-    static const char *const FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS_KEY;
-    static const char *const MAX_UNIGRAM_COUNT_KEY;
-    static const char *const MAX_BIGRAM_COUNT_KEY;
-    static const int DEFAULT_MULTIPLE_WORDS_DEMOTION_RATE;
-    static const float MULTIPLE_WORD_COST_MULTIPLIER_SCALE;
-    static const int DEFAULT_FORGETTING_CURVE_OCCURRENCES_TO_LEVEL_UP;
-    static const int DEFAULT_FORGETTING_CURVE_PROBABILITY_VALUES_TABLE_ID;
-    static const int DEFAULT_FORGETTING_CURVE_DURATION_TO_LEVEL_DOWN_IN_SECONDS;
-    static const int DEFAULT_MAX_UNIGRAM_COUNT;
-    static const int DEFAULT_MAX_BIGRAM_COUNT;
-
-    const FormatUtils::FORMAT_VERSION mDictFormatVersion;
-    const HeaderReadWriteUtils::DictionaryFlags mDictionaryFlags;
-    const int mSize;
-    DictionaryHeaderStructurePolicy::AttributeMap mAttributeMap;
-    const std::vector<int> mLocale;
-    const float mMultiWordCostMultiplier;
-    const bool mRequiresGermanUmlautProcessing;
-    const bool mIsDecayingDict;
-    const int mDate;
-    const int mLastDecayedTime;
-    const int mUnigramCount;
-    const int mBigramCount;
-    const int mExtendedRegionSize;
-    const bool mHasHistoricalInfoOfWords;
-    const int mForgettingCurveOccurrencesToLevelUp;
-    const int mForgettingCurveProbabilityValuesTableId;
-    const int mForgettingCurveDurationToLevelDown;
-    const int mMaxUnigramCount;
-    const int mMaxBigramCount;
-
-    const std::vector<int> readLocale() const;
-    float readMultipleWordCostMultiplier() const;
-    bool readRequiresGermanUmlautProcessing() const;
-
-    static DictionaryHeaderStructurePolicy::AttributeMap createAttributeMapAndReadAllAttributes(
-            const uint8_t *const dictBuf);
-};
-} // namespace latinime
-#endif /* LATINIME_HEADER_POLICY_H */
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
deleted file mode 100644
index a8f8f28..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.cpp
+++ /dev/null
@@ -1,231 +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.
- */
-
-#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
-
-#include <cctype>
-#include <cstdio>
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-// Number of base-10 digits in the largest integer + 1 to leave room for a zero terminator.
-// As such, this is the maximum number of characters will be needed to represent an int as a
-// string, including the terminator; this is used as the size of a string buffer large enough to
-// hold any value that is intended to fit in an integer, e.g. in the code that reads the header
-// of the binary dictionary where a {key,value} string pair scheme is used.
-const int HeaderReadWriteUtils::LARGEST_INT_DIGIT_COUNT = 11;
-
-const int HeaderReadWriteUtils::MAX_ATTRIBUTE_KEY_LENGTH = 256;
-const int HeaderReadWriteUtils::MAX_ATTRIBUTE_VALUE_LENGTH = 256;
-
-const int HeaderReadWriteUtils::HEADER_MAGIC_NUMBER_SIZE = 4;
-const int HeaderReadWriteUtils::HEADER_DICTIONARY_VERSION_SIZE = 2;
-const int HeaderReadWriteUtils::HEADER_FLAG_SIZE = 2;
-const int HeaderReadWriteUtils::HEADER_SIZE_FIELD_SIZE = 4;
-
-const HeaderReadWriteUtils::DictionaryFlags HeaderReadWriteUtils::NO_FLAGS = 0;
-
-typedef DictionaryHeaderStructurePolicy::AttributeMap AttributeMap;
-
-/* static */ int HeaderReadWriteUtils::getHeaderSize(const uint8_t *const dictBuf) {
-    // See the format of the header in the comment in
-    // BinaryDictionaryFormatUtils::detectFormatVersion()
-    return ByteArrayUtils::readUint32(dictBuf, HEADER_MAGIC_NUMBER_SIZE
-            + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE);
-}
-
-/* static */ HeaderReadWriteUtils::DictionaryFlags
-        HeaderReadWriteUtils::getFlags(const uint8_t *const dictBuf) {
-    return ByteArrayUtils::readUint16(dictBuf,
-            HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE);
-}
-
-/* static */ HeaderReadWriteUtils::DictionaryFlags
-        HeaderReadWriteUtils::createAndGetDictionaryFlagsUsingAttributeMap(
-                const AttributeMap *const attributeMap) {
-    return NO_FLAGS;
-}
-
-/* static */ void HeaderReadWriteUtils::fetchAllHeaderAttributes(const uint8_t *const dictBuf,
-        AttributeMap *const headerAttributes) {
-    const int headerSize = getHeaderSize(dictBuf);
-    int pos = getHeaderOptionsPosition();
-    if (pos == NOT_A_DICT_POS) {
-        // The header doesn't have header options.
-        return;
-    }
-    int keyBuffer[MAX_ATTRIBUTE_KEY_LENGTH];
-    int valueBuffer[MAX_ATTRIBUTE_VALUE_LENGTH];
-    while (pos < headerSize) {
-        const int keyLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
-                MAX_ATTRIBUTE_KEY_LENGTH, keyBuffer, &pos);
-        std::vector<int> key;
-        key.insert(key.end(), keyBuffer, keyBuffer + keyLength);
-        const int valueLength = ByteArrayUtils::readStringAndAdvancePosition(dictBuf,
-                MAX_ATTRIBUTE_VALUE_LENGTH, valueBuffer, &pos);
-        std::vector<int> value;
-        value.insert(value.end(), valueBuffer, valueBuffer + valueLength);
-        headerAttributes->insert(AttributeMap::value_type(key, value));
-    }
-}
-
-/* static */ bool HeaderReadWriteUtils::writeDictionaryVersion(
-        BufferWithExtendableBuffer *const buffer, const FormatUtils::FORMAT_VERSION version,
-        int *const writingPos) {
-    if (!buffer->writeUintAndAdvancePosition(FormatUtils::MAGIC_NUMBER, HEADER_MAGIC_NUMBER_SIZE,
-            writingPos)) {
-        return false;
-    }
-    switch (version) {
-        case FormatUtils::VERSION_2:
-            // Version 2 dictionary writing is not supported.
-            return false;
-        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-        case FormatUtils::VERSION_4:
-        case FormatUtils::VERSION_4_DEV:
-            return buffer->writeUintAndAdvancePosition(version /* data */,
-                    HEADER_DICTIONARY_VERSION_SIZE, writingPos);
-        default:
-            return false;
-    }
-}
-
-/* static */ bool HeaderReadWriteUtils::writeDictionaryFlags(
-        BufferWithExtendableBuffer *const buffer, const DictionaryFlags flags,
-        int *const writingPos) {
-    return buffer->writeUintAndAdvancePosition(flags, HEADER_FLAG_SIZE, writingPos);
-}
-
-/* static */ bool HeaderReadWriteUtils::writeDictionaryHeaderSize(
-        BufferWithExtendableBuffer *const buffer, const int size, int *const writingPos) {
-    return buffer->writeUintAndAdvancePosition(size, HEADER_SIZE_FIELD_SIZE, writingPos);
-}
-
-/* static */ bool HeaderReadWriteUtils::writeHeaderAttributes(
-        BufferWithExtendableBuffer *const buffer, const AttributeMap *const headerAttributes,
-        int *const writingPos) {
-    for (AttributeMap::const_iterator it = headerAttributes->begin();
-            it != headerAttributes->end(); ++it) {
-        if (it->first.empty() || it->second.empty()) {
-            continue;
-        }
-        // Write a key.
-        if (!buffer->writeCodePointsAndAdvancePosition(&(it->first.at(0)), it->first.size(),
-                true /* writesTerminator */, writingPos)) {
-            return false;
-        }
-        // Write a value.
-        if (!buffer->writeCodePointsAndAdvancePosition(&(it->second.at(0)), it->second.size(),
-                true /* writesTerminator */, writingPos)) {
-            return false;
-        }
-    }
-    return true;
-}
-
-/* static */ void HeaderReadWriteUtils::setCodePointVectorAttribute(
-        AttributeMap *const headerAttributes, const char *const key, const std::vector<int> value) {
-    AttributeMap::key_type keyVector;
-    insertCharactersIntoVector(key, &keyVector);
-    (*headerAttributes)[keyVector] = value;
-}
-
-/* static */ void HeaderReadWriteUtils::setBoolAttribute(AttributeMap *const headerAttributes,
-        const char *const key, const bool value) {
-    setIntAttribute(headerAttributes, key, value ? 1 : 0);
-}
-
-/* static */ void HeaderReadWriteUtils::setIntAttribute(AttributeMap *const headerAttributes,
-        const char *const key, const int value) {
-    AttributeMap::key_type keyVector;
-    insertCharactersIntoVector(key, &keyVector);
-    setIntAttributeInner(headerAttributes, &keyVector, value);
-}
-
-/* static */ void HeaderReadWriteUtils::setIntAttributeInner(AttributeMap *const headerAttributes,
-        const AttributeMap::key_type *const key, const int value) {
-    AttributeMap::mapped_type valueVector;
-    char charBuf[LARGEST_INT_DIGIT_COUNT];
-    snprintf(charBuf, sizeof(charBuf), "%d", value);
-    insertCharactersIntoVector(charBuf, &valueVector);
-    (*headerAttributes)[*key] = valueVector;
-}
-
-/* static */ const std::vector<int> HeaderReadWriteUtils::readCodePointVectorAttributeValue(
-        const AttributeMap *const headerAttributes, const char *const key) {
-    AttributeMap::key_type keyVector;
-    insertCharactersIntoVector(key, &keyVector);
-    AttributeMap::const_iterator it = headerAttributes->find(keyVector);
-    if (it == headerAttributes->end()) {
-        return std::vector<int>();
-    } else {
-        return it->second;
-    }
-}
-
-/* static */ bool HeaderReadWriteUtils::readBoolAttributeValue(
-        const AttributeMap *const headerAttributes, const char *const key,
-        const bool defaultValue) {
-    const int intDefaultValue = defaultValue ? 1 : 0;
-    const int intValue = readIntAttributeValue(headerAttributes, key, intDefaultValue);
-    return intValue != 0;
-}
-
-/* static */ int HeaderReadWriteUtils::readIntAttributeValue(
-        const AttributeMap *const headerAttributes, const char *const key,
-        const int defaultValue) {
-    AttributeMap::key_type keyVector;
-    insertCharactersIntoVector(key, &keyVector);
-    return readIntAttributeValueInner(headerAttributes, &keyVector, defaultValue);
-}
-
-/* static */ int HeaderReadWriteUtils::readIntAttributeValueInner(
-        const AttributeMap *const headerAttributes, const AttributeMap::key_type *const key,
-        const int defaultValue) {
-    AttributeMap::const_iterator it = headerAttributes->find(*key);
-    if (it != headerAttributes->end()) {
-        int value = 0;
-        bool isNegative = false;
-        for (size_t i = 0; i < it->second.size(); ++i) {
-            if (i == 0 && it->second.at(i) == '-') {
-                isNegative = true;
-            } else {
-                if (!isdigit(it->second.at(i))) {
-                    // If not a number.
-                    return defaultValue;
-                }
-                value *= 10;
-                value += it->second.at(i) - '0';
-            }
-        }
-        return isNegative ? -value : value;
-    }
-    return defaultValue;
-}
-
-/* static */ void HeaderReadWriteUtils::insertCharactersIntoVector(const char *const characters,
-        std::vector<int> *const vector) {
-    for (int i = 0; characters[i]; ++i) {
-        vector->push_back(characters[i]);
-    }
-}
-
-} // namespace latinime
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
deleted file mode 100644
index 9b90488..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/header/header_read_write_utils.h
+++ /dev/null
@@ -1,118 +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.
- */
-
-#ifndef LATINIME_HEADER_READ_WRITE_UTILS_H
-#define LATINIME_HEADER_READ_WRITE_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-
-class HeaderReadWriteUtils {
- public:
-    typedef uint16_t DictionaryFlags;
-
-    static int getHeaderSize(const uint8_t *const dictBuf);
-
-    static DictionaryFlags getFlags(const uint8_t *const dictBuf);
-
-    static AK_FORCE_INLINE int getHeaderOptionsPosition() {
-        return HEADER_MAGIC_NUMBER_SIZE + HEADER_DICTIONARY_VERSION_SIZE + HEADER_FLAG_SIZE
-                + HEADER_SIZE_FIELD_SIZE;
-    }
-
-    static DictionaryFlags createAndGetDictionaryFlagsUsingAttributeMap(
-            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
-
-    static void fetchAllHeaderAttributes(const uint8_t *const dictBuf,
-            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes);
-
-    static bool writeDictionaryVersion(BufferWithExtendableBuffer *const buffer,
-            const FormatUtils::FORMAT_VERSION version, int *const writingPos);
-
-    static bool writeDictionaryFlags(BufferWithExtendableBuffer *const buffer,
-            const DictionaryFlags flags, int *const writingPos);
-
-    static bool writeDictionaryHeaderSize(BufferWithExtendableBuffer *const buffer,
-            const int size, int *const writingPos);
-
-    static bool writeHeaderAttributes(BufferWithExtendableBuffer *const buffer,
-            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            int *const writingPos);
-
-    /**
-     * Methods for header attributes.
-     */
-    static void setCodePointVectorAttribute(
-            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key, const std::vector<int> value);
-
-    static void setBoolAttribute(
-            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key, const bool value);
-
-    static void setIntAttribute(
-            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key, const int value);
-
-    static const std::vector<int> readCodePointVectorAttributeValue(
-            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key);
-
-    static bool readBoolAttributeValue(
-            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key, const bool defaultValue);
-
-    static int readIntAttributeValue(
-            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const char *const key, const int defaultValue);
-
-    static void insertCharactersIntoVector(const char *const characters,
-            DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(HeaderReadWriteUtils);
-
-    static const int LARGEST_INT_DIGIT_COUNT;
-    static const int MAX_ATTRIBUTE_KEY_LENGTH;
-    static const int MAX_ATTRIBUTE_VALUE_LENGTH;
-
-    static const int HEADER_MAGIC_NUMBER_SIZE;
-    static const int HEADER_DICTIONARY_VERSION_SIZE;
-    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;
-
-    static void setIntAttributeInner(
-            DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key,
-            const int value);
-
-    static int readIntAttributeValueInner(
-            const DictionaryHeaderStructurePolicy::AttributeMap *const headerAttributes,
-            const DictionaryHeaderStructurePolicy::AttributeMap::key_type *const key,
-            const int defaultValue);
-};
-}
-#endif /* LATINIME_HEADER_READ_WRITE_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
deleted file mode 100644
index 3e8e059..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.cpp
+++ /dev/null
@@ -1,290 +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.
- */
-
-/*
- * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
- * Do not edit this file other than updating policy's interface.
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
-
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability,
-        bool *const outHasNext, int *const bigramEntryPos) const {
-    const BigramEntry bigramEntry =
-            mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos);
-    if (outBigramPos) {
-        // Lookup target PtNode position.
-        *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-    }
-    if (outProbability) {
-        if (bigramEntry.hasHistoricalInfo()) {
-            *outProbability =
-                    ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(),
-                            mHeaderPolicy);
-        } else {
-            *outProbability = bigramEntry.getProbability();
-        }
-    }
-    if (outHasNext) {
-        *outHasNext = bigramEntry.hasNext();
-    }
-}
-
-bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
-        const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
-    // 1. The word has no bigrams yet.
-    // 2. The word has bigrams, and there is the target in the list.
-    // 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
-    // 4. The word has bigrams. We have to append new bigram entry to the list.
-    // 5. Same as 4, but the list is the last entry of the content file.
-    if (outAddedNewEntry) {
-        *outAddedNewEntry = false;
-    }
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Case 1. PtNode that doesn't have a bigram list.
-        // Create new bigram list.
-        if (!mBigramDictContent->createNewBigramList(terminalId)) {
-            return false;
-        }
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
-                bigramProperty);
-        // Write an entry.
-        const int writingPos =  mBigramDictContent->getBigramListHeadPos(terminalId);
-        if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) {
-            return false;
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    int tailEntryPos = NOT_A_DICT_POS;
-    const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos,
-            &tailEntryPos);
-    if (tailEntryPos != NOT_A_DICT_POS || entryPosToUpdate == NOT_A_DICT_POS) {
-        // Case 4, 5.
-        // Add new entry to the bigram list.
-        if (tailEntryPos == NOT_A_DICT_POS) {
-            // Case 4. Create new bigram list.
-            if (!mBigramDictContent->createNewBigramList(terminalId)) {
-                return false;
-            }
-            const int destPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-            // Copy existing bigram list.
-            if (!mBigramDictContent->copyBigramList(bigramListPos, destPos, &tailEntryPos)) {
-                return false;
-            }
-        }
-        // Write new entry at the tail position of the bigram content.
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-                &newBigramEntry, bigramProperty);
-        if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) {
-            return false;
-        }
-        // Update has next flag of the tail entry.
-        if (!updateHasNextFlag(true /* hasNext */, tailEntryPos)) {
-            return false;
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry.
-    const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (!originalBigramEntry.isValid()) {
-        // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing
-        // entry is updated.
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-    }
-    const BigramEntry updatedBigramEntry =
-            originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
-    const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-            &updatedBigramEntry, bigramProperty);
-    return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return false;
-    }
-    const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos,
-            nullptr /* outTailEntryPos */);
-    if (entryPosToUpdate == NOT_A_DICT_POS) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (targetTerminalId != bigramEntry.getTargetTerminalId()) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    // Remove bigram entry by marking it as invalid entry and overwriting the original entry.
-    const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-        int *const outBigramCount) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return true;
-    }
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const int entryPos = readingPos;
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (!bigramEntry.isValid()) {
-            continue;
-        }
-        const int targetPtNodePos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-        if (targetPtNodePos == NOT_A_DICT_POS) {
-            // Invalidate bigram entry.
-            const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-            if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                return false;
-            }
-        } else if (bigramEntry.hasHistoricalInfo()) {
-            const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
-                    bigramEntry.getHistoricalInfo(), mHeaderPolicy);
-            if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) {
-                const BigramEntry updatedBigramEntry =
-                        bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo);
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-                *outBigramCount += 1;
-            } else {
-                // Remove entry.
-                const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-            }
-        } else {
-            *outBigramCount += 1;
-        }
-    }
-    return true;
-}
-
-int Ver4BigramListPolicy::getBigramEntryConut(const int terminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return 0;
-    }
-    int bigramCount = 0;
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (bigramEntry.isValid()) {
-            bigramCount++;
-        }
-    }
-    return bigramCount;
-}
-
-int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
-        const int bigramListPos, int *const outTailEntryPos) const {
-    if (outTailEntryPos) {
-        *outTailEntryPos = NOT_A_DICT_POS;
-    }
-    bool hasNext = true;
-    int invalidEntryPos = NOT_A_DICT_POS;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const int entryPos = readingPos;
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (bigramEntry.getTargetTerminalId() == targetTerminalIdToFind) {
-            // Entry with same target is found.
-            return entryPos;
-        } else if (!bigramEntry.isValid()) {
-            // Invalid entry that can be reused is found.
-            invalidEntryPos = entryPos;
-        }
-        if (!hasNext && mBigramDictContent->isContentTailPos(readingPos)) {
-            if (outTailEntryPos) {
-                *outTailEntryPos = entryPos;
-            }
-        }
-    }
-    return invalidEntryPos;
-}
-
-const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
-        const BigramEntry *const originalBigramEntry,
-        const BigramProperty *const bigramProperty) const {
-    // TODO: Consolidate historical info and probability.
-    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(bigramProperty->getTimestamp(),
-                bigramProperty->getLevel(), bigramProperty->getCount());
-        const HistoricalInfo updatedHistoricalInfo =
-                ForgettingCurveUtils::createUpdatedHistoricalInfo(
-                        originalBigramEntry->getHistoricalInfo(), bigramProperty->getProbability(),
-                        &historicalInfoForUpdate, mHeaderPolicy);
-        return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
-    } else {
-        return originalBigramEntry->updateProbabilityAndGetEntry(bigramProperty->getProbability());
-    }
-}
-
-bool Ver4BigramListPolicy::updateHasNextFlag(const bool hasNext, const int bigramEntryPos) {
-    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(bigramEntryPos);
-    const BigramEntry updatedBigramEntry = bigramEntry.updateHasNextAndGetEntry(hasNext);
-    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, bigramEntryPos);
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
deleted file mode 100644
index 50a4c97..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h
+++ /dev/null
@@ -1,94 +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.
- */
-
-/*
- * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
- * Do not edit this file other than updating policy's interface.
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H
-#define LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class BigramDictContent;
-} // namespace v402
-} // namespace backward
-class BigramProperty;
-namespace backward {
-namespace v402 {
-} // namespace v402
-} // namespace backward
-class HeaderPolicy;
-namespace backward {
-namespace v402 {
-class TerminalPositionLookupTable;
-
-class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
- public:
-    Ver4BigramListPolicy(BigramDictContent *const bigramDictContent,
-            const TerminalPositionLookupTable *const terminalPositionLookupTable,
-            const HeaderPolicy *const headerPolicy)
-            : mBigramDictContent(bigramDictContent),
-              mTerminalPositionLookupTable(terminalPositionLookupTable),
-              mHeaderPolicy(headerPolicy) {}
-
-    void getNextBigram(int *const outBigramPos, int *const outProbability,
-            bool *const outHasNext, int *const bigramEntryPos) const;
-
-    bool skipAllBigrams(int *const pos) const {
-        // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
-        return true;
-    }
-
-    bool addNewEntry(const int terminalId, const int newTargetTerminalId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    bool removeEntry(const int terminalId, const int targetTerminalId);
-
-    bool updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-            int *const outBigramCount);
-
-    int getBigramEntryConut(const int terminalId);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy);
-
-    int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos,
-            int *const outTailEntryPos) const;
-
-    const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
-            const BigramProperty *const bigramProperty) const;
-
-    bool updateHasNextFlag(const bool hasNext, const int bigramEntryPos);
-
-    BigramDictContent *const mBigramDictContent;
-    const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
-    const HeaderPolicy *const mHeaderPolicy;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_BIGRAM_LIST_POLICY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
deleted file mode 100644
index e2dd93c..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.cpp
+++ /dev/null
@@ -1,224 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition(
-        int *const bigramEntryPos) const {
-    const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer();
-    const int bigramEntryTailPos = (*bigramEntryPos) + getBigramEntrySize();
-    if (*bigramEntryPos < 0 || bigramEntryTailPos > bigramListBuffer->getTailPosition()) {
-        AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bigramEntryTailPos: %d, "
-                "bufSize: %d", *bigramEntryPos, bigramEntryTailPos,
-                        bigramListBuffer->getTailPosition());
-        ASSERT(false);
-        return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-    const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
-    const bool hasNext = (bigramFlags & Ver4DictConstants::BIGRAM_HAS_NEXT_MASK) != 0;
-    int probability = NOT_A_PROBABILITY;
-    int timestamp = NOT_A_TIMESTAMP;
-    int level = 0;
-    int count = 0;
-    if (mHasHistoricalInfo) {
-        timestamp = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, bigramEntryPos);
-        level = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, bigramEntryPos);
-        count = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, bigramEntryPos);
-    } else {
-        probability = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::PROBABILITY_SIZE, bigramEntryPos);
-    }
-    const int encodedTargetTerminalId = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos);
-    const int targetTerminalId =
-            (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
-                    Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
-    if (mHasHistoricalInfo) {
-        const HistoricalInfo historicalInfo(timestamp, level, count);
-        return BigramEntry(hasNext, probability, &historicalInfo, targetTerminalId);
-    } else {
-        return BigramEntry(hasNext, probability, targetTerminalId);
-    }
-}
-
-bool BigramDictContent::writeBigramEntryAndAdvancePosition(
-        const BigramEntry *const bigramEntryToWrite, int *const entryWritingPos) {
-    BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer();
-    const int bigramFlags = createAndGetBigramFlags(bigramEntryToWrite->hasNext());
-    if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags,
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram flags. pos: %d, flags: %x", *entryWritingPos, bigramFlags);
-        return false;
-    }
-    if (mHasHistoricalInfo) {
-        const HistoricalInfo *const historicalInfo = bigramEntryToWrite->getHistoricalInfo();
-        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
-                    historicalInfo->getTimeStamp());
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getLevel(),
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
-                    historicalInfo->getLevel());
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(historicalInfo->getCount(),
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
-                    historicalInfo->getCount());
-            return false;
-        }
-    } else {
-        if (!bigramListBuffer->writeUintAndAdvancePosition(bigramEntryToWrite->getProbability(),
-                Ver4DictConstants::PROBABILITY_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram probability. pos: %d, probability: %d", *entryWritingPos,
-                    bigramEntryToWrite->getProbability());
-            return false;
-        }
-    }
-    const int targetTerminalIdToWrite =
-            (bigramEntryToWrite->getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) ?
-                    Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID :
-                            bigramEntryToWrite->getTargetTerminalId();
-    if (!bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite,
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram target terminal id. pos: %d, target terminal id: %d",
-                *entryWritingPos, bigramEntryToWrite->getTargetTerminalId());
-        return false;
-    }
-    return true;
-}
-
-bool BigramDictContent::copyBigramList(const int bigramListPos, const int toPos,
-        int *const outTailEntryPos) {
-    int readingPos = bigramListPos;
-    int writingPos = toPos;
-    bool hasNext = true;
-    while (hasNext) {
-        const BigramEntry bigramEntry = getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (!hasNext) {
-            *outTailEntryPos = writingPos;
-        }
-        if (!writeBigramEntryAndAdvancePosition(&bigramEntry, &writingPos)) {
-            AKLOGE("Cannot write bigram entry to copy. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool BigramDictContent::runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const BigramDictContent *const originalBigramDictContent,
-        int *const outBigramEntryCount) {
-    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-            it != terminalIdMap->end(); ++it) {
-        const int originalBigramListPos =
-                originalBigramDictContent->getBigramListHeadPos(it->first);
-        if (originalBigramListPos == NOT_A_DICT_POS) {
-            // This terminal does not have a bigram list.
-            continue;
-        }
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        int bigramEntryCount = 0;
-        // Copy bigram list with GC from original content.
-        if (!runGCBigramList(originalBigramListPos, originalBigramDictContent, bigramListPos,
-                terminalIdMap, &bigramEntryCount)) {
-            AKLOGE("Cannot complete GC for the bigram list. original pos: %d, pos: %d",
-                    originalBigramListPos, bigramListPos);
-            return false;
-        }
-        if (bigramEntryCount == 0) {
-            // All bigram entries are useless. This terminal does not have a bigram list.
-            continue;
-        }
-        *outBigramEntryCount += bigramEntryCount;
-        // Set bigram list position to the lookup table.
-        if (!getUpdatableAddressLookupTable()->set(it->second, bigramListPos)) {
-            AKLOGE("Cannot set bigram list position. terminal id: %d, pos: %d",
-                    it->second, bigramListPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-// Returns whether GC for the bigram list was succeeded or not.
-bool BigramDictContent::runGCBigramList(const int bigramListPos,
-        const BigramDictContent *const sourceBigramDictContent, const int toPos,
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        int *const outEntrycount) {
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    int writingPos = toPos;
-    int lastEntryPos = NOT_A_DICT_POS;
-    while (hasNext) {
-        const BigramEntry originalBigramEntry =
-                sourceBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = originalBigramEntry.hasNext();
-        if (originalBigramEntry.getTargetTerminalId() == Ver4DictConstants::NOT_A_TERMINAL_ID) {
-            continue;
-        }
-        TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
-                terminalIdMap->find(originalBigramEntry.getTargetTerminalId());
-        if (it == terminalIdMap->end()) {
-            // Target word has been removed.
-            continue;
-        }
-        lastEntryPos = hasNext ? writingPos : NOT_A_DICT_POS;
-        const BigramEntry updatedBigramEntry =
-                originalBigramEntry.updateTargetTerminalIdAndGetEntry(it->second);
-        if (!writeBigramEntryAndAdvancePosition(&updatedBigramEntry, &writingPos)) {
-            AKLOGE("Cannot write bigram entry to run GC. pos: %d", writingPos);
-            return false;
-        }
-        *outEntrycount += 1;
-    }
-    if (lastEntryPos != NOT_A_DICT_POS) {
-        // Update has next flag in the last written entry.
-        const BigramEntry bigramEntry = getBigramEntry(lastEntryPos).updateHasNextAndGetEntry(
-                false /* hasNext */);
-        if (!writeBigramEntry(&bigramEntry, lastEntryPos)) {
-            AKLOGE("Cannot write bigram entry to set hasNext flag after GC. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h
deleted file mode 100644
index b554e56..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h
+++ /dev/null
@@ -1,135 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class BigramDictContent : public SparseTableDictContent {
- public:
-    BigramDictContent(const char *const dictPath, const bool hasHistoricalInfo,
-            const bool isUpdatable)
-            : SparseTableDictContent(dictPath,
-                      Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
-                      Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
-                      Ver4DictConstants::BIGRAM_FILE_EXTENSION, isUpdatable,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    BigramDictContent(const bool hasHistoricalInfo)
-            : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    const BigramEntry getBigramEntry(const int bigramEntryPos) const {
-        int readingPos = bigramEntryPos;
-        return getBigramEntryAndAdvancePosition(&readingPos);
-    }
-
-    const BigramEntry getBigramEntryAndAdvancePosition(int *const bigramEntryPos) const;
-
-    // Returns head position of bigram list for a PtNode specified by terminalId.
-    int getBigramListHeadPos(const int terminalId) const {
-        const SparseTable *const addressLookupTable = getAddressLookupTable();
-        if (!addressLookupTable->contains(terminalId)) {
-            return NOT_A_DICT_POS;
-        }
-        return addressLookupTable->get(terminalId);
-    }
-
-    bool writeBigramEntryAtTail(const BigramEntry *const bigramEntryToWrite) {
-        int writingPos = getContentBuffer()->getTailPosition();
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntry(const BigramEntry *const bigramEntryToWrite, const int entryWritingPos) {
-        int writingPos = entryWritingPos;
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntryAndAdvancePosition(const BigramEntry *const bigramEntryToWrite,
-            int *const entryWritingPos);
-
-    bool createNewBigramList(const int terminalId) {
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos);
-    }
-
-    bool copyBigramList(const int bigramListPos, const int toPos, int *const outTailEntryPos);
-
-    bool flushToFile(const char *const dictPath) const {
-        return flush(dictPath, Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION,
-                Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION,
-                Ver4DictConstants::BIGRAM_FILE_EXTENSION);
-    }
-
-    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const BigramDictContent *const originalBigramDictContent,
-            int *const outBigramEntryCount);
-
-    bool isContentTailPos(const int pos) const {
-        return pos == getContentBuffer()->getTailPosition();
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(BigramDictContent);
-
-    int createAndGetBigramFlags(const bool hasNext) const {
-        return hasNext ? Ver4DictConstants::BIGRAM_HAS_NEXT_MASK : 0;
-    }
-
-    int getBigramEntrySize() const {
-        if (mHasHistoricalInfo) {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
-                    + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                    + Ver4DictConstants::WORD_COUNT_FIELD_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        } else {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::PROBABILITY_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        }
-    }
-
-    bool runGCBigramList(const int bigramListPos,
-            const BigramDictContent *const sourceBigramDictContent, const int toPos,
-            const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            int *const outEntryCount);
-
-    bool mHasHistoricalInfo;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_BIGRAM_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h
deleted file mode 100644
index 40968b4..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_entry.h
+++ /dev/null
@@ -1,110 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H
-#define LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class BigramEntry {
- public:
-    BigramEntry(const BigramEntry& bigramEntry)
-            : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
-              mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
-              mTargetTerminalId(targetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability,
-            const HistoricalInfo *const historicalInfo, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
-              mTargetTerminalId(targetTerminalId) {}
-
-    const BigramEntry getInvalidatedEntry() const {
-        return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-
-    const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
-        return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
-        return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
-    }
-
-    const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
-        return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateHistoricalInfoAndGetEntry(
-            const HistoricalInfo *const historicalInfo) const {
-        return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
-    }
-
-    bool isValid() const {
-        return mTargetTerminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
-    }
-
-    bool hasNext() const {
-        return mHasNext;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    bool hasHistoricalInfo() const {
-        return mHistoricalInfo.isValid();
-    }
-
-    const HistoricalInfo *getHistoricalInfo() const {
-        return &mHistoricalInfo;
-    }
-
-    int getTargetTerminalId() const {
-        return mTargetTerminalId;
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_DEFAULT_CONSTRUCTOR(BigramEntry);
-    DISALLOW_ASSIGNMENT_OPERATOR(BigramEntry);
-
-    const bool mHasNext;
-    const int mProbability;
-    const HistoricalInfo mHistoricalInfo;
-    const int mTargetTerminalId;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_BIGRAM_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/dict_content.h
deleted file mode 100644
index 0f2f255..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/dict_content.h
+++ /dev/null
@@ -1,47 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_DICT_CONTENT_H
-
-#include "defines.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class DictContent {
- public:
-    virtual ~DictContent() {}
-    virtual bool isValid() const = 0;
-
- protected:
-    DictContent() {}
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(DictContent);
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp
deleted file mode 100644
index c671647..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.cpp
+++ /dev/null
@@ -1,171 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-const ProbabilityEntry ProbabilityDictContent::getProbabilityEntry(const int terminalId) const {
-    if (terminalId < 0 || terminalId >= mSize) {
-        // This method can be called with invalid terminal id during GC.
-        return ProbabilityEntry(0 /* flags */, NOT_A_PROBABILITY);
-    }
-    const BufferWithExtendableBuffer *const buffer = getBuffer();
-    int entryPos = getEntryPos(terminalId);
-    const int flags = buffer->readUintAndAdvancePosition(
-            Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &entryPos);
-    const int probability = buffer->readUintAndAdvancePosition(
-            Ver4DictConstants::PROBABILITY_SIZE, &entryPos);
-    if (mHasHistoricalInfo) {
-        const int timestamp = buffer->readUintAndAdvancePosition(
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &entryPos);
-        const int level = buffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &entryPos);
-        const int count = buffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &entryPos);
-        const HistoricalInfo historicalInfo(timestamp, level, count);
-        return ProbabilityEntry(flags, probability, &historicalInfo);
-    } else {
-        return ProbabilityEntry(flags, probability);
-    }
-}
-
-bool ProbabilityDictContent::setProbabilityEntry(const int terminalId,
-        const ProbabilityEntry *const probabilityEntry) {
-    if (terminalId < 0) {
-        return false;
-    }
-    const int entryPos = getEntryPos(terminalId);
-    if (terminalId >= mSize) {
-        ProbabilityEntry dummyEntry;
-        // Write new entry.
-        int writingPos = getBuffer()->getTailPosition();
-        while (writingPos <= entryPos) {
-            // Fulfilling with dummy entries until writingPos.
-            if (!writeEntry(&dummyEntry, writingPos)) {
-                AKLOGE("Cannot write dummy entry. pos: %d, mSize: %d", writingPos, mSize);
-                return false;
-            }
-            writingPos += getEntrySize();
-            mSize++;
-        }
-    }
-    return writeEntry(probabilityEntry, entryPos);
-}
-
-bool ProbabilityDictContent::flushToFile(const char *const dictPath) const {
-    if (getEntryPos(mSize) < getBuffer()->getTailPosition()) {
-        ProbabilityDictContent probabilityDictContentToWrite(mHasHistoricalInfo);
-        for (int i = 0; i < mSize; ++i) {
-            const ProbabilityEntry probabilityEntry = getProbabilityEntry(i);
-            if (!probabilityDictContentToWrite.setProbabilityEntry(i, &probabilityEntry)) {
-                AKLOGE("Cannot set probability entry in flushToFile. terminalId: %d", i);
-                return false;
-            }
-        }
-        return probabilityDictContentToWrite.flush(dictPath,
-                Ver4DictConstants::FREQ_FILE_EXTENSION);
-    } else {
-        return flush(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION);
-    }
-}
-
-bool ProbabilityDictContent::runGC(
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const ProbabilityDictContent *const originalProbabilityDictContent) {
-    mSize = 0;
-    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-            it != terminalIdMap->end(); ++it) {
-        const ProbabilityEntry probabilityEntry =
-                originalProbabilityDictContent->getProbabilityEntry(it->first);
-        if (!setProbabilityEntry(it->second, &probabilityEntry)) {
-            AKLOGE("Cannot set probability entry in runGC. terminalId: %d", it->second);
-            return false;
-        }
-        mSize++;
-    }
-    return true;
-}
-
-int ProbabilityDictContent::getEntrySize() const {
-    if (mHasHistoricalInfo) {
-        return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
-                + Ver4DictConstants::PROBABILITY_SIZE
-                + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
-                + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                + Ver4DictConstants::WORD_COUNT_FIELD_SIZE;
-    } else {
-        return Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE
-                + Ver4DictConstants::PROBABILITY_SIZE;
-    }
-}
-
-int ProbabilityDictContent::getEntryPos(const int terminalId) const {
-    return terminalId * getEntrySize();
-}
-
-bool ProbabilityDictContent::writeEntry(const ProbabilityEntry *const probabilityEntry,
-        const int entryPos) {
-    BufferWithExtendableBuffer *const bufferToWrite = getWritableBuffer();
-    int writingPos = entryPos;
-    if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getFlags(),
-            Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE, &writingPos)) {
-        AKLOGE("Cannot write flags in probability dict content. pos: %d", writingPos);
-        return false;
-    }
-    if (!bufferToWrite->writeUintAndAdvancePosition(probabilityEntry->getProbability(),
-            Ver4DictConstants::PROBABILITY_SIZE, &writingPos)) {
-        AKLOGE("Cannot write probability in probability dict content. pos: %d", writingPos);
-        return false;
-    }
-    if (mHasHistoricalInfo) {
-        const HistoricalInfo *const historicalInfo = probabilityEntry->getHistoricalInfo();
-        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getTimeStamp(),
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, &writingPos)) {
-            AKLOGE("Cannot write timestamp in probability dict content. pos: %d", writingPos);
-            return false;
-        }
-        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getLevel(),
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, &writingPos)) {
-            AKLOGE("Cannot write level in probability dict content. pos: %d", writingPos);
-            return false;
-        }
-        if (!bufferToWrite->writeUintAndAdvancePosition(historicalInfo->getCount(),
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, &writingPos)) {
-            AKLOGE("Cannot write count in probability dict content. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h
deleted file mode 100644
index 3734797..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h
+++ /dev/null
@@ -1,74 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/probability_dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/single_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class ProbabilityEntry;
-
-class ProbabilityDictContent : public SingleDictContent {
- public:
-    ProbabilityDictContent(const char *const dictPath, const bool hasHistoricalInfo,
-            const bool isUpdatable)
-            : SingleDictContent(dictPath, Ver4DictConstants::FREQ_FILE_EXTENSION, isUpdatable),
-              mHasHistoricalInfo(hasHistoricalInfo),
-              mSize(getBuffer()->getTailPosition() / getEntrySize()) {}
-
-    ProbabilityDictContent(const bool hasHistoricalInfo)
-            : mHasHistoricalInfo(hasHistoricalInfo), mSize(0) {}
-
-    const ProbabilityEntry getProbabilityEntry(const int terminalId) const;
-
-    bool setProbabilityEntry(const int terminalId, const ProbabilityEntry *const probabilityEntry);
-
-    bool flushToFile(const char *const dictPath) const;
-
-    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const ProbabilityDictContent *const originalProbabilityDictContent);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(ProbabilityDictContent);
-
-    int getEntrySize() const;
-
-    int getEntryPos(const int terminalId) const;
-
-    bool writeEntry(const ProbabilityEntry *const probabilityEntry, const int entryPos);
-
-    bool mHasHistoricalInfo;
-    int mSize;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_PROBABILITY_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h
deleted file mode 100644
index 8ccfa33..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h
+++ /dev/null
@@ -1,90 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H
-#define LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class ProbabilityEntry {
- public:
-    ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
-            : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
-              mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
-
-    // Dummy entry
-    ProbabilityEntry()
-            : mFlags(0), mProbability(NOT_A_PROBABILITY), mHistoricalInfo() {}
-
-    // Entry without historical information
-    ProbabilityEntry(const int flags, const int probability)
-            : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
-
-    // Entry with historical information.
-    ProbabilityEntry(const int flags, const int probability,
-            const HistoricalInfo *const historicalInfo)
-            : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
-
-    const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
-        return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
-    }
-
-    const ProbabilityEntry createEntryWithUpdatedHistoricalInfo(
-            const HistoricalInfo *const historicalInfo) const {
-        return ProbabilityEntry(mFlags, mProbability, historicalInfo);
-    }
-
-    bool hasHistoricalInfo() const {
-        return mHistoricalInfo.isValid();
-    }
-
-    int getFlags() const {
-        return mFlags;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    const HistoricalInfo *getHistoricalInfo() const {
-        return &mHistoricalInfo;
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry);
-
-    const int mFlags;
-    const int mProbability;
-    const HistoricalInfo mHistoricalInfo;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp
deleted file mode 100644
index 56bc8b9..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.cpp
+++ /dev/null
@@ -1,199 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
-        int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
-        bool *const outhasNext, int *const shortcutEntryPos) const {
-    const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
-    if (*shortcutEntryPos < 0 || *shortcutEntryPos >=  shortcutListBuffer->getTailPosition()) {
-        AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
-                *shortcutEntryPos, shortcutListBuffer->getTailPosition());
-        ASSERT(false);
-        if (outhasNext) {
-            *outhasNext = false;
-        }
-        if (outCodePointCount) {
-            *outCodePointCount = 0;
-        }
-        return;
-    }
-
-    const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-    if (outProbability) {
-        *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
-    }
-    if (outhasNext) {
-        *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
-    }
-    if (outCodePoint && outCodePointCount) {
-        shortcutListBuffer->readCodePointsAndAdvancePosition(
-                maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
-    }
-}
-
-int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
-    const SparseTable *const addressLookupTable = getAddressLookupTable();
-    if (!addressLookupTable->contains(terminalId)) {
-        return NOT_A_DICT_POS;
-    }
-    return addressLookupTable->get(terminalId);
-}
-
-bool ShortcutDictContent::flushToFile(const char *const dictPath) const {
-    return flush(dictPath, Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
-            Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
-            Ver4DictConstants::SHORTCUT_FILE_EXTENSION);
-}
-
-bool ShortcutDictContent::runGC(
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const ShortcutDictContent *const originalShortcutDictContent) {
-   for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-           it != terminalIdMap->end(); ++it) {
-       const int originalShortcutListPos =
-               originalShortcutDictContent->getShortcutListHeadPos(it->first);
-       if (originalShortcutListPos == NOT_A_DICT_POS) {
-           continue;
-       }
-       const int shortcutListPos = getContentBuffer()->getTailPosition();
-       // Copy shortcut list from original content.
-       if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
-               shortcutListPos)) {
-           AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
-                   originalShortcutListPos, shortcutListPos);
-           return false;
-       }
-       // Set shortcut list position to the lookup table.
-       if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
-           AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
-                   it->second, shortcutListPos);
-           return false;
-       }
-   }
-   return true;
-}
-
-bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
-    const int shortcutListListPos = getContentBuffer()->getTailPosition();
-    return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
-}
-
-bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
-    return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
-}
-
-bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
-        const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
-    bool hasNext = true;
-    int readingPos = shortcutListPos;
-    int writingPos = toPos;
-    int codePoints[MAX_WORD_LENGTH];
-    while (hasNext) {
-        int probability = 0;
-        int codePointCount = 0;
-        sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
-                codePoints, &codePointCount, &probability, &hasNext, &readingPos);
-        if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
-                hasNext, &writingPos)) {
-            AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
-    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
-    const int shortcutFlags = shortcutListBuffer->readUint(
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-    const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
-    const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
-    return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-}
-
-bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
-        const int codePointCount, const int probability, const bool hasNext,
-        int *const shortcutEntryPos) {
-    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
-    const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
-    if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
-        AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
-        return false;
-    }
-    if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
-            true /* writesTerminator */, shortcutEntryPos)) {
-        AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
-        return false;
-    }
-    return true;
-}
-
-// Find a shortcut entry that has specified target and return its position.
-int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
-        const int *const targetCodePointsToFind, const int codePointCount) const {
-    bool hasNext = true;
-    int readingPos = shortcutListPos;
-    int targetCodePoints[MAX_WORD_LENGTH];
-    while (hasNext) {
-        const int entryPos = readingPos;
-        int probability = 0;
-        int targetCodePointCount = 0;
-        getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
-                &probability, &hasNext, &readingPos);
-        if (targetCodePointCount != codePointCount) {
-            continue;
-        }
-        bool matched = true;
-        for (int i = 0; i < codePointCount; ++i) {
-            if (targetCodePointsToFind[i] != targetCodePoints[i]) {
-                matched = false;
-                break;
-            }
-        }
-        if (matched) {
-            return entryPos;
-        }
-    }
-    return NOT_A_DICT_POS;
-}
-
-int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
-        const bool hasNext) const {
-    return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
-            | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h
deleted file mode 100644
index 179cec5..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h
+++ /dev/null
@@ -1,101 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class ShortcutDictContent : public SparseTableDictContent {
- public:
-    ShortcutDictContent(const char *const dictPath, const bool isUpdatable)
-            : SparseTableDictContent(dictPath,
-                      Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION,
-                      Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION,
-                      Ver4DictConstants::SHORTCUT_FILE_EXTENSION, isUpdatable,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
-
-    ShortcutDictContent()
-            : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
-
-    void getShortcutEntry(const int maxCodePointCount, int *const outCodePoint,
-            int *const outCodePointCount, int *const outProbability, bool *const outhasNext,
-            const int shortcutEntryPos) {
-        int readingPos = shortcutEntryPos;
-        return getShortcutEntryAndAdvancePosition(maxCodePointCount, outCodePoint,
-                outCodePointCount, outProbability, outhasNext, &readingPos);
-    }
-
-    void getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
-            int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
-            bool *const outhasNext, int *const shortcutEntryPos) const;
-
-   // Returns head position of shortcut list for a PtNode specified by terminalId.
-   int getShortcutListHeadPos(const int terminalId) const;
-
-   bool flushToFile(const char *const dictPath) const;
-
-   bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-           const ShortcutDictContent *const originalShortcutDictContent);
-
-   bool createNewShortcutList(const int terminalId);
-
-   bool copyShortcutList(const int shortcutListPos, const int toPos);
-
-   bool setProbability(const int probability, const int shortcutEntryPos);
-
-   bool writeShortcutEntry(const int *const codePoint, const int codePointCount,
-           const int probability, const bool hasNext, const int shortcutEntryPos) {
-       int writingPos = shortcutEntryPos;
-       return writeShortcutEntryAndAdvancePosition(codePoint, codePointCount, probability,
-               hasNext, &writingPos);
-   }
-
-   bool writeShortcutEntryAndAdvancePosition(const int *const codePoint,
-           const int codePointCount, const int probability, const bool hasNext,
-           int *const shortcutEntryPos);
-
-   int findShortcutEntryAndGetPos(const int shortcutListPos,
-           const int *const targetCodePointsToFind, const int codePointCount) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent);
-
-    bool copyShortcutListFromDictContent(const int shortcutListPos,
-            const ShortcutDictContent *const sourceShortcutDictContent, const int toPos);
-
-    int createAndGetShortcutFlags(const int probability, const bool hasNext) const;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_SHORTCUT_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/single_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/single_dict_content.h
deleted file mode 100644
index 49f4468..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/single_dict_content.h
+++ /dev/null
@@ -1,88 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class SingleDictContent : public DictContent {
- public:
-    SingleDictContent(const char *const dictPath, const char *const contentFileName,
-            const bool isUpdatable)
-            : mMmappedBuffer(MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
-              mExpandableContentBuffer(
-                      mMmappedBuffer ? mMmappedBuffer->getReadWriteByteArrayView() :
-                              ReadWriteByteArrayView(),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mIsValid(mMmappedBuffer) {}
-
-    SingleDictContent()
-            : mMmappedBuffer(nullptr),
-              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE), mIsValid(true) {}
-
-    virtual ~SingleDictContent() {}
-
-    virtual bool isValid() const {
-        return mIsValid;
-    }
-
-    bool isNearSizeLimit() const {
-        return mExpandableContentBuffer.isNearSizeLimit();
-    }
-
- protected:
-    BufferWithExtendableBuffer *getWritableBuffer() {
-        return &mExpandableContentBuffer;
-    }
-
-    const BufferWithExtendableBuffer *getBuffer() const {
-        return &mExpandableContentBuffer;
-    }
-
-    bool flush(const char *const dictPath, const char *const contentFileNameSuffix) const {
-        return DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
-                contentFileNameSuffix, &mExpandableContentBuffer);
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(SingleDictContent);
-
-    const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
-    BufferWithExtendableBuffer mExpandableContentBuffer;
-    const bool mIsValid;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_SINGLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp
deleted file mode 100644
index 7c9b496..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.cpp
+++ /dev/null
@@ -1,50 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-bool SparseTableDictContent::flush(const char *const dictPath,
-        const char *const lookupTableFileNameSuffix, const char *const addressTableFileNameSuffix,
-        const char *const contentFileNameSuffix) const {
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, lookupTableFileNameSuffix,
-            &mExpandableLookupTableBuffer)){
-        return false;
-    }
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, addressTableFileNameSuffix,
-            &mExpandableAddressTableBuffer)) {
-        return false;
-    }
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath, contentFileNameSuffix,
-            &mExpandableContentBuffer)) {
-        return false;
-    }
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h
deleted file mode 100644
index 3c626df..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/sparse_table_dict_content.h
+++ /dev/null
@@ -1,124 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H
-#define LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/sparse_table.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-// TODO: Support multiple contents.
-class SparseTableDictContent : public DictContent {
- public:
-    AK_FORCE_INLINE SparseTableDictContent(const char *const dictPath,
-            const char *const lookupTableFileName, const char *const addressTableFileName,
-            const char *const contentFileName, const bool isUpdatable,
-            const int sparseTableBlockSize, const int sparseTableDataSize)
-            : mLookupTableBuffer(
-                      MmappedBuffer::openBuffer(dictPath, lookupTableFileName, isUpdatable)),
-              mAddressTableBuffer(
-                      MmappedBuffer::openBuffer(dictPath, addressTableFileName, isUpdatable)),
-              mContentBuffer(
-                      MmappedBuffer::openBuffer(dictPath, contentFileName, isUpdatable)),
-              mExpandableLookupTableBuffer(
-                      mLookupTableBuffer ? mLookupTableBuffer->getReadWriteByteArrayView() :
-                              ReadWriteByteArrayView(),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mExpandableAddressTableBuffer(
-                      mAddressTableBuffer ? mAddressTableBuffer->getReadWriteByteArrayView() :
-                              ReadWriteByteArrayView(),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mExpandableContentBuffer(
-                      mContentBuffer ? mContentBuffer->getReadWriteByteArrayView() :
-                              ReadWriteByteArrayView(),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
-                      sparseTableBlockSize, sparseTableDataSize),
-              mIsValid(mLookupTableBuffer && mAddressTableBuffer && mContentBuffer) {}
-
-    SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize)
-            : mLookupTableBuffer(), mAddressTableBuffer(), mContentBuffer(),
-              mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
-                      sparseTableBlockSize, sparseTableDataSize), mIsValid(true) {}
-
-    virtual ~SparseTableDictContent() {}
-
-    virtual bool isValid() const {
-        return mIsValid;
-    }
-
-    bool isNearSizeLimit() const {
-        return mExpandableLookupTableBuffer.isNearSizeLimit()
-                || mExpandableAddressTableBuffer.isNearSizeLimit()
-                || mExpandableContentBuffer.isNearSizeLimit();
-    }
-
- protected:
-    SparseTable *getUpdatableAddressLookupTable() {
-        return &mAddressLookupTable;
-    }
-
-    const SparseTable *getAddressLookupTable() const {
-        return &mAddressLookupTable;
-    }
-
-    BufferWithExtendableBuffer *getWritableContentBuffer() {
-        return &mExpandableContentBuffer;
-    }
-
-    const BufferWithExtendableBuffer *getContentBuffer() const {
-        return &mExpandableContentBuffer;
-    }
-
-    bool flush(const char *const dictDirPath, const char *const lookupTableFileName,
-            const char *const addressTableFileName, const char *const contentFileName) const;
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
-
-    const MmappedBuffer::MmappedBufferPtr mLookupTableBuffer;
-    const MmappedBuffer::MmappedBufferPtr mAddressTableBuffer;
-    const MmappedBuffer::MmappedBufferPtr mContentBuffer;
-    BufferWithExtendableBuffer mExpandableLookupTableBuffer;
-    BufferWithExtendableBuffer mExpandableAddressTableBuffer;
-    BufferWithExtendableBuffer mExpandableContentBuffer;
-    SparseTable mAddressLookupTable;
-    const bool mIsValid;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_SPARSE_TABLE_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp
deleted file mode 100644
index a9f8417..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.cpp
+++ /dev/null
@@ -1,111 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
-    if (terminalId < 0 || terminalId >= mSize) {
-        return NOT_A_DICT_POS;
-    }
-    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;
-}
-
-bool TerminalPositionLookupTable::setTerminalPtNodePosition(
-        const int terminalId, const int terminalPtNodePos) {
-    if (terminalId < 0) {
-        return NOT_A_DICT_POS;
-    }
-    while (terminalId >= mSize) {
-        // Write new entry.
-        if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
-                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
-            return false;
-        }
-        mSize++;
-    }
-    const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
-            terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
-    return getWritableBuffer()->writeUint(terminalPos,
-            Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
-}
-
-bool TerminalPositionLookupTable::flushToFile(const char *const dictPath) 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)) {
-                AKLOGE("Cannot set terminal position to lookupTableToWrite."
-                        " terminalId: %d, position: %d", i, terminalPtNodePosition);
-                return false;
-            }
-        }
-        return lookupTableToWrite.flush(dictPath,
-                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
-    } else {
-        // We can simply use this lookup table because the buffer size has not been
-        // changed.
-        return flush(dictPath, Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION);
-    }
-}
-
-bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
-    int removedEntryCount = 0;
-    int nextNewTerminalId = 0;
-    for (int i = 0; i < mSize; ++i) {
-        const int terminalPos = getBuffer()->readUint(
-                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
-        if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
-            // This entry is a garbage.
-            removedEntryCount++;
-        } else {
-            // Give a new terminal id to the entry.
-            if (!getWritableBuffer()->writeUint(terminalPos,
-                    Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
-                    getEntryPos(nextNewTerminalId))) {
-                return false;
-            }
-            // Memorize the mapping to the old terminal id to the new terminal id.
-            terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
-            nextNewTerminalId++;
-        }
-    }
-    mSize = nextNewTerminalId;
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h
deleted file mode 100644
index eadfe0f..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h
+++ /dev/null
@@ -1,73 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
-#define LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
-
-#include <unordered_map>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/single_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class TerminalPositionLookupTable : public SingleDictContent {
- public:
-    typedef std::unordered_map<int, int> TerminalIdMap;
-
-    TerminalPositionLookupTable(const char *const dictPath, const bool isUpdatable)
-            : SingleDictContent(dictPath,
-                      Ver4DictConstants::TERMINAL_ADDRESS_TABLE_FILE_EXTENSION, isUpdatable),
-              mSize(getBuffer()->getTailPosition()
-                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
-
-    TerminalPositionLookupTable() : mSize(0) {}
-
-    int getTerminalPtNodePosition(const int terminalId) const;
-
-    bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos);
-
-    int getNextTerminalId() const {
-        return mSize;
-    }
-
-    bool flushToFile(const char *const dictPath) const;
-
-    bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable);
-
-    int getEntryPos(const int terminalId) const {
-        return terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
-    }
-
-    int mSize;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif // LATINIME_BACKWARD_V402_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h
deleted file mode 100644
index 941fda7..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h
+++ /dev/null
@@ -1,118 +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.
- */
-
-/*
- * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
- * Do not edit this file other than updating policy's interface.
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
-#define LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
- public:
-    Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
-            const TerminalPositionLookupTable *const terminalPositionLookupTable)
-            : mShortcutDictContent(shortcutDictContent) {}
-
-    ~Ver4ShortcutListPolicy() {}
-
-    int getStartPos(const int pos) const {
-        // The first shortcut entry is located at the head position of the shortcut list.
-        return pos;
-    }
-
-    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
-            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
-            int *const pos) const {
-        int probability = 0;
-        mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount,
-                outCodePoint, outCodePointCount, &probability, outHasNext, pos);
-        if (outIsWhitelist) {
-            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(probability);
-        }
-    }
-
-    void skipAllShortcuts(int *const pos) const {
-        // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries.
-    }
-
-    bool addNewShortcut(const int terminalId, const int *const codePoints, const int codePointCount,
-            const int probability) {
-        const int shortcutListPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
-        if (shortcutListPos == NOT_A_DICT_POS) {
-            // Create shortcut list.
-            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
-                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
-                return false;
-            }
-            const int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
-            return mShortcutDictContent->writeShortcutEntry(codePoints, codePointCount, probability,
-                    false /* hasNext */, writingPos);
-        }
-        const int entryPos = mShortcutDictContent->findShortcutEntryAndGetPos(shortcutListPos,
-                codePoints, codePointCount);
-        if (entryPos == NOT_A_DICT_POS) {
-            // Add new entry to the shortcut list.
-            // Create new shortcut list.
-            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
-                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
-                return false;
-            }
-            int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
-            if (!mShortcutDictContent->writeShortcutEntryAndAdvancePosition(codePoints,
-                    codePointCount, probability, true /* hasNext */, &writingPos)) {
-                AKLOGE("Cannot write shortcut entry. terminal id: %d, pos: %d", terminalId,
-                        writingPos);
-                return false;
-            }
-            return mShortcutDictContent->copyShortcutList(shortcutListPos, writingPos);
-        }
-        // Overwrite existing entry.
-        bool hasNext = false;
-        mShortcutDictContent->getShortcutEntry(MAX_WORD_LENGTH, 0 /* outCodePoint */,
-                0 /* outCodePointCount */ , 0 /* probability */, &hasNext, entryPos);
-        if (!mShortcutDictContent->writeShortcutEntry(codePoints,
-                codePointCount, probability, hasNext, entryPos)) {
-            AKLOGE("Cannot overwrite shortcut entry. terminal id: %d, pos: %d", terminalId,
-                    entryPos);
-            return false;
-        }
-        return true;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
-
-    ShortcutDictContent *const mShortcutDictContent;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif // LATINIME_BACKWARD_V402_VER4_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.cpp
deleted file mode 100644
index 3dfbd1c..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.cpp
+++ /dev/null
@@ -1,157 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-
-#include <cerrno>
-#include <cstring>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-/* static */ Ver4DictBuffers::Ver4DictBuffersPtr Ver4DictBuffers::openVer4DictBuffers(
-        const char *const dictPath, MmappedBuffer::MmappedBufferPtr headerBuffer,
-        const FormatUtils::FORMAT_VERSION formatVersion) {
-    if (!headerBuffer) {
-        ASSERT(false);
-        AKLOGE("The header buffer must be valid to open ver4 dict buffers.");
-        return Ver4DictBuffersPtr(nullptr);
-    }
-    // TODO: take only dictDirPath, and open both header and trie files in the constructor below
-    const bool isUpdatable = headerBuffer->isUpdatable();
-    return Ver4DictBuffersPtr(new Ver4DictBuffers(dictPath, std::move(headerBuffer), isUpdatable,
-            formatVersion));
-}
-
-bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
-        const BufferWithExtendableBuffer *const headerBuffer) const {
-    // Create temporary directory.
-    const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath,
-            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
-    char tmpDirPath[tmpDirPathBufSize];
-    FileUtils::getFilePathWithSuffix(dictDirPath,
-            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize,
-            tmpDirPath);
-    if (FileUtils::existsDir(tmpDirPath)) {
-        if (!FileUtils::removeDirAndFiles(tmpDirPath)) {
-            AKLOGE("Existing directory %s cannot be removed.", tmpDirPath);
-            ASSERT(false);
-            return false;
-        }
-    }
-    umask(S_IWGRP | S_IWOTH);
-    if (mkdir(tmpDirPath, S_IRWXU) == -1) {
-        AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
-        return false;
-    }
-    // Get dictionary base path.
-    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
-    char dictName[dictNameBufSize];
-    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
-    const int dictPathBufSize = FileUtils::getFilePathBufSize(tmpDirPath, dictName);
-    char dictPath[dictPathBufSize];
-    FileUtils::getFilePath(tmpDirPath, dictName, dictPathBufSize, dictPath);
-
-    // Write header file.
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
-            Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
-        AKLOGE("Dictionary header file %s%s cannot be written.", tmpDirPath,
-                Ver4DictConstants::HEADER_FILE_EXTENSION);
-        return false;
-    }
-    // Write trie file.
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
-            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(dictPath)) {
-        AKLOGE("Terminal position lookup table cannot be written. %s", tmpDirPath);
-        return false;
-    }
-    if (!mProbabilityDictContent.flushToFile(dictPath)) {
-        AKLOGE("Probability dict content cannot be written. %s", tmpDirPath);
-        return false;
-    }
-    if (!mBigramDictContent.flushToFile(dictPath)) {
-        AKLOGE("Bigram dict content cannot be written. %s", tmpDirPath);
-        return false;
-    }
-    if (!mShortcutDictContent.flushToFile(dictPath)) {
-        AKLOGE("Shortcut dict content cannot be written. %s", tmpDirPath);
-        return false;
-    }
-    // Remove existing dictionary.
-    if (!FileUtils::removeDirAndFiles(dictDirPath)) {
-        AKLOGE("Existing directory %s cannot be removed.", dictDirPath);
-        ASSERT(false);
-        return false;
-    }
-    // Rename temporary directory.
-    if (rename(tmpDirPath, dictDirPath) != 0) {
-        AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath);
-        ASSERT(false);
-        return false;
-    }
-    return true;
-}
-
-Ver4DictBuffers::Ver4DictBuffers(const char *const dictPath,
-        MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
-        const FormatUtils::FORMAT_VERSION formatVersion)
-        : mHeaderBuffer(std::move(headerBuffer)),
-          mDictBuffer(MmappedBuffer::openBuffer(dictPath,
-                  Ver4DictConstants::TRIE_FILE_EXTENSION, isUpdatable)),
-          mHeaderPolicy(mHeaderBuffer->getReadOnlyByteArrayView().data(), formatVersion),
-          mExpandableHeaderBuffer(mHeaderBuffer->getReadWriteByteArrayView(),
-                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-          mExpandableTrieBuffer(
-                  mDictBuffer ? mDictBuffer->getReadWriteByteArrayView() :
-                          ReadWriteByteArrayView(),
-                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-          mTerminalPositionLookupTable(dictPath, isUpdatable),
-          mProbabilityDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
-          mBigramDictContent(dictPath, mHeaderPolicy.hasHistoricalInfoOfWords(), isUpdatable),
-          mShortcutDictContent(dictPath, isUpdatable),
-          mIsUpdatable(isUpdatable) {}
-
-Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize)
-        : mHeaderBuffer(nullptr), mDictBuffer(nullptr), mHeaderPolicy(headerPolicy),
-          mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-          mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
-          mProbabilityDictContent(headerPolicy->hasHistoricalInfoOfWords()),
-          mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
-          mIsUpdatable(true) {}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h
deleted file mode 100644
index e775be5..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h
+++ /dev/null
@@ -1,152 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H
-#define LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H
-
-#include <memory>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/bigram_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/shortcut_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-class Ver4DictBuffers {
- public:
-    typedef std::unique_ptr<Ver4DictBuffers> Ver4DictBuffersPtr;
-
-    static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
-            MmappedBuffer::MmappedBufferPtr headerBuffer,
-            const FormatUtils::FORMAT_VERSION formatVersion);
-
-    static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
-            const HeaderPolicy *const headerPolicy, const int maxTrieSize) {
-        return Ver4DictBuffersPtr(new Ver4DictBuffers(headerPolicy, maxTrieSize));
-    }
-
-    AK_FORCE_INLINE bool isValid() const {
-        return mHeaderBuffer && mDictBuffer && mHeaderPolicy.isValid()
-                && mProbabilityDictContent.isValid() && mTerminalPositionLookupTable.isValid()
-                && mBigramDictContent.isValid() && mShortcutDictContent.isValid();
-    }
-
-    AK_FORCE_INLINE bool isNearSizeLimit() const {
-        return mExpandableTrieBuffer.isNearSizeLimit()
-                || mTerminalPositionLookupTable.isNearSizeLimit()
-                || mProbabilityDictContent.isNearSizeLimit()
-                || mBigramDictContent.isNearSizeLimit()
-                || mShortcutDictContent.isNearSizeLimit();
-    }
-
-    AK_FORCE_INLINE const HeaderPolicy *getHeaderPolicy() const {
-        return &mHeaderPolicy;
-    }
-
-    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() {
-        return &mExpandableHeaderBuffer;
-    }
-
-    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() {
-        return &mExpandableTrieBuffer;
-    }
-
-    AK_FORCE_INLINE const BufferWithExtendableBuffer *getTrieBuffer() const {
-        return &mExpandableTrieBuffer;
-    }
-
-    AK_FORCE_INLINE TerminalPositionLookupTable *getMutableTerminalPositionLookupTable() {
-        return &mTerminalPositionLookupTable;
-    }
-
-    AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const {
-        return &mTerminalPositionLookupTable;
-    }
-
-    AK_FORCE_INLINE ProbabilityDictContent *getMutableProbabilityDictContent() {
-        return &mProbabilityDictContent;
-    }
-
-    AK_FORCE_INLINE const ProbabilityDictContent *getProbabilityDictContent() const {
-        return &mProbabilityDictContent;
-    }
-
-    AK_FORCE_INLINE BigramDictContent *getMutableBigramDictContent() {
-        return &mBigramDictContent;
-    }
-
-    AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const {
-        return &mBigramDictContent;
-    }
-
-    AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
-        return &mShortcutDictContent;
-    }
-
-    AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const {
-        return &mShortcutDictContent;
-    }
-
-    AK_FORCE_INLINE bool isUpdatable() const {
-        return mIsUpdatable;
-    }
-
-    bool flush(const char *const dictDirPath) const {
-        return flushHeaderAndDictBuffers(dictDirPath, &mExpandableHeaderBuffer);
-    }
-
-    bool flushHeaderAndDictBuffers(const char *const dictDirPath,
-            const BufferWithExtendableBuffer *const headerBuffer) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
-
-    Ver4DictBuffers(const char *const dictDirPath,
-            const MmappedBuffer::MmappedBufferPtr headerBuffer, const bool isUpdatable,
-            const FormatUtils::FORMAT_VERSION formatVersion);
-
-    Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize);
-
-    const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
-    const MmappedBuffer::MmappedBufferPtr mDictBuffer;
-    const HeaderPolicy mHeaderPolicy;
-    BufferWithExtendableBuffer mExpandableHeaderBuffer;
-    BufferWithExtendableBuffer mExpandableTrieBuffer;
-    TerminalPositionLookupTable mTerminalPositionLookupTable;
-    ProbabilityDictContent mProbabilityDictContent;
-    BigramDictContent mBigramDictContent;
-    ShortcutDictContent mShortcutDictContent;
-    const int mIsUpdatable;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_DICT_BUFFER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.cpp
deleted file mode 100644
index 81d85f4..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.cpp
+++ /dev/null
@@ -1,81 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-// 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";
-const char *const Ver4DictConstants::BIGRAM_FILE_EXTENSION = ".bigram_freq";
-const char *const Ver4DictConstants::BIGRAM_LOOKUP_TABLE_FILE_EXTENSION = ".bigram_lookup";
-const char *const Ver4DictConstants::BIGRAM_CONTENT_TABLE_FILE_EXTENSION = ".bigram_index_freq";
-const char *const Ver4DictConstants::SHORTCUT_FILE_EXTENSION = ".shortcut_shortcut";
-const char *const Ver4DictConstants::SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION = ".shortcut_lookup";
-const char *const Ver4DictConstants::SHORTCUT_CONTENT_TABLE_FILE_EXTENSION =
-        ".shortcut_index_shortcut";
-
-// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets.
-const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 8 * 1024 * 1024;
-// Extended region size, which is not GCed region size in dict file + additional buffer size, is
-// limited to 1MB to prevent from inefficient traversing.
-const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
-
-const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
-const int Ver4DictConstants::PROBABILITY_SIZE = 1;
-const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
-const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
-const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
-const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
-const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4;
-const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 1;
-const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 1;
-
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4;
-const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
-const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
-
-const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3;
-// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing
-// invalid terminal ID in bigram lists.
-const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID =
-        (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1;
-const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1;
-const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F;
-const int Ver4DictConstants::BIGRAM_HAS_NEXT_MASK = 0x80;
-const int Ver4DictConstants::BIGRAM_LARGE_PROBABILITY_FIELD_SIZE = 1;
-
-const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
-const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
-const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h
deleted file mode 100644
index 88ebd6a..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h
+++ /dev/null
@@ -1,84 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H
-#define LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H
-
-#include "defines.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-// TODO: Create PtConstants under the pt_common and move some constant values there.
-// Note that there are corresponding definitions in FormatSpec.java.
-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;
-    static const char *const BIGRAM_LOOKUP_TABLE_FILE_EXTENSION;
-    static const char *const BIGRAM_CONTENT_TABLE_FILE_EXTENSION;
-    static const char *const SHORTCUT_FILE_EXTENSION;
-    static const char *const SHORTCUT_LOOKUP_TABLE_FILE_EXTENSION;
-    static const char *const SHORTCUT_CONTENT_TABLE_FILE_EXTENSION;
-
-    static const int MAX_DICTIONARY_SIZE;
-    static const int MAX_DICT_EXTENDED_REGION_SIZE;
-
-    static const int NOT_A_TERMINAL_ID;
-    static const int PROBABILITY_SIZE;
-    static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
-    static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
-    static const int NOT_A_TERMINAL_ADDRESS;
-    static const int TERMINAL_ID_FIELD_SIZE;
-    static const int TIME_STAMP_FIELD_SIZE;
-    static const int WORD_LEVEL_FIELD_SIZE;
-    static const int WORD_COUNT_FIELD_SIZE;
-
-    static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE;
-    static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE;
-    static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
-    static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
-
-    static const int BIGRAM_FLAGS_FIELD_SIZE;
-    static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-    static const int INVALID_BIGRAM_TARGET_TERMINAL_ID;
-    static const int BIGRAM_PROBABILITY_MASK;
-    static const int BIGRAM_HAS_NEXT_MASK;
-    // Used when bigram list has time stamp.
-    static const int BIGRAM_LARGE_PROBABILITY_FIELD_SIZE;
-
-    static const int SHORTCUT_FLAGS_FIELD_SIZE;
-    static const int SHORTCUT_PROBABILITY_MASK;
-    static const int SHORTCUT_HAS_NEXT_MASK;
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_DICT_CONSTANTS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp
deleted file mode 100644
index 82399f1..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.cpp
+++ /dev/null
@@ -1,109 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
-        const int ptNodePos, const int siblingNodePos) const {
-    if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
-                ptNodePos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return PtNodeParams();
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int pos = ptNodePos;
-    const int headPos = ptNodePos;
-    if (usesAdditionalBuffer) {
-        pos -= mBuffer->getOriginalBufferSize();
-    }
-    const PatriciaTrieReadingUtils::NodeFlags flags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const int parentPosOffset =
-            DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
-                    dictBuf, &pos);
-    const int parentPos =
-            DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
-    int codePoints[MAX_WORD_LENGTH];
-    const int codePonitCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
-            dictBuf, flags, MAX_WORD_LENGTH, codePoints, &pos);
-    int terminalIdFieldPos = NOT_A_DICT_POS;
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    int probability = NOT_A_PROBABILITY;
-    if (PatriciaTrieReadingUtils::isTerminal(flags)) {
-        terminalIdFieldPos = pos;
-        if (usesAdditionalBuffer) {
-            terminalIdFieldPos += mBuffer->getOriginalBufferSize();
-        }
-        terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
-        const ProbabilityEntry probabilityEntry =
-                mProbabilityDictContent->getProbabilityEntry(terminalId);
-        if (probabilityEntry.hasHistoricalInfo()) {
-            probability = ForgettingCurveUtils::decodeProbability(
-                    probabilityEntry.getHistoricalInfo(), mHeaderPolicy);
-        } else {
-            probability = probabilityEntry.getProbability();
-        }
-    }
-    int childrenPosFieldPos = pos;
-    if (usesAdditionalBuffer) {
-        childrenPosFieldPos += mBuffer->getOriginalBufferSize();
-    }
-    int childrenPos = DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
-            dictBuf, &pos);
-    if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
-        childrenPos += mBuffer->getOriginalBufferSize();
-    }
-    if (usesAdditionalBuffer) {
-        pos += mBuffer->getOriginalBufferSize();
-    }
-    // Sibling position is the tail position of original PtNode.
-    int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos;
-    // Read destination node if the read node is a moved node.
-    if (DynamicPtReadingUtils::isMoved(flags)) {
-        // The destination position is stored at the same place as the parent position.
-        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
-    } else {
-        return PtNodeParams(headPos, flags, parentPos, codePonitCount, codePoints,
-                terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos,
-                newSiblingNodePos);
-    }
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
deleted file mode 100644
index 1999a51..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h
+++ /dev/null
@@ -1,79 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H
-#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class BufferWithExtendableBuffer;
-namespace backward {
-namespace v402 {
-} // namespace v402
-} // namespace backward
-class HeaderPolicy;
-namespace backward {
-namespace v402 {
-class ProbabilityDictContent;
-
-/*
- * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
- * node and reads node attributes including probability form probabilityBuffer.
- */
-class Ver4PatriciaTrieNodeReader : public PtNodeReader {
- public:
-    Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
-            const ProbabilityDictContent *const probabilityDictContent,
-            const HeaderPolicy *const headerPolicy)
-            : mBuffer(buffer), mProbabilityDictContent(probabilityDictContent),
-              mHeaderPolicy(headerPolicy) {}
-
-    ~Ver4PatriciaTrieNodeReader() {}
-
-    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
-        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
-                NOT_A_DICT_POS /* siblingNodePos */);
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
-
-    const BufferWithExtendableBuffer *const mBuffer;
-    const ProbabilityDictContent *const mProbabilityDictContent;
-    const HeaderPolicy *const mHeaderPolicy;
-
-    const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
-            const int siblingNodePos) const;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
deleted file mode 100644
index 278f2b1..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.cpp
+++ /dev/null
@@ -1,430 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
-
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3;
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted(
-        const PtNodeParams *const toBeUpdatedPtNodeParams) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
-                    true /* isDeleted */, false /* willBecomeNonTerminal */);
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    // Update flags.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos)) {
-        return false;
-    }
-    if (toBeUpdatedPtNodeParams->isTerminal()) {
-        // The PtNode is a terminal. Delete entry from the terminal position lookup table.
-        return mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-                toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */);
-    } else {
-        return true;
-    }
-}
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const int movedPos, const int bigramLinkedNodePos) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
-                    false /* isDeleted */, false /* willBecomeNonTerminal */);
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    // Update flags.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos)) {
-        return false;
-    }
-    // Update moved position, which is stored in the parent offset field.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
-            mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
-        return false;
-    }
-    if (toBeUpdatedPtNodeParams->hasChildren()) {
-        // Update children's parent position.
-        mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
-        while (!mReadingHelper.isEnd()) {
-            const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams());
-            int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
-                    + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
-            if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
-                    mTrieBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
-                    &parentOffsetFieldPos)) {
-                // Parent offset cannot be written because of a bug or a broken dictionary; thus,
-                // we give up to update dictionary.
-                return false;
-            }
-            mReadingHelper.readNextSiblingNode(childPtNodeParams);
-        }
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsWillBecomeNonTerminal(
-        const PtNodeParams *const toBeUpdatedPtNodeParams) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
-                    false /* isDeleted */, true /* willBecomeNonTerminal */);
-    if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-            toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */)) {
-        AKLOGE("Cannot update terminal position lookup table. terminal id: %d",
-                toBeUpdatedPtNodeParams->getTerminalId());
-        return false;
-    }
-    // Update flags.
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    return DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const UnigramProperty *const unigramProperty) {
-    // Update probability and historical information.
-    // TODO: Update other information in the unigram property.
-    if (!toBeUpdatedPtNodeParams->isTerminal()) {
-        return false;
-    }
-    const ProbabilityEntry originalProbabilityEntry =
-            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
-                    toBeUpdatedPtNodeParams->getTerminalId());
-    const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
-            unigramProperty);
-    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
-            toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-        const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
-    if (!toBeUpdatedPtNodeParams->isTerminal()) {
-        AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
-        return false;
-    }
-    const ProbabilityEntry originalProbabilityEntry =
-            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
-                    toBeUpdatedPtNodeParams->getTerminalId());
-    if (originalProbabilityEntry.hasHistoricalInfo()) {
-        const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
-                originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy);
-        const ProbabilityEntry probabilityEntry =
-                originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo);
-        if (!mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
-                toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) {
-            AKLOGE("Cannot write updated probability entry. terminalId: %d",
-                    toBeUpdatedPtNodeParams->getTerminalId());
-            return false;
-        }
-        const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy);
-        if (!isValid) {
-            if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
-                AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
-                return false;
-            }
-        }
-        *outNeedsToKeepPtNode = isValid;
-    } else {
-        // No need to update probability.
-        *outNeedsToKeepPtNode = true;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
-        const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
-    int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
-    return DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
-            newChildrenPosition, &childrenPosFieldPos);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const int newTerminalId) {
-    return mTrieBuffer->writeUint(newTerminalId, Ver4DictConstants::TERMINAL_ID_FIELD_SIZE,
-            toBeUpdatedPtNodeParams->getTerminalIdFieldPos());
-}
-
-bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) {
-    return writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, 0 /* outTerminalId */,
-            ptNodeWritingPos);
-}
-
-
-bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, const UnigramProperty *const unigramProperty,
-        int *const ptNodeWritingPos) {
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (!writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, &terminalId,
-            ptNodeWritingPos)) {
-        return false;
-    }
-    // Write probability.
-    ProbabilityEntry newProbabilityEntry;
-    const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
-            &newProbabilityEntry, unigramProperty);
-    return mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(terminalId,
-            &probabilityEntryToWrite);
-}
-
-bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
-        const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
-    if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewEntry)) {
-        AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
-                sourcePtNodeParams->getTerminalId(), targetPtNodeParam->getTerminalId());
-        return false;
-    }
-    const int ptNodePos =
-            mBuffers->getTerminalPositionLookupTable()->getTerminalPtNodePosition(prevWordIds[0]);
-    const PtNodeParams sourcePtNodeParams =
-            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    if (!sourcePtNodeParams.hasBigrams()) {
-        // Update has bigrams flag.
-        return updatePtNodeFlags(sourcePtNodeParams.getHeadPos(),
-                sourcePtNodeParams.isBlacklisted(), sourcePtNodeParams.isNotAWord(),
-                sourcePtNodeParams.isTerminal(), sourcePtNodeParams.hasShortcutTargets(),
-                true /* hasBigrams */,
-                sourcePtNodeParams.getCodePointCount() > 1 /* hasMultipleChars */);
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
-        const int wordId) {
-    return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
-            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
-    return mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(
-            sourcePtNodeParams->getTerminalId(), outBigramEntryCount);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const DictPositionRelocationMap *const dictPositionRelocationMap,
-        int *const outBigramEntryCount) {
-    int parentPos = toBeUpdatedPtNodeParams->getParentPos();
-    if (parentPos != NOT_A_DICT_POS) {
-        PtNodeWriter::PtNodePositionRelocationMap::const_iterator it =
-                dictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
-        if (it != dictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
-            parentPos = it->second;
-        }
-    }
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos()
-            + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
-    // Write updated parent offset.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
-            parentPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
-        return false;
-    }
-
-    // Updates children position.
-    int childrenPos = toBeUpdatedPtNodeParams->getChildrenPos();
-    if (childrenPos != NOT_A_DICT_POS) {
-        PtNodeWriter::PtNodeArrayPositionRelocationMap::const_iterator it =
-                dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
-        if (it != dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
-            childrenPos = it->second;
-        }
-    }
-    if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
-        return false;
-    }
-
-    // Counts bigram entries.
-    if (outBigramEntryCount) {
-        *outBigramEntryCount = mBigramPolicy->getBigramEntryConut(
-                toBeUpdatedPtNodeParams->getTerminalId());
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptNodeParams,
-        const int *const targetCodePoints, const int targetCodePointCount,
-        const int shortcutProbability) {
-    if (!mShortcutPolicy->addNewShortcut(ptNodeParams->getTerminalId(),
-            targetCodePoints, targetCodePointCount, shortcutProbability)) {
-        AKLOGE("Cannot add new shortuct entry. terminalId: %d", ptNodeParams->getTerminalId());
-        return false;
-    }
-    if (!ptNodeParams->hasShortcutTargets()) {
-        // Update has shortcut targets flag.
-        return updatePtNodeFlags(ptNodeParams->getHeadPos(),
-                ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
-                ptNodeParams->isTerminal(), true /* hasShortcutTargets */,
-                ptNodeParams->hasBigrams(),
-                ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeHasBigramsAndShortcutTargetsFlags(
-        const PtNodeParams *const ptNodeParams) {
-    const bool hasBigrams = mBuffers->getBigramDictContent()->getBigramListHeadPos(
-            ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
-    const bool hasShortcutTargets = mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
-            ptNodeParams->getTerminalId()) != NOT_A_DICT_POS;
-    return updatePtNodeFlags(ptNodeParams->getHeadPos(), ptNodeParams->isBlacklisted(),
-            ptNodeParams->isNotAWord(), ptNodeParams->isTerminal(), hasShortcutTargets,
-            hasBigrams, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
-}
-
-bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, int *const outTerminalId,
-        int *const ptNodeWritingPos) {
-    const int nodePos = *ptNodeWritingPos;
-    // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the
-    // PtNode writing.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer,
-            0 /* nodeFlags */, ptNodeWritingPos)) {
-        return false;
-    }
-    // Calculate a parent offset and write the offset.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) {
-        return false;
-    }
-    // Write code points
-    if (!DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) {
-        return false;
-    }
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (!ptNodeParams->willBecomeNonTerminal()) {
-        if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) {
-            terminalId = ptNodeParams->getTerminalId();
-        } else if (ptNodeParams->isTerminal()) {
-            // Write terminal information using a new terminal id.
-            // Get a new unused terminal id.
-            terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId();
-        }
-    }
-    const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (isTerminal) {
-        // Update the lookup table.
-        if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-                terminalId, nodePos)) {
-            return false;
-        }
-        // Write terminal Id.
-        if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId,
-                Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) {
-            return false;
-        }
-        if (outTerminalId) {
-            *outTerminalId = terminalId;
-        }
-    }
-    // Write children position
-    if (!DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getChildrenPos(), ptNodeWritingPos)) {
-        return false;
-    }
-    return updatePtNodeFlags(nodePos, ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
-            isTerminal, ptNodeParams->hasShortcutTargets(), ptNodeParams->hasBigrams(),
-            ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
-}
-
-const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
-        const ProbabilityEntry *const originalProbabilityEntry,
-        const UnigramProperty *const unigramProperty) const {
-    // TODO: Consolidate historical info and probability.
-    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
-                unigramProperty->getLevel(), unigramProperty->getCount());
-        const HistoricalInfo updatedHistoricalInfo =
-                ForgettingCurveUtils::createUpdatedHistoricalInfo(
-                        originalProbabilityEntry->getHistoricalInfo(),
-                        unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
-        return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
-                &updatedHistoricalInfo);
-    } else {
-        return originalProbabilityEntry->createEntryWithUpdatedProbability(
-                unigramProperty->getProbability());
-    }
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
-        const bool isBlacklisted, const bool isNotAWord, const bool isTerminal,
-        const bool hasShortcutTargets, const bool hasBigrams, const bool hasMultipleChars) {
-    // Create node flags and write them.
-    PatriciaTrieReadingUtils::NodeFlags nodeFlags =
-            PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, isTerminal,
-                    hasShortcutTargets, hasBigrams, hasMultipleChars,
-                    CHILDREN_POSITION_FIELD_SIZE);
-    if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
-        AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
-        return false;
-    }
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
deleted file mode 100644
index d49d9a6..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h
+++ /dev/null
@@ -1,145 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H
-#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/probability_entry.h"
-#include "utils/int_array_view.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class BufferWithExtendableBuffer;
-namespace backward {
-namespace v402 {
-} // namespace v402
-} // namespace backward
-class HeaderPolicy;
-namespace backward {
-namespace v402 {
-class Ver4BigramListPolicy;
-class Ver4DictBuffers;
-class Ver4PatriciaTrieNodeReader;
-class Ver4PtNodeArrayReader;
-class Ver4ShortcutListPolicy;
-
-/*
- * This class is used for helping to writes nodes of ver4 patricia trie.
- */
-class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
- public:
-    Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer,
-            Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy,
-            const PtNodeReader *const ptNodeReader,
-            const PtNodeArrayReader *const ptNodeArrayReader,
-            Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy)
-            : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy),
-              mPtNodeReader(ptNodeReader), mReadingHelper(ptNodeReader, ptNodeArrayReader),
-              mBigramPolicy(bigramPolicy), mShortcutPolicy(shortcutPolicy) {}
-
-    virtual ~Ver4PatriciaTrieNodeWriter() {}
-
-    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
-
-    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int movedPos, const int bigramLinkedNodePos);
-
-    virtual bool markPtNodeAsWillBecomeNonTerminal(
-            const PtNodeParams *const toBeUpdatedPtNodeParams);
-
-    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const UnigramProperty *const unigramProperty);
-
-    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-            const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
-
-    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int newChildrenPosition);
-
-    bool updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int newTerminalId);
-
-    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            int *const ptNodeWritingPos);
-
-    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
-
-    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId);
-
-    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
-            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount);
-
-    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const DictPositionRelocationMap *const dictPositionRelocationMap,
-            int *const outBigramEntryCount);
-
-    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
-            const int *const targetCodePoints, const int targetCodePointCount,
-            const int shortcutProbability);
-
-    bool updatePtNodeHasBigramsAndShortcutTargetsFlags(const PtNodeParams *const ptNodeParams);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
-
-    bool writePtNodeAndGetTerminalIdAndAdvancePosition(
-            const PtNodeParams *const ptNodeParams, int *const outTerminalId,
-            int *const ptNodeWritingPos);
-
-    // Create updated probability entry using given unigram property. In addition to the
-    // probability, this method updates historical information if needed.
-    // TODO: Update flags belonging to the unigram property.
-    const ProbabilityEntry createUpdatedEntryFrom(
-            const ProbabilityEntry *const originalProbabilityEntry,
-            const UnigramProperty *const unigramProperty) const;
-
-    bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
-            const bool isTerminal, const bool hasShortcutTargets, const bool hasBigrams,
-            const bool hasMultipleChars);
-
-    static const int CHILDREN_POSITION_FIELD_SIZE;
-
-    BufferWithExtendableBuffer *const mTrieBuffer;
-    Ver4DictBuffers *const mBuffers;
-    const HeaderPolicy *const mHeaderPolicy;
-    const PtNodeReader *const mPtNodeReader;
-    DynamicPtReadingHelper mReadingHelper;
-    Ver4BigramListPolicy *const mBigramPolicy;
-    Ver4ShortcutListPolicy *const mShortcutPolicy;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_NODE_WRITER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
deleted file mode 100644
index 1296b8a..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ /dev/null
@@ -1,541 +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.
- */
-
-/*
- * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
- * Do not edit this file other than updating policy's interface.
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h"
-
-#include <vector>
-
-#include "suggest/core/dicnode/dic_node.h"
-#include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/core/dictionary/ngram_listener.h"
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/core/dictionary/property/word_property.h"
-#include "suggest/core/session/prev_words_info.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-// Note that there are corresponding definitions in Java side in BinaryDictionaryTests and
-// BinaryDictionaryDecayingTests.
-const char *const Ver4PatriciaTriePolicy::UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
-const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024;
-const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
-        Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
-
-void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
-        DicNodeVector *const childDicNodes) const {
-    if (!dicNode->hasChildren()) {
-        return;
-    }
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
-    while (!readingHelper.isEnd()) {
-        const PtNodeParams ptNodeParams = readingHelper.getPtNodeParams();
-        if (!ptNodeParams.isValid()) {
-            break;
-        }
-        bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
-        if (isTerminal && mHeaderPolicy->isDecayingDict()) {
-            // A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
-            // probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
-            // valid terminal DicNode.
-            isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
-        }
-        readingHelper.readNextSiblingNode(ptNodeParams);
-        if (ptNodeParams.representsNonWordInfo()) {
-            // Skip PtNodes that represent non-word information.
-            continue;
-        }
-        childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
-                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
-                ptNodeParams.hasChildren(),
-                ptNodeParams.isBlacklisted()
-                        || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
-                ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
-    }
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
-    }
-}
-
-int Ver4PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
-        const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
-        int *const outUnigramProbability) const {
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodePos(ptNodePos);
-    const int codePointCount =  readingHelper.getCodePointsAndProbabilityAndReturnCodePointCount(
-            maxCodePointCount, outCodePoints, outUnigramProbability);
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in getCodePointsAndProbabilityAndReturnCodePointCount().");
-    }
-    return codePointCount;
-}
-
-int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
-    }
-    return ptNodePos;
-}
-
-int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
-        const int bigramProbability) const {
-    if (mHeaderPolicy->isDecayingDict()) {
-        // Both probabilities are encoded. Decode them and get probability.
-        return ForgettingCurveUtils::getProbability(unigramProbability, bigramProbability);
-    } else {
-        if (unigramProbability == NOT_A_PROBABILITY) {
-            return NOT_A_PROBABILITY;
-        } else if (bigramProbability == NOT_A_PROBABILITY) {
-            return ProbabilityUtils::backoff(unigramProbability);
-        } else {
-            return bigramProbability;
-        }
-    }
-}
-
-int Ver4PatriciaTriePolicy::getProbabilityOfPtNode(const int *const prevWordsPtNodePos,
-        const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_PROBABILITY;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
-        return NOT_A_PROBABILITY;
-    }
-    if (prevWordsPtNodePos) {
-        const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-        BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
-        while (bigramsIt.hasNext()) {
-            bigramsIt.next();
-            if (bigramsIt.getBigramPos() == ptNodePos
-                    && bigramsIt.getProbability() != NOT_A_PROBABILITY) {
-                return getProbability(ptNodeParams.getProbability(), bigramsIt.getProbability());
-            }
-        }
-        return NOT_A_PROBABILITY;
-    }
-    return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
-}
-
-void Ver4PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordsPtNodePos,
-        NgramListener *const listener) const {
-    if (!prevWordsPtNodePos) {
-        return;
-    }
-    const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-    BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
-    while (bigramsIt.hasNext()) {
-        bigramsIt.next();
-        listener->onVisitEntry(bigramsIt.getProbability(), bigramsIt.getBigramPos());
-    }
-}
-
-int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted()) {
-        return NOT_A_DICT_POS;
-    }
-    return mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
-            ptNodeParams.getTerminalId());
-}
-
-int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted()) {
-        return NOT_A_DICT_POS;
-    }
-    return mBuffers->getBigramDictContent()->getBigramListHeadPos(
-            ptNodeParams.getTerminalId());
-}
-
-bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int length,
-        const UnigramProperty *const unigramProperty) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert to the dictionary, length: %d", length);
-        return false;
-    }
-    for (const auto &shortcut : unigramProperty->getShortcuts()) {
-        if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
-                    shortcut.getTargetCodePoints()->size());
-            return false;
-        }
-    }
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    bool addedNewUnigram = false;
-    int codePointsToAdd[MAX_WORD_LENGTH];
-    int codePointCountToAdd = length;
-    memmove(codePointsToAdd, word, sizeof(int) * length);
-    if (unigramProperty->representsBeginningOfSentence()) {
-        codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
-                codePointCountToAdd, MAX_WORD_LENGTH);
-    }
-    if (codePointCountToAdd <= 0) {
-        return false;
-    }
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointsToAdd, codePointCountToAdd,
-            unigramProperty, &addedNewUnigram)) {
-        if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
-            mUnigramCount++;
-        }
-        if (unigramProperty->getShortcuts().size() > 0) {
-            // Add shortcut target.
-            const int wordPos = getTerminalPtNodePositionOfWord(word, length,
-                    false /* forceLowerCaseSearch */);
-            if (wordPos == NOT_A_DICT_POS) {
-                AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
-                return false;
-            }
-            for (const auto &shortcut : unigramProperty->getShortcuts()) {
-                if (!mUpdatingHelper.addShortcutTarget(wordPos,
-                        shortcut.getTargetCodePoints()->data(),
-                        shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
-                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
-                            "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
-                            shortcut.getProbability());
-                    return false;
-                }
-            }
-        }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const BigramProperty *const bigramProperty) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (!prevWordsInfo->isValid()) {
-        AKLOGE("prev words info is not valid for adding n-gram entry to the dictionary.");
-        return false;
-    }
-    if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert the ngram to the dictionary. "
-                "length: %d", bigramProperty->getTargetCodePoints()->size());
-        return false;
-    }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-            false /* tryLowerCaseSearch */);
-    // TODO: Support N-gram.
-    if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
-        if (prevWordsInfo->isNthPrevWordBeginningOfSentence(1 /* n */)) {
-            const std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-            const UnigramProperty beginningOfSentenceUnigramProperty(
-                    true /* representsBeginningOfSentence */, true /* isNotAWord */,
-                    false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
-            if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
-                    prevWordsInfo->getNthPrevWordCodePointCount(1 /* n */),
-                    &beginningOfSentenceUnigramProperty)) {
-                AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
-                return false;
-            }
-            // Refresh Terminal PtNode positions.
-            prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-                    false /* tryLowerCaseSearch */);
-        } else {
-            return false;
-        }
-    }
-    const int word1Pos = getTerminalPtNodePositionOfWord(
-            bigramProperty->getTargetCodePoints()->data(),
-            bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
-    if (word1Pos == NOT_A_DICT_POS) {
-        return false;
-    }
-    bool addedNewBigram = false;
-    if (mUpdatingHelper.addNgramEntry(PtNodePosArrayView::fromObject(prevWordsPtNodePos),
-            word1Pos, bigramProperty, &addedNewBigram)) {
-        if (addedNewBigram) {
-            mBigramCount++;
-        }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const int *const word, const int length) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (!prevWordsInfo->isValid()) {
-        AKLOGE("prev words info is not valid for removing n-gram entry form the dictionary.");
-        return false;
-    }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %d", length);
-    }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-            false /* tryLowerCaseSerch */);
-    // TODO: Support N-gram.
-    if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
-        return false;
-    }
-    const int wordPos = getTerminalPtNodePositionOfWord(word, length,
-            false /* forceLowerCaseSearch */);
-    if (wordPos == NOT_A_DICT_POS) {
-        return false;
-    }
-    if (mUpdatingHelper.removeNgramEntry(
-            PtNodePosArrayView::fromObject(prevWordsPtNodePos), wordPos)) {
-        mBigramCount--;
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::flush(const char *const filePath) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath);
-        return false;
-    }
-    if (!mWritingHelper.writeToDictFile(filePath, mUnigramCount, mBigramCount)) {
-        AKLOGE("Cannot flush the dictionary to file.");
-        mIsCorrupted = true;
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) {
-        AKLOGE("Cannot flush the dictionary to file with GC.");
-        mIsCorrupted = true;
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mBuffers->isNearSizeLimit()) {
-        // Additional buffer size is near the limit.
-        return true;
-    } else if (mHeaderPolicy->getExtendedRegionSize() + mDictBuffer->getUsedAdditionalBufferSize()
-            > Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE) {
-        // Total extended region size of the trie exceeds the limit.
-        return true;
-    } else if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS
-            && mDictBuffer->getUsedAdditionalBufferSize() > 0) {
-        // Needs to reduce dictionary size.
-        return true;
-    } else if (mHeaderPolicy->isDecayingDict()) {
-        return ForgettingCurveUtils::needsToDecay(mindsBlockByGC, mUnigramCount, mBigramCount,
-                mHeaderPolicy);
-    }
-    return false;
-}
-
-void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength,
-        char *const outResult, const int maxResultLength) {
-    const int compareLength = queryLength + 1 /* terminator */;
-    if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d", mUnigramCount);
-    } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d", mBigramCount);
-    } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d",
-                mHeaderPolicy->isDecayingDict() ?
-                        ForgettingCurveUtils::getUnigramCountHardLimit(
-                                mHeaderPolicy->getMaxUnigramCount()) :
-                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d",
-                mHeaderPolicy->isDecayingDict() ?
-                        ForgettingCurveUtils::getBigramCountHardLimit(
-                                mHeaderPolicy->getMaxBigramCount()) :
-                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    }
-}
-
-const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
-            false /* forceLowerCaseSearch */);
-    if (ptNodePos == NOT_A_DICT_POS) {
-        AKLOGE("getWordProperty is called for invalid word.");
-        return WordProperty();
-    }
-    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
-            ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
-    const ProbabilityEntry probabilityEntry =
-            mBuffers->getProbabilityDictContent()->getProbabilityEntry(
-                    ptNodeParams.getTerminalId());
-    const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
-    // Fetch bigram information.
-    std::vector<BigramProperty> bigrams;
-    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
-    if (bigramListPos != NOT_A_DICT_POS) {
-        int bigramWord1CodePoints[MAX_WORD_LENGTH];
-        const BigramDictContent *const bigramDictContent = mBuffers->getBigramDictContent();
-        const TerminalPositionLookupTable *const terminalPositionLookupTable =
-                mBuffers->getTerminalPositionLookupTable();
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            hasNext = bigramEntry.hasNext();
-            const int word1TerminalId = bigramEntry.getTargetTerminalId();
-            const int word1TerminalPtNodePos =
-                    terminalPositionLookupTable->getTerminalPtNodePosition(word1TerminalId);
-            if (word1TerminalPtNodePos == NOT_A_DICT_POS) {
-                continue;
-            }
-            // Word (unigram) probability
-            int word1Probability = NOT_A_PROBABILITY;
-            const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-                    word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
-                    &word1Probability);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + codePointCount);
-            const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
-                    bigramEntry.getProbability();
-            bigrams.emplace_back(&word1, probability,
-                    historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                    historicalInfo->getCount());
-        }
-    }
-    // Fetch shortcut information.
-    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-    int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
-    if (shortcutPos != NOT_A_DICT_POS) {
-        int shortcutTarget[MAX_WORD_LENGTH];
-        const ShortcutDictContent *const shortcutDictContent =
-                mBuffers->getShortcutDictContent();
-        bool hasNext = true;
-        while (hasNext) {
-            int shortcutTargetLength = 0;
-            int shortcutProbability = NOT_A_PROBABILITY;
-            shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
-                    &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
-            const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcuts.emplace_back(&target, shortcutProbability);
-        }
-    }
-    const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
-            ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
-            historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-            historicalInfo->getCount(), &shortcuts);
-    return WordProperty(&codePointVector, &unigramProperty, &bigrams);
-}
-
-int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
-        int *const outCodePointCount) {
-    *outCodePointCount = 0;
-    if (token == 0) {
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
-                &mTerminalPtNodePositionsForIteratingWords);
-        DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-        readingHelper.initWithPtNodeArrayPos(getRootPosition());
-        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
-    }
-    const int terminalPtNodePositionsVectorSize =
-            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
-    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
-        AKLOGE("Given token %d is invalid.", token);
-        return 0;
-    }
-    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
-    int unigramProbability = NOT_A_PROBABILITY;
-    *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-            terminalPtNodePos, MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
-    const int nextToken = token + 1;
-    if (nextToken >= terminalPtNodePositionsVectorSize) {
-        // All words have been iterated.
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        return 0;
-    }
-    return nextToken;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
deleted file mode 100644
index 9e989b2..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h
+++ /dev/null
@@ -1,173 +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.
- */
-
-/*
- * !!!!! DO NOT CHANGE THE LOGIC IN THIS FILE !!!!!
- * Do not edit this file other than updating policy's interface.
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
-#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
-
-#include <vector>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class DicNode;
-namespace backward {
-namespace v402 {
-} // namespace v402
-} // namespace backward
-class DicNodeVector;
-namespace backward {
-namespace v402 {
-
-class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
- public:
-    Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
-            : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
-              mDictBuffer(mBuffers->getWritableTrieBuffer()),
-              mBigramPolicy(mBuffers->getMutableBigramDictContent(),
-                      mBuffers->getTerminalPositionLookupTable(), mHeaderPolicy),
-              mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
-                      mBuffers->getTerminalPositionLookupTable()),
-              mNodeReader(mDictBuffer, mBuffers->getProbabilityDictContent(), mHeaderPolicy),
-              mPtNodeArrayReader(mDictBuffer),
-              mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
-                      &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy),
-              mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
-              mWritingHelper(mBuffers.get()),
-              mUnigramCount(mHeaderPolicy->getUnigramCount()),
-              mBigramCount(mHeaderPolicy->getBigramCount()),
-              mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
-
-    AK_FORCE_INLINE int getRootPosition() const {
-        return 0;
-    }
-
-    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
-            DicNodeVector *const childDicNodes) const;
-
-    int getCodePointsAndProbabilityAndReturnCodePointCount(
-            const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
-            int *const outUnigramProbability) const;
-
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
-
-    int getProbability(const int unigramProbability, const int bigramProbability) const;
-
-    int getProbabilityOfPtNode(const int *const prevWordsPtNodePos, const int ptNodePos) const;
-
-    void iterateNgramEntries(const int *const prevWordsPtNodePos,
-            NgramListener *const listener) const;
-
-    int getShortcutPositionOfPtNode(const int ptNodePos) const;
-
-    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
-        return mHeaderPolicy;
-    }
-
-    const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const {
-        return &mShortcutPolicy;
-    }
-
-    bool addUnigramEntry(const int *const word, const int length,
-            const UnigramProperty *const unigramProperty);
-
-    bool removeUnigramEntry(const int *const word, const int length) {
-        // Removing unigram entry is not supported.
-        return false;
-    }
-
-    bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const BigramProperty *const bigramProperty);
-
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word1,
-            const int length1);
-
-    bool flush(const char *const filePath);
-
-    bool flushWithGC(const char *const filePath);
-
-    bool needsToRunGC(const bool mindsBlockByGC) const;
-
-    void getProperty(const char *const query, const int queryLength, char *const outResult,
-            const int maxResultLength);
-
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
-
-    int getNextWordAndNextToken(const int token, int *const outCodePoints,
-            int *const outCodePointCount);
-
-    bool isCorrupted() const {
-        return mIsCorrupted;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
-
-    static const char *const UNIGRAM_COUNT_QUERY;
-    static const char *const BIGRAM_COUNT_QUERY;
-    static const char *const MAX_UNIGRAM_COUNT_QUERY;
-    static const char *const MAX_BIGRAM_COUNT_QUERY;
-    // When the dictionary size is near the maximum size, we have to refuse dynamic operations to
-    // prevent the dictionary from overflowing.
-    static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
-    static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
-
-    const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
-    const HeaderPolicy *const mHeaderPolicy;
-    BufferWithExtendableBuffer *const mDictBuffer;
-    Ver4BigramListPolicy mBigramPolicy;
-    Ver4ShortcutListPolicy mShortcutPolicy;
-    Ver4PatriciaTrieNodeReader mNodeReader;
-    Ver4PtNodeArrayReader mPtNodeArrayReader;
-    Ver4PatriciaTrieNodeWriter mNodeWriter;
-    DynamicPtUpdatingHelper mUpdatingHelper;
-    Ver4PatriciaTrieWritingHelper mWritingHelper;
-    int mUnigramCount;
-    int mBigramCount;
-    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
-    mutable bool mIsCorrupted;
-
-    int getBigramsPositionOfPtNode(const int ptNodePos) const;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif // LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp
deleted file mode 100644
index 80d5311..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.cpp
+++ /dev/null
@@ -1,39 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h"
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(
-        const uint8_t *const buffer, int *pos) {
-    return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos);
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h
deleted file mode 100644
index 3579c26..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_reading_utils.h
+++ /dev/null
@@ -1,52 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H
-#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class BufferWithExtendableBuffer;
-namespace backward {
-namespace v402 {
-
-class Ver4PatriciaTrieReadingUtils {
- public:
-    static int getTerminalIdAndAdvancePosition(const uint8_t *const buffer,
-            int *const pos);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieReadingUtils);
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_READING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
deleted file mode 100644
index 3fb4caa..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.cpp
+++ /dev/null
@@ -1,304 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h"
-
-#include <cstring>
-#include <queue>
-
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-bool Ver4PatriciaTrieWritingHelper::writeToDictFile(const char *const dictDirPath,
-        const int unigramCount, const int bigramCount) const {
-    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
-    BufferWithExtendableBuffer headerBuffer(
-            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
-    const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
-            + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
-            unigramCount, bigramCount, extendedRegionSize, &headerBuffer)) {
-        AKLOGE("Cannot write header structure to buffer. "
-                "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, "
-                "extendedRegionSize: %d", false, unigramCount, bigramCount,
-                extendedRegionSize);
-        return false;
-    }
-    return mBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
-}
-
-bool Ver4PatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
-        const char *const dictDirPath) {
-    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
-    Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
-            Ver4DictBuffers::createVer4DictBuffers(headerPolicy,
-                    Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    int unigramCount = 0;
-    int bigramCount = 0;
-    if (!runGC(rootPtNodeArrayPos, headerPolicy, dictBuffers.get(), &unigramCount, &bigramCount)) {
-        return false;
-    }
-    BufferWithExtendableBuffer headerBuffer(
-            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
-            unigramCount, bigramCount, 0 /* extendedRegionSize */, &headerBuffer)) {
-        return false;
-    }
-    return dictBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
-}
-
-bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
-        const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
-        int *const outUnigramCount, int *const outBigramCount) {
-    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
-            mBuffers->getProbabilityDictContent(), headerPolicy);
-    Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
-    Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(),
-            mBuffers->getTerminalPositionLookupTable(), headerPolicy);
-    Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
-            mBuffers->getTerminalPositionLookupTable());
-    Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
-            mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
-
-    DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners
-            ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-                    traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
-                            &ptNodeWriter);
-    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
-        return false;
-    }
-    const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-            .getValidUnigramCount();
-    const int maxUnigramCount = headerPolicy->getMaxUnigramCount();
-    if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) {
-        if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) {
-            AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount,
-                    maxUnigramCount);
-            return false;
-        }
-    }
-
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
-            traversePolicyToUpdateBigramProbability(&ptNodeWriter);
-    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateBigramProbability)) {
-        return false;
-    }
-    const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount();
-    const int maxBigramCount = headerPolicy->getMaxBigramCount();
-    if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) {
-        if (!truncateBigrams(maxBigramCount)) {
-            AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount);
-            return false;
-        }
-    }
-
-    // Mapping from positions in mBuffer to positions in bufferToWrite.
-    PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
-    DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-            traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
-                    buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
-    if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-            &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
-        return false;
-    }
-
-    // Create policy instances for the GCed dictionary.
-    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
-            buffersToWrite->getProbabilityDictContent(), headerPolicy);
-    Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
-    Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(),
-            buffersToWrite->getTerminalPositionLookupTable(), headerPolicy);
-    Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
-            buffersToWrite->getTerminalPositionLookupTable());
-    Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy,
-            &newShortcutPolicy);
-    // Re-assign terminal IDs for valid terminal PtNodes.
-    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
-    if(!buffersToWrite->getMutableTerminalPositionLookupTable()->runGCTerminalIds(
-            &terminalIdMap)) {
-        return false;
-    }
-    // Run GC for probability dict content.
-    if (!buffersToWrite->getMutableProbabilityDictContent()->runGC(&terminalIdMap,
-            mBuffers->getProbabilityDictContent())) {
-        return false;
-    }
-    // Run GC for bigram dict content.
-    if(!buffersToWrite->getMutableBigramDictContent()->runGC(&terminalIdMap,
-            mBuffers->getBigramDictContent(), outBigramCount)) {
-        return false;
-    }
-    // Run GC for shortcut dict content.
-    if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
-            mBuffers->getShortcutDictContent())) {
-        return false;
-    }
-    DynamicPtReadingHelper newDictReadingHelper(&newPtNodeReader, &newPtNodeArrayreader);
-    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
-            traversePolicyToUpdateAllPositionFields(&newPtNodeWriter, &dictPositionRelocationMap);
-    if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-            &traversePolicyToUpdateAllPositionFields)) {
-        return false;
-    }
-    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-            traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(&newPtNodeWriter, &terminalIdMap);
-    if (!newDictReadingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
-        return false;
-    }
-    *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount();
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
-        const Ver4PatriciaTrieNodeReader *const ptNodeReader,
-        Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int terminalPos = terminalPosLookupTable->getTerminalPtNodePosition(i);
-        if (terminalPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        const ProbabilityEntry probabilityEntry =
-                mBuffers->getProbabilityDictContent()->getProbabilityEntry(i);
-        const int probability = probabilityEntry.hasHistoricalInfo() ?
-                ForgettingCurveUtils::decodeProbability(
-                        probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                probabilityEntry.getProbability();
-        priorityQueue.push(DictProbability(terminalPos, probability,
-                probabilityEntry.getHistoricalInfo()->getTimeStamp()));
-    }
-
-    // Delete unigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxUnigramCount) {
-        const int ptNodePos = priorityQueue.top().getDictPos();
-        priorityQueue.pop();
-        const PtNodeParams ptNodeParams =
-                ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-        if (ptNodeParams.representsNonWordInfo()) {
-            continue;
-        }
-        if (!ptNodeWriter->markPtNodeAsWillBecomeNonTerminal(&ptNodeParams)) {
-            AKLOGE("Cannot mark PtNode as willBecomeNonterminal. PtNode pos: %d", ptNodePos);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    BigramDictContent *const bigramDictContent = mBuffers->getMutableBigramDictContent();
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int bigramListPos = bigramDictContent->getBigramListHeadPos(i);
-        if (bigramListPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const int entryPos = readingPos;
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            hasNext = bigramEntry.hasNext();
-            if (!bigramEntry.isValid()) {
-                continue;
-            }
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                    bigramEntry.getProbability();
-            priorityQueue.push(DictProbability(entryPos, probability,
-                    bigramEntry.getHistoricalInfo()->getTimeStamp()));
-        }
-    }
-
-    // Delete bigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxBigramCount) {
-        const int entryPos = priorityQueue.top().getDictPos();
-        const BigramEntry bigramEntry = bigramDictContent->getBigramEntry(entryPos);
-        const BigramEntry invalidatedBigramEntry = bigramEntry.getInvalidatedEntry();
-        if (!bigramDictContent->writeBigramEntry(&invalidatedBigramEntry, entryPos)) {
-            AKLOGE("Cannot write bigram entry to remove. pos: %d", entryPos);
-            return false;
-        }
-        priorityQueue.pop();
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    if (!ptNodeParams->isTerminal()) {
-        return true;
-    }
-    TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
-            mTerminalIdMap->find(ptNodeParams->getTerminalId());
-    if (it == mTerminalIdMap->end()) {
-        AKLOGE("terminal Id %d is not in the terminal position map. map size: %zd",
-                ptNodeParams->getTerminalId(), mTerminalIdMap->size());
-        return false;
-    }
-    if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
-        AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
-    }
-    return mPtNodeWriter->updatePtNodeHasBigramsAndShortcutTargetsFlags(ptNodeParams);
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h
deleted file mode 100644
index 9034ee6..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_writing_helper.h
+++ /dev/null
@@ -1,140 +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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H
-#define LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/content/terminal_position_lookup_table.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class HeaderPolicy;
-namespace backward {
-namespace v402 {
-class Ver4DictBuffers;
-class Ver4PatriciaTrieNodeReader;
-class Ver4PatriciaTrieNodeWriter;
-
-class Ver4PatriciaTrieWritingHelper {
- public:
-    Ver4PatriciaTrieWritingHelper(Ver4DictBuffers *const buffers)
-            : mBuffers(buffers) {}
-
-    bool writeToDictFile(const char *const dictDirPath, const int unigramCount,
-            const int bigramCount) const;
-
-    // This method cannot be const because the original dictionary buffer will be updated to detect
-    // useless PtNodes during GC.
-    bool writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const dictDirPath);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieWritingHelper);
-
-    class TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-            : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(
-                Ver4PatriciaTrieNodeWriter *const ptNodeWriter,
-                const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap)
-                : mPtNodeWriter(ptNodeWriter), mTerminalIdMap(terminalIdMap) {}
-
-        bool onAscend() { return true; }
-
-        bool onDescend(const int ptNodeArrayPos) { return true; }
-
-        bool onReadingPtNodeArrayTail() { return true; }
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds);
-
-        Ver4PatriciaTrieNodeWriter *const mPtNodeWriter;
-        const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
-    };
-
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbability {
-     public:
-        DictProbability(const int dictPos, const int probability, const int timestamp)
-                : mDictPos(dictPos), mProbability(probability), mTimestamp(timestamp) {}
-
-        int getDictPos() const {
-            return mDictPos;
-        }
-
-        int getProbability() const {
-            return mProbability;
-        }
-
-        int getTimestamp() const {
-            return mTimestamp;
-        }
-
-     private:
-        DISALLOW_DEFAULT_CONSTRUCTOR(DictProbability);
-
-        int mDictPos;
-        int mProbability;
-        int mTimestamp;
-    };
-
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbabilityComparator {
-     public:
-        bool operator()(const DictProbability &left, const DictProbability &right) {
-            if (left.getProbability() != right.getProbability()) {
-                return left.getProbability() > right.getProbability();
-            }
-            if (left.getTimestamp() != right.getTimestamp()) {
-                return left.getTimestamp() < right.getTimestamp();
-            }
-            return left.getDictPos() > right.getDictPos();
-        }
-
-     private:
-        DISALLOW_ASSIGNMENT_OPERATOR(DictProbabilityComparator);
-    };
-
-    bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
-            Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount,
-            int *const outBigramCount);
-
-    bool truncateUnigrams(const Ver4PatriciaTrieNodeReader *const ptNodeReader,
-            Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount);
-
-    bool truncateBigrams(const int maxBigramCount);
-
-    Ver4DictBuffers *const mBuffers;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-
-#endif /* LATINIME_BACKWARD_V402_VER4_PATRICIA_TRIE_WRITING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp
deleted file mode 100644
index 537a6d4..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
- */
-
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
-    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of a bug or a broken dictionary.
-        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
-                ptNodeArrayPos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return false;
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int readingPos = ptNodeArrayPos;
-    if (usesAdditionalBuffer) {
-        readingPos -= mBuffer->getOriginalBufferSize();
-    }
-    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-            dictBuf, &readingPos);
-    if (usesAdditionalBuffer) {
-        readingPos += mBuffer->getOriginalBufferSize();
-    }
-    if (ptNodeCountInArray < 0) {
-        AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
-        return false;
-    }
-    *outPtNodeCount = ptNodeCountInArray;
-    *outFirstPtNodePos = readingPos;
-    return true;
-}
-
-bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-        int *const outNextPtNodeArrayPos) const {
-    if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
-                forwordLinkPos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return false;
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int readingPos = forwordLinkPos;
-    if (usesAdditionalBuffer) {
-        readingPos -= mBuffer->getOriginalBufferSize();
-    }
-    const int nextPtNodeArrayOffset =
-            DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
-    if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
-        *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
-    } else {
-        *outNextPtNodeArrayPos = NOT_A_DICT_POS;
-    }
-    return true;
-}
-
-} // namespace v402
-} // namespace backward
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h
deleted file mode 100644
index 4f80568..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_pt_node_array_reader.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-/*
- * !!!!! DO NOT EDIT THIS FILE !!!!!
- *
- * This file was generated from
- *   suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h
- */
-
-#ifndef LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H
-#define LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h"
-
-namespace latinime {
-namespace backward {
-namespace v402 {
-
-} // namespace v402
-} // namespace backward
-class BufferWithExtendableBuffer;
-namespace backward {
-namespace v402 {
-
-class Ver4PtNodeArrayReader : public PtNodeArrayReader {
- public:
-    Ver4PtNodeArrayReader(const BufferWithExtendableBuffer *const buffer) : mBuffer(buffer) {};
-
-    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
-    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-            int *const outNextPtNodeArrayPos) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PtNodeArrayReader);
-
-    const BufferWithExtendableBuffer *const mBuffer;
-};
-} // namespace v402
-} // namespace backward
-} // namespace latinime
-#endif /* LATINIME_BACKWARD_V402_VER4_PT_NODE_ARRAY_READER_H */
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
deleted file mode 100644
index e4ea3da..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.cpp
+++ /dev/null
@@ -1,205 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h"
-
-#include <climits>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyForExistingDictFile(
-                const char *const path, const int bufOffset, const int size,
-                const bool isUpdatable) {
-    if (FileUtils::existsDir(path)) {
-        // Given path represents a directory.
-        return newPolicyForDirectoryDict(path, isUpdatable);
-    } else {
-        if (isUpdatable) {
-            AKLOGE("One file dictionaries don't support updating. path: %s", path);
-            ASSERT(false);
-            return nullptr;
-        }
-        return newPolicyForFileDict(path, bufOffset, size);
-    }
-}
-
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory:: newPolicyForOnMemoryDict(
-                const int formatVersion, const std::vector<int> &locale,
-                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
-    FormatUtils::FORMAT_VERSION dictFormatVersion = FormatUtils::getFormatVersion(formatVersion);
-    switch (dictFormatVersion) {
-        case FormatUtils::VERSION_4: {
-            return newPolicyForOnMemoryV4Dict<backward::v402::Ver4DictConstants,
-                    backward::v402::Ver4DictBuffers,
-                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
-                    backward::v402::Ver4PatriciaTriePolicy>(
-                            dictFormatVersion, locale, attributeMap);
-        }
-        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-        case FormatUtils::VERSION_4_DEV: {
-            return newPolicyForOnMemoryV4Dict<Ver4DictConstants, Ver4DictBuffers,
-                    Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
-                            dictFormatVersion, locale, attributeMap);
-        }
-        default:
-            AKLOGE("DICT: dictionary format %d is not supported for on memory dictionary",
-                    formatVersion);
-            break;
-    }
-    return nullptr;
-}
-
-template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyForOnMemoryV4Dict(
-                const FormatUtils::FORMAT_VERSION formatVersion,
-                const std::vector<int> &locale,
-                const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
-    HeaderPolicy headerPolicy(formatVersion, locale, attributeMap);
-    DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
-            DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
-    if (!DynamicPtWritingUtils::writeEmptyDictionary(
-            dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
-        AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
-        return nullptr;
-    }
-    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
-            new StructurePolicy(std::move(dictBuffers)));
-}
-
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyForDirectoryDict(
-                const char *const path, const bool isUpdatable) {
-    const int headerFilePathBufSize = PATH_MAX + 1 /* terminator */;
-    char headerFilePath[headerFilePathBufSize];
-    getHeaderFilePathInDictDir(path, headerFilePathBufSize, headerFilePath);
-    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
-    // MmappedBufferPtr if the instance has the responsibility.
-    MmappedBuffer::MmappedBufferPtr mmappedBuffer =
-            MmappedBuffer::openBuffer(headerFilePath, isUpdatable);
-    if (!mmappedBuffer) {
-        return nullptr;
-    }
-    const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::detectFormatVersion(
-            mmappedBuffer->getReadOnlyByteArrayView().data(),
-            mmappedBuffer->getReadOnlyByteArrayView().size());
-    switch (formatVersion) {
-        case FormatUtils::VERSION_2:
-            AKLOGE("Given path is a directory but the format is version 2. path: %s", path);
-            break;
-        case FormatUtils::VERSION_4: {
-            return newPolicyForV4Dict<backward::v402::Ver4DictConstants,
-                    backward::v402::Ver4DictBuffers,
-                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr,
-                    backward::v402::Ver4PatriciaTriePolicy>(
-                            headerFilePath, formatVersion, std::move(mmappedBuffer));
-        }
-        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-        case FormatUtils::VERSION_4_DEV: {
-            return newPolicyForV4Dict<Ver4DictConstants, Ver4DictBuffers,
-                    Ver4DictBuffers::Ver4DictBuffersPtr, Ver4PatriciaTriePolicy>(
-                            headerFilePath, formatVersion, std::move(mmappedBuffer));
-        }
-        default:
-            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
-            break;
-    }
-    ASSERT(false);
-    return nullptr;
-}
-
-template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyForV4Dict(
-                const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
-                MmappedBuffer::MmappedBufferPtr &&mmappedBuffer) {
-    const int dictDirPathBufSize = strlen(headerFilePath) + 1 /* terminator */;
-    char dictPath[dictDirPathBufSize];
-    if (!FileUtils::getFilePathWithoutSuffix(headerFilePath,
-            DictConstants::HEADER_FILE_EXTENSION, dictDirPathBufSize, dictPath)) {
-        AKLOGE("Dictionary file name is not valid as a ver4 dictionary. header path: %s",
-                headerFilePath);
-        ASSERT(false);
-        return nullptr;
-    }
-    DictBuffersPtr dictBuffers =
-            DictBuffers::openVer4DictBuffers(dictPath, std::move(mmappedBuffer), formatVersion);
-    if (!dictBuffers || !dictBuffers->isValid()) {
-        AKLOGE("DICT: The dictionary doesn't satisfy ver4 format requirements. path: %s",
-                dictPath);
-        ASSERT(false);
-        return nullptr;
-    }
-    return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
-            new StructurePolicy(std::move(dictBuffers)));
-}
-
-/* static */ DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-        DictionaryStructureWithBufferPolicyFactory::newPolicyForFileDict(
-                const char *const path, const int bufOffset, const int size) {
-    // Allocated buffer in MmapedBuffer::openBuffer() will be freed in the destructor of
-    // MmappedBufferPtr if the instance has the responsibility.
-    MmappedBuffer::MmappedBufferPtr mmappedBuffer(
-            MmappedBuffer::openBuffer(path, bufOffset, size, false /* isUpdatable */));
-    if (!mmappedBuffer) {
-        return nullptr;
-    }
-    switch (FormatUtils::detectFormatVersion(mmappedBuffer->getReadOnlyByteArrayView().data(),
-            mmappedBuffer->getReadOnlyByteArrayView().size())) {
-        case FormatUtils::VERSION_2:
-            return DictionaryStructureWithBufferPolicy::StructurePolicyPtr(
-                    new PatriciaTriePolicy(std::move(mmappedBuffer)));
-        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-        case FormatUtils::VERSION_4:
-        case FormatUtils::VERSION_4_DEV:
-            AKLOGE("Given path is a file but the format is version 4. path: %s", path);
-            break;
-        default:
-            AKLOGE("DICT: dictionary format is unknown, bad magic number. path: %s", path);
-            break;
-    }
-    ASSERT(false);
-    return nullptr;
-}
-
-/* static */ void DictionaryStructureWithBufferPolicyFactory::getHeaderFilePathInDictDir(
-        const char *const dictDirPath, const int outHeaderFileBufSize,
-        char *const outHeaderFilePath) {
-    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
-    char dictName[dictNameBufSize];
-    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
-    snprintf(outHeaderFilePath, outHeaderFileBufSize, "%s/%s%s", dictDirPath,
-            dictName, Ver4DictConstants::HEADER_FILE_EXTENSION);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h b/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
deleted file mode 100644
index 768454d..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/dictionary_structure_with_buffer_policy_factory.h
+++ /dev/null
@@ -1,64 +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.
- */
-
-#ifndef LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
-#define LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
-
-#include <vector>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-
-namespace latinime {
-
-class DictionaryStructureWithBufferPolicyFactory {
- public:
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyForExistingDictFile(const char *const path, const int bufOffset,
-                    const int size, const bool isUpdatable);
-
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyForOnMemoryDict(const int formatVersion, const std::vector<int> &locale,
-                    const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(DictionaryStructureWithBufferPolicyFactory);
-
-    template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyForOnMemoryV4Dict(const FormatUtils::FORMAT_VERSION formatVersion,
-                    const std::vector<int> &locale,
-                    const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
-
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyForDirectoryDict(const char *const path, const bool isUpdatable);
-
-    template<class DictConstants, class DictBuffers, class DictBuffersPtr, class StructurePolicy>
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr newPolicyForV4Dict(
-            const char *const headerFilePath, const FormatUtils::FORMAT_VERSION formatVersion,
-                    MmappedBuffer::MmappedBufferPtr &&mmappedBuffer);
-
-    static DictionaryStructureWithBufferPolicy::StructurePolicyPtr
-            newPolicyForFileDict(const char *const path, const int bufOffset, const int size);
-
-    static void getHeaderFilePathInDictDir(const char *const dirPath,
-            const int outHeaderFileBufSize, char *const outHeaderFilePath);
-};
-} // namespace latinime
-#endif // LATINIME_DICTIONARY_STRUCTURE_WITH_BUFFER_POLICY_FACTORY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
deleted file mode 100644
index f7fd5c0..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.cpp
+++ /dev/null
@@ -1,96 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const BigramListReadWriteUtils::BigramFlags BigramListReadWriteUtils::MASK_ATTRIBUTE_ADDRESS_TYPE =
-        0x30;
-const BigramListReadWriteUtils::BigramFlags
-        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
-const BigramListReadWriteUtils::BigramFlags
-        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
-const BigramListReadWriteUtils::BigramFlags
-        BigramListReadWriteUtils::FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
-const BigramListReadWriteUtils::BigramFlags
-        BigramListReadWriteUtils::FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40;
-// Flag for presence of more attributes
-const BigramListReadWriteUtils::BigramFlags BigramListReadWriteUtils::FLAG_ATTRIBUTE_HAS_NEXT =
-        0x80;
-// Mask for attribute probability, stored on 4 bits inside the flags byte.
-const BigramListReadWriteUtils::BigramFlags
-        BigramListReadWriteUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
-
-/* static */ bool BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(
-        const uint8_t *const bigramsBuf, const int bufSize, BigramFlags *const outBigramFlags,
-        int *const outTargetPtNodePos, int *const bigramEntryPos) {
-    if (bufSize <= *bigramEntryPos) {
-        AKLOGE("Read invalid pos in getBigramEntryPropertiesAndAdvancePosition(). bufSize: %d, "
-                "bigramEntryPos: %d.", bufSize, *bigramEntryPos);
-        return false;
-    }
-    const BigramFlags bigramFlags = ByteArrayUtils::readUint8AndAdvancePosition(bigramsBuf,
-            bigramEntryPos);
-    if (outBigramFlags) {
-        *outBigramFlags = bigramFlags;
-    }
-    const int targetPos = getBigramAddressAndAdvancePosition(bigramsBuf, bigramFlags,
-            bigramEntryPos);
-    if (outTargetPtNodePos) {
-        *outTargetPtNodePos = targetPos;
-    }
-    return true;
-}
-
-/* static */ bool BigramListReadWriteUtils::skipExistingBigrams(const uint8_t *const bigramsBuf,
-        const int bufSize, int *const bigramListPos) {
-    BigramFlags flags;
-    do {
-        if (!getBigramEntryPropertiesAndAdvancePosition(bigramsBuf, bufSize, &flags,
-                0 /* outTargetPtNodePos */, bigramListPos)) {
-            return false;
-        }
-    } while(hasNext(flags));
-    return true;
-}
-
-/* static */ int BigramListReadWriteUtils::getBigramAddressAndAdvancePosition(
-        const uint8_t *const bigramsBuf, const BigramFlags flags, int *const pos) {
-    int offset = 0;
-    const int origin = *pos;
-    switch (MASK_ATTRIBUTE_ADDRESS_TYPE & flags) {
-        case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE:
-            offset = ByteArrayUtils::readUint8AndAdvancePosition(bigramsBuf, pos);
-            break;
-        case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES:
-            offset = ByteArrayUtils::readUint16AndAdvancePosition(bigramsBuf, pos);
-            break;
-        case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES:
-            offset = ByteArrayUtils::readUint24AndAdvancePosition(bigramsBuf, pos);
-            break;
-    }
-    if (isOffsetNegative(flags)) {
-        return origin - offset;
-    } else {
-        return origin + offset;
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
deleted file mode 100644
index 10f93fb..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h
+++ /dev/null
@@ -1,68 +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.
- */
-
-#ifndef LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
-#define LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
-
-#include <cstdint>
-#include <cstdlib>
-
-#include "defines.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-
-class BigramListReadWriteUtils {
-public:
-   typedef uint8_t BigramFlags;
-
-   static bool getBigramEntryPropertiesAndAdvancePosition(const uint8_t *const bigramsBuf,
-           const int bufSize, BigramFlags *const outBigramFlags, int *const outTargetPtNodePos,
-           int *const bigramEntryPos);
-
-   static AK_FORCE_INLINE int getProbabilityFromFlags(const BigramFlags flags) {
-       return flags & MASK_ATTRIBUTE_PROBABILITY;
-   }
-
-   static AK_FORCE_INLINE bool hasNext(const BigramFlags flags) {
-       return (flags & FLAG_ATTRIBUTE_HAS_NEXT) != 0;
-   }
-
-   // Bigrams reading methods
-   static bool skipExistingBigrams(const uint8_t *const bigramsBuf, const int bufSize,
-           int *const bigramListPos);
-
-private:
-   DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListReadWriteUtils);
-
-   static const BigramFlags MASK_ATTRIBUTE_ADDRESS_TYPE;
-   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE;
-   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES;
-   static const BigramFlags FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES;
-   static const BigramFlags FLAG_ATTRIBUTE_OFFSET_NEGATIVE;
-   static const BigramFlags FLAG_ATTRIBUTE_HAS_NEXT;
-   static const BigramFlags MASK_ATTRIBUTE_PROBABILITY;
-
-   static AK_FORCE_INLINE bool isOffsetNegative(const BigramFlags flags) {
-       return (flags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) != 0;
-   }
-
-   static int getBigramAddressAndAdvancePosition(const uint8_t *const bigramsBuf,
-           const BigramFlags flags, int *const pos);
-};
-} // namespace latinime
-#endif // LATINIME_BIGRAM_LIST_READ_WRITE_UTILS_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
deleted file mode 100644
index db1a802..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.cpp
+++ /dev/null
@@ -1,144 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
-
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
-
-namespace latinime {
-
-bool DynamicPtGcEventListeners
-        ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-                ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    // PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
-    // children.
-    bool isUselessPtNode = !ptNodeParams->isTerminal();
-    if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
-        bool needsToKeepPtNode = true;
-        if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-                ptNodeParams, &needsToKeepPtNode)) {
-            AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC.");
-            return false;
-        }
-        if (!needsToKeepPtNode) {
-            isUselessPtNode = true;
-        }
-    }
-    if (mChildrenValue > 0) {
-        isUselessPtNode = false;
-    } else if (ptNodeParams->isTerminal()) {
-        // Remove children as all children are useless.
-        if (!mPtNodeWriter->updateChildrenPosition(ptNodeParams,
-                NOT_A_DICT_POS /* newChildrenPosition */)) {
-            return false;
-        }
-    }
-    if (isUselessPtNode) {
-        // Current PtNode is no longer needed. Mark it as deleted.
-        if (!mPtNodeWriter->markPtNodeAsDeleted(ptNodeParams)) {
-            return false;
-        }
-    } else {
-        mValueStack.back() += 1;
-        if (ptNodeParams->isTerminal() && !ptNodeParams->representsNonWordInfo()) {
-            mValidUnigramCount += 1;
-        }
-    }
-    return true;
-}
-
-bool DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
-        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    if (!ptNodeParams->isDeleted()) {
-        int bigramEntryCount = 0;
-        if (!mPtNodeWriter->updateAllBigramEntriesAndDeleteUselessEntries(ptNodeParams,
-                &bigramEntryCount)) {
-            return false;
-        }
-        mValidBigramEntryCount += bigramEntryCount;
-    }
-    return true;
-}
-
-// Writes dummy PtNode array size when the head of PtNode array is read.
-bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-        ::onDescend(const int ptNodeArrayPos) {
-    mValidPtNodeCount = 0;
-    int writingPos = mBufferToWrite->getTailPosition();
-    mDictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.insert(
-            PtNodeWriter::PtNodeArrayPositionRelocationMap::value_type(ptNodeArrayPos, writingPos));
-    // Writes dummy PtNode array size because arrays can have a forward link or needles PtNodes.
-    // This field will be updated later in onReadingPtNodeArrayTail() with actual PtNode count.
-    mPtNodeArraySizeFieldPos = writingPos;
-    return DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
-            mBufferToWrite, 0 /* arraySize */, &writingPos);
-}
-
-// Write PtNode array terminal and actual PtNode array size.
-bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-        ::onReadingPtNodeArrayTail() {
-    int writingPos = mBufferToWrite->getTailPosition();
-    // Write PtNode array terminal.
-    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
-            mBufferToWrite, NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
-        return false;
-    }
-    // Write actual PtNode array size.
-    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
-            mBufferToWrite, mValidPtNodeCount, &mPtNodeArraySizeFieldPos)) {
-        return false;
-    }
-    return true;
-}
-
-// Write valid PtNode to buffer and memorize mapping from the old position to the new position.
-bool DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    if (ptNodeParams->isDeleted()) {
-        // Current PtNode is not written in new buffer because it has been deleted.
-        mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
-                PtNodeWriter::PtNodePositionRelocationMap::value_type(
-                        ptNodeParams->getHeadPos(), NOT_A_DICT_POS));
-        return true;
-    }
-    int writingPos = mBufferToWrite->getTailPosition();
-    mDictPositionRelocationMap->mPtNodePositionRelocationMap.insert(
-            PtNodeWriter::PtNodePositionRelocationMap::value_type(
-                    ptNodeParams->getHeadPos(), writingPos));
-    mValidPtNodeCount++;
-    // Writes current PtNode.
-    return mPtNodeWriter->writePtNodeAndAdvancePosition(ptNodeParams, &writingPos);
-}
-
-bool DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
-        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    // Updates parent position.
-    int bigramCount = 0;
-    if (!mPtNodeWriter->updateAllPositionFields(ptNodeParams, mDictPositionRelocationMap,
-            &bigramCount)) {
-        return false;
-    }
-    mBigramCount += bigramCount;
-    if (ptNodeParams->isTerminal()) {
-        mUnigramCount++;
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h
deleted file mode 100644
index 2aa4027..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h
+++ /dev/null
@@ -1,172 +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.
- */
-
-#ifndef LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H
-#define LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H
-
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-class PtNodeParams;
-
-class DynamicPtGcEventListeners {
- public:
-    // Updates all PtNodes that can be reached from the root. Checks if each PtNode is useless or
-    // not and marks useless PtNodes as deleted. Such deleted PtNodes will be discarded in the GC.
-    // TODO: Concatenate non-terminal PtNodes.
-    class TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-        : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
-                PtNodeWriter *const ptNodeWriter)
-                : mPtNodeWriter(ptNodeWriter), mValueStack(), mChildrenValue(0),
-                  mValidUnigramCount(0) {}
-
-        ~TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted() {};
-
-        bool onAscend() {
-            if (mValueStack.empty()) {
-                return false;
-            }
-            mChildrenValue = mValueStack.back();
-            mValueStack.pop_back();
-            return true;
-        }
-
-        bool onDescend(const int ptNodeArrayPos) {
-            mValueStack.push_back(0);
-            mChildrenValue = 0;
-            return true;
-        }
-
-        bool onReadingPtNodeArrayTail() { return true; }
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-        int getValidUnigramCount() const {
-            return mValidUnigramCount;
-        }
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(
-                TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted);
-
-        PtNodeWriter *const mPtNodeWriter;
-        std::vector<int> mValueStack;
-        int mChildrenValue;
-        int mValidUnigramCount;
-    };
-
-    // Updates all bigram entries that are held by valid PtNodes. This removes useless bigram
-    // entries.
-    class TraversePolicyToUpdateBigramProbability
-            : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToUpdateBigramProbability(PtNodeWriter *const ptNodeWriter)
-                : mPtNodeWriter(ptNodeWriter), mValidBigramEntryCount(0) {}
-
-        bool onAscend() { return true; }
-
-        bool onDescend(const int ptNodeArrayPos) { return true; }
-
-        bool onReadingPtNodeArrayTail() { return true; }
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-        int getValidBigramEntryCount() const {
-            return mValidBigramEntryCount;
-        }
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateBigramProbability);
-
-        PtNodeWriter *const mPtNodeWriter;
-        int mValidBigramEntryCount;
-    };
-
-    class TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-            : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToPlaceAndWriteValidPtNodesToBuffer(
-                PtNodeWriter *const ptNodeWriter, BufferWithExtendableBuffer *const bufferToWrite,
-                PtNodeWriter::DictPositionRelocationMap *const dictPositionRelocationMap)
-                : mPtNodeWriter(ptNodeWriter), mBufferToWrite(bufferToWrite),
-                  mDictPositionRelocationMap(dictPositionRelocationMap), mValidPtNodeCount(0),
-                  mPtNodeArraySizeFieldPos(NOT_A_DICT_POS) {};
-
-        bool onAscend() { return true; }
-
-        bool onDescend(const int ptNodeArrayPos);
-
-        bool onReadingPtNodeArrayTail();
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToPlaceAndWriteValidPtNodesToBuffer);
-
-        PtNodeWriter *const mPtNodeWriter;
-        BufferWithExtendableBuffer *const mBufferToWrite;
-        PtNodeWriter::DictPositionRelocationMap *const mDictPositionRelocationMap;
-        int mValidPtNodeCount;
-        int mPtNodeArraySizeFieldPos;
-    };
-
-    class TraversePolicyToUpdateAllPositionFields
-            : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToUpdateAllPositionFields(PtNodeWriter *const ptNodeWriter,
-                const PtNodeWriter::DictPositionRelocationMap *const dictPositionRelocationMap)
-                : mPtNodeWriter(ptNodeWriter),
-                  mDictPositionRelocationMap(dictPositionRelocationMap), mUnigramCount(0),
-                  mBigramCount(0) {};
-
-        bool onAscend() { return true; }
-
-        bool onDescend(const int ptNodeArrayPos) { return true; }
-
-        bool onReadingPtNodeArrayTail() { return true; }
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-        int getUnigramCount() const {
-            return mUnigramCount;
-        }
-
-        int getBigramCount() const {
-            return mBigramCount;
-        }
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPositionFields);
-
-        PtNodeWriter *const mPtNodeWriter;
-        const PtNodeWriter::DictPositionRelocationMap *const mDictPositionRelocationMap;
-        int mUnigramCount;
-        int mBigramCount;
-    };
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtGcEventListeners);
-};
-} // namespace latinime
-#endif /* LATINIME_DYNAMIC_PT_GC_EVENT_LISTENERS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
deleted file mode 100644
index 086d98b..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.cpp
+++ /dev/null
@@ -1,326 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h"
-#include "utils/char_utils.h"
-
-namespace latinime {
-
-// To avoid infinite loop caused by invalid or malicious forward links.
-const int DynamicPtReadingHelper::MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
-const int DynamicPtReadingHelper::MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP = 100000;
-const size_t DynamicPtReadingHelper::MAX_READING_STATE_STACK_SIZE = MAX_WORD_LENGTH;
-
-bool DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions::onVisitingPtNode(
-        const PtNodeParams *const ptNodeParams) {
-    if (ptNodeParams->isTerminal() && !ptNodeParams->isDeleted()) {
-        mTerminalPositions->push_back(ptNodeParams->getHeadPos());
-    }
-    return true;
-}
-
-// Visits all PtNodes in post-order depth first manner.
-// For example, visits c -> b -> y -> x -> a for the following dictionary:
-// a _ b _ c
-//   \ x _ y
-bool DynamicPtReadingHelper::traverseAllPtNodesInPostorderDepthFirstManner(
-        TraversingEventListener *const listener) {
-    bool alreadyVisitedChildren = false;
-    // Descend from the root to the root PtNode array.
-    if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) {
-        return false;
-    }
-    while (!isEnd()) {
-        const PtNodeParams ptNodeParams(getPtNodeParams());
-        if (!ptNodeParams.isValid()) {
-            break;
-        }
-        if (!alreadyVisitedChildren) {
-            if (ptNodeParams.hasChildren()) {
-                // Move to the first child.
-                if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
-                    return false;
-                }
-                pushReadingStateToStack();
-                readChildNode(ptNodeParams);
-            } else {
-                alreadyVisitedChildren = true;
-            }
-        } else {
-            if (!listener->onVisitingPtNode(&ptNodeParams)) {
-                return false;
-            }
-            readNextSiblingNode(ptNodeParams);
-            if (isEnd()) {
-                // All PtNodes in current linked PtNode arrays have been visited.
-                // Return to the parent.
-                if (!listener->onReadingPtNodeArrayTail()) {
-                    return false;
-                }
-                if (mReadingStateStack.size() <= 0) {
-                    break;
-                }
-                if (!listener->onAscend()) {
-                    return false;
-                }
-                popReadingStateFromStack();
-                alreadyVisitedChildren = true;
-            } else {
-                // Process sibling PtNode.
-                alreadyVisitedChildren = false;
-            }
-        }
-    }
-    // Ascend from the root PtNode array to the root.
-    if (!listener->onAscend()) {
-        return false;
-    }
-    return !isError();
-}
-
-// Visits all PtNodes in PtNode array level pre-order depth first manner, which is the same order
-// that PtNodes are written in the dictionary buffer.
-// For example, visits a -> b -> x -> c -> y for the following dictionary:
-// a _ b _ c
-//   \ x _ y
-bool DynamicPtReadingHelper::traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-        TraversingEventListener *const listener) {
-    bool alreadyVisitedAllPtNodesInArray = false;
-    bool alreadyVisitedChildren = false;
-    // Descend from the root to the root PtNode array.
-    if (!listener->onDescend(getPosOfLastPtNodeArrayHead())) {
-        return false;
-    }
-    if (isEnd()) {
-        // Empty dictionary. Needs to notify the listener of the tail of empty PtNode array.
-        if (!listener->onReadingPtNodeArrayTail()) {
-            return false;
-        }
-    }
-    pushReadingStateToStack();
-    while (!isEnd()) {
-        const PtNodeParams ptNodeParams(getPtNodeParams());
-        if (!ptNodeParams.isValid()) {
-            break;
-        }
-        if (alreadyVisitedAllPtNodesInArray) {
-            if (alreadyVisitedChildren) {
-                // Move to next sibling PtNode's children.
-                readNextSiblingNode(ptNodeParams);
-                if (isEnd()) {
-                    // Return to the parent PTNode.
-                    if (!listener->onAscend()) {
-                        return false;
-                    }
-                    if (mReadingStateStack.size() <= 0) {
-                        break;
-                    }
-                    popReadingStateFromStack();
-                    alreadyVisitedChildren = true;
-                    alreadyVisitedAllPtNodesInArray = true;
-                } else {
-                    alreadyVisitedChildren = false;
-                }
-            } else {
-                if (ptNodeParams.hasChildren()) {
-                    // Move to the first child.
-                    if (!listener->onDescend(ptNodeParams.getChildrenPos())) {
-                        return false;
-                    }
-                    pushReadingStateToStack();
-                    readChildNode(ptNodeParams);
-                    // Push state to return the head of PtNode array.
-                    pushReadingStateToStack();
-                    alreadyVisitedAllPtNodesInArray = false;
-                    alreadyVisitedChildren = false;
-                } else {
-                    alreadyVisitedChildren = true;
-                }
-            }
-        } else {
-            if (!listener->onVisitingPtNode(&ptNodeParams)) {
-                return false;
-            }
-            readNextSiblingNode(ptNodeParams);
-            if (isEnd()) {
-                if (!listener->onReadingPtNodeArrayTail()) {
-                    return false;
-                }
-                // Return to the head of current PtNode array.
-                popReadingStateFromStack();
-                alreadyVisitedAllPtNodesInArray = true;
-            }
-        }
-    }
-    popReadingStateFromStack();
-    // Ascend from the root PtNode array to the root.
-    if (!listener->onAscend()) {
-        return false;
-    }
-    return !isError();
-}
-
-int DynamicPtReadingHelper::getCodePointsAndProbabilityAndReturnCodePointCount(
-        const int maxCodePointCount, int *const outCodePoints, int *const outUnigramProbability) {
-    // This method traverses parent nodes from the terminal by following parent pointers; thus,
-    // node code points are stored in the buffer in the reverse order.
-    int reverseCodePoints[maxCodePointCount];
-    const PtNodeParams terminalPtNodeParams(getPtNodeParams());
-    // First, read the terminal node and get its probability.
-    if (!isValidTerminalNode(terminalPtNodeParams)) {
-        // Node at the ptNodePos is not a valid terminal node.
-        *outUnigramProbability = NOT_A_PROBABILITY;
-        return 0;
-    }
-    // Store terminal node probability.
-    *outUnigramProbability = terminalPtNodeParams.getProbability();
-    // Then, following parent node link to the dictionary root and fetch node code points.
-    int totalCodePointCount = 0;
-    while (!isEnd()) {
-        const PtNodeParams ptNodeParams(getPtNodeParams());
-        totalCodePointCount = getTotalCodePointCount(ptNodeParams);
-        if (!ptNodeParams.isValid() || totalCodePointCount > maxCodePointCount) {
-            // The ptNodePos is not a valid terminal node position in the dictionary.
-            *outUnigramProbability = NOT_A_PROBABILITY;
-            return 0;
-        }
-        // Store node code points to buffer in the reverse order.
-        fetchMergedNodeCodePointsInReverseOrder(ptNodeParams, getPrevTotalCodePointCount(),
-                reverseCodePoints);
-        // Follow parent node toward the root node.
-        readParentNode(ptNodeParams);
-    }
-    if (isError()) {
-        // The node position or the dictionary is invalid.
-        *outUnigramProbability = NOT_A_PROBABILITY;
-        return 0;
-    }
-    // Reverse the stored code points to output them.
-    for (int i = 0; i < totalCodePointCount; ++i) {
-        outCodePoints[i] = reverseCodePoints[totalCodePointCount - i - 1];
-    }
-    return totalCodePointCount;
-}
-
-int DynamicPtReadingHelper::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) {
-    int searchCodePoints[length];
-    for (int i = 0; i < length; ++i) {
-        searchCodePoints[i] = forceLowerCaseSearch ? CharUtils::toLowerCase(inWord[i]) : inWord[i];
-    }
-    while (!isEnd()) {
-        const PtNodeParams ptNodeParams(getPtNodeParams());
-        const int matchedCodePointCount = getPrevTotalCodePointCount();
-        if (getTotalCodePointCount(ptNodeParams) > length
-                || !isMatchedCodePoint(ptNodeParams, 0 /* index */,
-                        searchCodePoints[matchedCodePointCount])) {
-            // Current node has too many code points or its first code point is different from
-            // target code point. Skip this node and read the next sibling node.
-            readNextSiblingNode(ptNodeParams);
-            continue;
-        }
-        // Check following merged node code points.
-        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
-        for (int j = 1; j < nodeCodePointCount; ++j) {
-            if (!isMatchedCodePoint(ptNodeParams, j, searchCodePoints[matchedCodePointCount + j])) {
-                // Different code point is found. The given word is not included in the dictionary.
-                return NOT_A_DICT_POS;
-            }
-        }
-        // All characters are matched.
-        if (length == getTotalCodePointCount(ptNodeParams)) {
-            if (!ptNodeParams.isTerminal()) {
-                return NOT_A_DICT_POS;
-            }
-            // Terminal position is found.
-            return ptNodeParams.getHeadPos();
-        }
-        if (!ptNodeParams.hasChildren()) {
-            return NOT_A_DICT_POS;
-        }
-        // Advance to the children nodes.
-        readChildNode(ptNodeParams);
-    }
-    // If we already traversed the tree further than the word is long, there means
-    // there was no match (or we would have found it).
-    return NOT_A_DICT_POS;
-}
-
-// Read node array size and process empty node arrays. Nodes and arrays are counted up in this
-// method to avoid an infinite loop.
-void DynamicPtReadingHelper::nextPtNodeArray() {
-    int ptNodeCountInArray = 0;
-    int firstPtNodePos = NOT_A_DICT_POS;
-    if (!mPtNodeArrayReader->readPtNodeArrayInfoAndReturnIfValid(
-            mReadingState.mPos, &ptNodeCountInArray, &firstPtNodePos)) {
-        mIsError = true;
-        mReadingState.mPos = NOT_A_DICT_POS;
-        return;
-    }
-    mReadingState.mPosOfThisPtNodeArrayHead = mReadingState.mPos;
-    mReadingState.mRemainingPtNodeCountInThisArray = ptNodeCountInArray;
-    mReadingState.mPos = firstPtNodePos;
-    // Count up nodes and node arrays to avoid infinite loop.
-    mReadingState.mTotalPtNodeIndexInThisArrayChain +=
-            mReadingState.mRemainingPtNodeCountInThisArray;
-    mReadingState.mPtNodeArrayIndexInThisArrayChain++;
-    if (mReadingState.mRemainingPtNodeCountInThisArray < 0
-            || mReadingState.mTotalPtNodeIndexInThisArrayChain
-                    > MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP
-            || mReadingState.mPtNodeArrayIndexInThisArrayChain
-                    > MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP) {
-        // Invalid dictionary.
-        AKLOGI("Invalid dictionary. nodeCount: %d, totalNodeCount: %d, MAX_CHILD_COUNT: %d"
-                "nodeArrayCount: %d, MAX_NODE_ARRAY_COUNT: %d",
-                mReadingState.mRemainingPtNodeCountInThisArray,
-                mReadingState.mTotalPtNodeIndexInThisArrayChain,
-                MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP,
-                mReadingState.mPtNodeArrayIndexInThisArrayChain,
-                MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP);
-        ASSERT(false);
-        mIsError = true;
-        mReadingState.mPos = NOT_A_DICT_POS;
-        return;
-    }
-    if (mReadingState.mRemainingPtNodeCountInThisArray == 0) {
-        // Empty node array. Try following forward link.
-        followForwardLink();
-    }
-}
-
-// Follow the forward link and read the next node array if exists.
-void DynamicPtReadingHelper::followForwardLink() {
-    int nextPtNodeArrayPos = NOT_A_DICT_POS;
-    if (!mPtNodeArrayReader->readForwardLinkAndReturnIfValid(
-            mReadingState.mPos, &nextPtNodeArrayPos)) {
-        mIsError = true;
-        mReadingState.mPos = NOT_A_DICT_POS;
-        return;
-    }
-    mReadingState.mPosOfLastForwardLinkField = mReadingState.mPos;
-    if (nextPtNodeArrayPos != NOT_A_DICT_POS) {
-        // Follow the forward link.
-        mReadingState.mPos = nextPtNodeArrayPos;
-        nextPtNodeArray();
-    } else {
-        // All node arrays have been read.
-        mReadingState.mPos = NOT_A_DICT_POS;
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
deleted file mode 100644
index b726258..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h
+++ /dev/null
@@ -1,283 +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.
- */
-
-#ifndef LATINIME_DYNAMIC_PT_READING_HELPER_H
-#define LATINIME_DYNAMIC_PT_READING_HELPER_H
-
-#include <cstddef>
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
-
-namespace latinime {
-
-class DictionaryShortcutsStructurePolicy;
-class PtNodeArrayReader;
-
-/*
- * This class is used for traversing dynamic patricia trie. This class supports iterating nodes and
- * dealing with additional buffer. This class counts nodes and node arrays to avoid infinite loop.
- */
-class DynamicPtReadingHelper {
- public:
-    class TraversingEventListener {
-     public:
-        virtual ~TraversingEventListener() {};
-
-        // Returns whether the event handling was succeeded or not.
-        virtual bool onAscend() = 0;
-
-        // Returns whether the event handling was succeeded or not.
-        virtual bool onDescend(const int ptNodeArrayPos) = 0;
-
-        // Returns whether the event handling was succeeded or not.
-        virtual bool onReadingPtNodeArrayTail() = 0;
-
-        // Returns whether the event handling was succeeded or not.
-        virtual bool onVisitingPtNode(const PtNodeParams *const node) = 0;
-
-     protected:
-        TraversingEventListener() {};
-
-     private:
-        DISALLOW_COPY_AND_ASSIGN(TraversingEventListener);
-    };
-
-    class TraversePolicyToGetAllTerminalPtNodePositions : public TraversingEventListener {
-     public:
-        TraversePolicyToGetAllTerminalPtNodePositions(std::vector<int> *const terminalPositions)
-                : mTerminalPositions(terminalPositions) {}
-        bool onAscend() { return true; }
-        bool onDescend(const int ptNodeArrayPos) { return true; }
-        bool onReadingPtNodeArrayTail() { return true; }
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToGetAllTerminalPtNodePositions);
-
-        std::vector<int> *const mTerminalPositions;
-    };
-
-    DynamicPtReadingHelper(const PtNodeReader *const ptNodeReader,
-            const PtNodeArrayReader *const ptNodeArrayReader)
-            : mIsError(false), mReadingState(), mPtNodeReader(ptNodeReader),
-              mPtNodeArrayReader(ptNodeArrayReader), mReadingStateStack() {}
-
-    ~DynamicPtReadingHelper() {}
-
-    AK_FORCE_INLINE bool isError() const {
-        return mIsError;
-    }
-
-    AK_FORCE_INLINE bool isEnd() const {
-        return mReadingState.mPos == NOT_A_DICT_POS;
-    }
-
-    // Initialize reading state with the head position of a PtNode array.
-    AK_FORCE_INLINE void initWithPtNodeArrayPos(const int ptNodeArrayPos) {
-        if (ptNodeArrayPos == NOT_A_DICT_POS) {
-            mReadingState.mPos = NOT_A_DICT_POS;
-        } else {
-            mIsError = false;
-            mReadingState.mPos = ptNodeArrayPos;
-            mReadingState.mTotalCodePointCountSinceInitialization = 0;
-            mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
-            mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
-            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
-            mReadingStateStack.clear();
-            nextPtNodeArray();
-        }
-    }
-
-    // Initialize reading state with the head position of a node.
-    AK_FORCE_INLINE void initWithPtNodePos(const int ptNodePos) {
-        if (ptNodePos == NOT_A_DICT_POS) {
-            mReadingState.mPos = NOT_A_DICT_POS;
-        } else {
-            mIsError = false;
-            mReadingState.mPos = ptNodePos;
-            mReadingState.mRemainingPtNodeCountInThisArray = 1;
-            mReadingState.mTotalCodePointCountSinceInitialization = 0;
-            mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
-            mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
-            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
-            mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
-            mReadingStateStack.clear();
-        }
-    }
-
-    AK_FORCE_INLINE const PtNodeParams getPtNodeParams() const {
-        if (isEnd()) {
-            return PtNodeParams();
-        }
-        return mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(mReadingState.mPos);
-    }
-
-    AK_FORCE_INLINE bool isValidTerminalNode(const PtNodeParams &ptNodeParams) const {
-        return !isEnd() && !ptNodeParams.isDeleted() && ptNodeParams.isTerminal();
-    }
-
-    AK_FORCE_INLINE bool isMatchedCodePoint(const PtNodeParams &ptNodeParams, const int index,
-            const int codePoint) const {
-        return ptNodeParams.getCodePoints()[index] == codePoint;
-    }
-
-    // Return code point count exclude the last read node's code points.
-    AK_FORCE_INLINE int getPrevTotalCodePointCount() const {
-        return mReadingState.mTotalCodePointCountSinceInitialization;
-    }
-
-    // Return code point count include the last read node's code points.
-    AK_FORCE_INLINE int getTotalCodePointCount(const PtNodeParams &ptNodeParams) const {
-        return mReadingState.mTotalCodePointCountSinceInitialization
-                + ptNodeParams.getCodePointCount();
-    }
-
-    AK_FORCE_INLINE void fetchMergedNodeCodePointsInReverseOrder(const PtNodeParams &ptNodeParams,
-            const int index, int *const outCodePoints) const {
-        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
-        const int *const nodeCodePoints = ptNodeParams.getCodePoints();
-        for (int i =  0; i < nodeCodePointCount; ++i) {
-            outCodePoints[index + i] = nodeCodePoints[nodeCodePointCount - 1 - i];
-        }
-    }
-
-    AK_FORCE_INLINE void readNextSiblingNode(const PtNodeParams &ptNodeParams) {
-        mReadingState.mRemainingPtNodeCountInThisArray -= 1;
-        mReadingState.mPos = ptNodeParams.getSiblingNodePos();
-        if (mReadingState.mRemainingPtNodeCountInThisArray <= 0) {
-            // All nodes in the current node array have been read.
-            followForwardLink();
-        }
-    }
-
-    // Read the first child node of the current node.
-    AK_FORCE_INLINE void readChildNode(const PtNodeParams &ptNodeParams) {
-        if (ptNodeParams.hasChildren()) {
-            mReadingState.mTotalCodePointCountSinceInitialization +=
-                    ptNodeParams.getCodePointCount();
-            mReadingState.mTotalPtNodeIndexInThisArrayChain = 0;
-            mReadingState.mPtNodeArrayIndexInThisArrayChain = 0;
-            mReadingState.mPos = ptNodeParams.getChildrenPos();
-            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
-            // Read children node array.
-            nextPtNodeArray();
-        } else {
-            mReadingState.mPos = NOT_A_DICT_POS;
-        }
-    }
-
-    // Read the parent node of the current node.
-    AK_FORCE_INLINE void readParentNode(const PtNodeParams &ptNodeParams) {
-        if (ptNodeParams.getParentPos() != NOT_A_DICT_POS) {
-            mReadingState.mTotalCodePointCountSinceInitialization +=
-                    ptNodeParams.getCodePointCount();
-            mReadingState.mTotalPtNodeIndexInThisArrayChain = 1;
-            mReadingState.mPtNodeArrayIndexInThisArrayChain = 1;
-            mReadingState.mRemainingPtNodeCountInThisArray = 1;
-            mReadingState.mPos = ptNodeParams.getParentPos();
-            mReadingState.mPosOfLastForwardLinkField = NOT_A_DICT_POS;
-            mReadingState.mPosOfThisPtNodeArrayHead = NOT_A_DICT_POS;
-        } else {
-            mReadingState.mPos = NOT_A_DICT_POS;
-        }
-    }
-
-    AK_FORCE_INLINE int getPosOfLastForwardLinkField() const {
-        return mReadingState.mPosOfLastForwardLinkField;
-    }
-
-    AK_FORCE_INLINE int getPosOfLastPtNodeArrayHead() const {
-        return mReadingState.mPosOfThisPtNodeArrayHead;
-    }
-
-    bool traverseAllPtNodesInPostorderDepthFirstManner(TraversingEventListener *const listener);
-
-    bool traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-            TraversingEventListener *const listener);
-
-    int getCodePointsAndProbabilityAndReturnCodePointCount(const int maxCodePointCount,
-            int *const outCodePoints, int *const outUnigramProbability);
-
-    int getTerminalPtNodePositionOfWord(const int *const inWord, const int length,
-            const bool forceLowerCaseSearch);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(DynamicPtReadingHelper);
-
-    // This class encapsulates the reading state of a position in the dictionary. It points at a
-    // specific PtNode in the dictionary.
-    class PtNodeReadingState {
-     public:
-        // Note that copy constructor and assignment operator are used for this class to use
-        // std::vector.
-        PtNodeReadingState() : mPos(NOT_A_DICT_POS), mRemainingPtNodeCountInThisArray(0),
-                mTotalCodePointCountSinceInitialization(0), mTotalPtNodeIndexInThisArrayChain(0),
-                mPtNodeArrayIndexInThisArrayChain(0), mPosOfLastForwardLinkField(NOT_A_DICT_POS),
-                mPosOfThisPtNodeArrayHead(NOT_A_DICT_POS) {}
-
-        int mPos;
-        // Remaining node count in the current array.
-        int mRemainingPtNodeCountInThisArray;
-        int mTotalCodePointCountSinceInitialization;
-        // Counter of PtNodes used to avoid infinite loops caused by broken or malicious links.
-        int mTotalPtNodeIndexInThisArrayChain;
-        // Counter of PtNode arrays used to avoid infinite loops caused by cyclic links of empty
-        // PtNode arrays.
-        int mPtNodeArrayIndexInThisArrayChain;
-        int mPosOfLastForwardLinkField;
-        int mPosOfThisPtNodeArrayHead;
-    };
-
-    static const int MAX_CHILD_COUNT_TO_AVOID_INFINITE_LOOP;
-    static const int MAX_PT_NODE_ARRAY_COUNT_TO_AVOID_INFINITE_LOOP;
-    static const size_t MAX_READING_STATE_STACK_SIZE;
-
-    // TODO: Introduce error code to track what caused the error.
-    bool mIsError;
-    PtNodeReadingState mReadingState;
-    const PtNodeReader *const mPtNodeReader;
-    const PtNodeArrayReader *const mPtNodeArrayReader;
-    std::vector<PtNodeReadingState> mReadingStateStack;
-
-    void nextPtNodeArray();
-
-    void followForwardLink();
-
-    AK_FORCE_INLINE void pushReadingStateToStack() {
-        if (mReadingStateStack.size() > MAX_READING_STATE_STACK_SIZE) {
-            AKLOGI("Reading state stack overflow. Max size: %zd", MAX_READING_STATE_STACK_SIZE);
-            ASSERT(false);
-            mIsError = true;
-            mReadingState.mPos = NOT_A_DICT_POS;
-        } else {
-            mReadingStateStack.push_back(mReadingState);
-        }
-    }
-
-    AK_FORCE_INLINE void popReadingStateFromStack() {
-        if (mReadingStateStack.empty()) {
-            mReadingState.mPos = NOT_A_DICT_POS;
-        } else {
-            mReadingState = mReadingStateStack.back();
-            mReadingStateStack.pop_back();
-        }
-    }
-};
-} // namespace latinime
-#endif /* LATINIME_DYNAMIC_PT_READING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp
deleted file mode 100644
index 3586b50..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.cpp
+++ /dev/null
@@ -1,72 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::MASK_MOVED = 0xC0;
-const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_NOT_MOVED = 0xC0;
-const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_MOVED = 0x40;
-const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_IS_DELETED = 0x80;
-const DynamicPtReadingUtils::NodeFlags DynamicPtReadingUtils::FLAG_WILL_BECOME_NON_TERMINAL = 0x00;
-
-// TODO: Make DICT_OFFSET_ZERO_OFFSET = 0.
-// Currently, DICT_OFFSET_INVALID is 0 in Java side but offset can be 0 during GC. So, the maximum
-// value of offsets, which is 0x7FFFFF is used to represent 0 offset.
-const int DynamicPtReadingUtils::DICT_OFFSET_INVALID = 0;
-const int DynamicPtReadingUtils::DICT_OFFSET_ZERO_OFFSET = 0x7FFFFF;
-
-/* static */ int DynamicPtReadingUtils::getForwardLinkPosition(const uint8_t *const buffer,
-        const int pos) {
-    int linkAddressPos = pos;
-    return ByteArrayUtils::readSint24AndAdvancePosition(buffer, &linkAddressPos);
-}
-
-/* static */ int DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
-        const uint8_t *const buffer, int *const pos) {
-    return ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
-}
-
-/* static */ int DynamicPtReadingUtils::getParentPtNodePos(const int parentOffset,
-        const int ptNodePos) {
-    if (parentOffset == DICT_OFFSET_INVALID) {
-        return NOT_A_DICT_POS;
-    } else if (parentOffset == DICT_OFFSET_ZERO_OFFSET) {
-        return ptNodePos;
-    } else {
-        return parentOffset + ptNodePos;
-    }
-}
-
-/* static */ int DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
-        const uint8_t *const buffer, int *const pos) {
-    const int base = *pos;
-    const int offset = ByteArrayUtils::readSint24AndAdvancePosition(buffer, pos);
-    if (offset == DICT_OFFSET_INVALID) {
-        // The PtNode does not have children.
-        return NOT_A_DICT_POS;
-    } else if (offset == DICT_OFFSET_ZERO_OFFSET) {
-        return base;
-    } else {
-        return base + offset;
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
deleted file mode 100644
index 3c62e2e..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.cpp
+++ /dev/null
@@ -1,307 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
-
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const int DynamicPtUpdatingHelper::CHILDREN_POSITION_FIELD_SIZE = 3;
-
-bool DynamicPtUpdatingHelper::addUnigramWord(
-        DynamicPtReadingHelper *const readingHelper,
-        const int *const wordCodePoints, const int codePointCount,
-        const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram) {
-    int parentPos = NOT_A_DICT_POS;
-    while (!readingHelper->isEnd()) {
-        const PtNodeParams ptNodeParams(readingHelper->getPtNodeParams());
-        if (!ptNodeParams.isValid()) {
-            break;
-        }
-        const int matchedCodePointCount = readingHelper->getPrevTotalCodePointCount();
-        if (!readingHelper->isMatchedCodePoint(ptNodeParams, 0 /* index */,
-                wordCodePoints[matchedCodePointCount])) {
-            // The first code point is different from target code point. Skip this node and read
-            // the next sibling node.
-            readingHelper->readNextSiblingNode(ptNodeParams);
-            continue;
-        }
-        // Check following merged node code points.
-        const int nodeCodePointCount = ptNodeParams.getCodePointCount();
-        for (int j = 1; j < nodeCodePointCount; ++j) {
-            const int nextIndex = matchedCodePointCount + j;
-            if (nextIndex >= codePointCount || !readingHelper->isMatchedCodePoint(ptNodeParams, j,
-                    wordCodePoints[matchedCodePointCount + j])) {
-                *outAddedNewUnigram = true;
-                return reallocatePtNodeAndAddNewPtNodes(&ptNodeParams, j, unigramProperty,
-                        wordCodePoints + matchedCodePointCount,
-                        codePointCount - matchedCodePointCount);
-            }
-        }
-        // All characters are matched.
-        if (codePointCount == readingHelper->getTotalCodePointCount(ptNodeParams)) {
-            return setPtNodeProbability(&ptNodeParams, unigramProperty, outAddedNewUnigram);
-        }
-        if (!ptNodeParams.hasChildren()) {
-            *outAddedNewUnigram = true;
-            return createChildrenPtNodeArrayAndAChildPtNode(&ptNodeParams, unigramProperty,
-                    wordCodePoints + readingHelper->getTotalCodePointCount(ptNodeParams),
-                    codePointCount - readingHelper->getTotalCodePointCount(ptNodeParams));
-        }
-        // Advance to the children nodes.
-        parentPos = ptNodeParams.getHeadPos();
-        readingHelper->readChildNode(ptNodeParams);
-    }
-    if (readingHelper->isError()) {
-        // The dictionary is invalid.
-        return false;
-    }
-    int pos = readingHelper->getPosOfLastForwardLinkField();
-    *outAddedNewUnigram = true;
-    return createAndInsertNodeIntoPtNodeArray(parentPos,
-            wordCodePoints + readingHelper->getPrevTotalCodePointCount(),
-            codePointCount - readingHelper->getPrevTotalCodePointCount(),
-            unigramProperty, &pos);
-}
-
-bool DynamicPtUpdatingHelper::addNgramEntry(const PtNodePosArrayView prevWordsPtNodePos,
-        const int wordPos, const BigramProperty *const bigramProperty,
-        bool *const outAddedNewEntry) {
-    if (prevWordsPtNodePos.empty()) {
-        return false;
-    }
-    ASSERT(prevWordsPtNodePos.size() <= MAX_PREV_WORD_COUNT_FOR_N_GRAM);
-    int prevWordTerminalIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
-        prevWordTerminalIds[i] = mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(
-                prevWordsPtNodePos[i]).getTerminalId();
-    }
-    const WordIdArrayView prevWordIds(prevWordTerminalIds, prevWordsPtNodePos.size());
-    const int wordId =
-            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos).getTerminalId();
-    return mPtNodeWriter->addNgramEntry(prevWordIds, wordId, bigramProperty, outAddedNewEntry);
-}
-
-bool DynamicPtUpdatingHelper::removeNgramEntry(const PtNodePosArrayView prevWordsPtNodePos,
-        const int wordPos) {
-    if (prevWordsPtNodePos.empty()) {
-        return false;
-    }
-    ASSERT(prevWordsPtNodePos.size() <= MAX_PREV_WORD_COUNT_FOR_N_GRAM);
-    int prevWordTerminalIds[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    for (size_t i = 0; i < prevWordsPtNodePos.size(); ++i) {
-        prevWordTerminalIds[i] = mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(
-                prevWordsPtNodePos[i]).getTerminalId();
-    }
-    const WordIdArrayView prevWordIds(prevWordTerminalIds, prevWordsPtNodePos.size());
-    const int wordId =
-            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos).getTerminalId();
-    return mPtNodeWriter->removeNgramEntry(prevWordIds, wordId);
-}
-
-bool DynamicPtUpdatingHelper::addShortcutTarget(const int wordPos,
-        const int *const targetCodePoints, const int targetCodePointCount,
-        const int shortcutProbability) {
-    const PtNodeParams ptNodeParams(mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(wordPos));
-    return mPtNodeWriter->addShortcutTarget(&ptNodeParams, targetCodePoints, targetCodePointCount,
-            shortcutProbability);
-}
-
-bool DynamicPtUpdatingHelper::createAndInsertNodeIntoPtNodeArray(const int parentPos,
-        const int *const nodeCodePoints, const int nodeCodePointCount,
-        const UnigramProperty *const unigramProperty, int *const forwardLinkFieldPos) {
-    const int newPtNodeArrayPos = mBuffer->getTailPosition();
-    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
-            newPtNodeArrayPos, forwardLinkFieldPos)) {
-        return false;
-    }
-    return createNewPtNodeArrayWithAChildPtNode(parentPos, nodeCodePoints, nodeCodePointCount,
-            unigramProperty);
-}
-
-bool DynamicPtUpdatingHelper::setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
-        const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram) {
-    if (originalPtNodeParams->isTerminal() && !originalPtNodeParams->isDeleted()) {
-        // Overwrites the probability.
-        *outAddedNewUnigram = false;
-        return mPtNodeWriter->updatePtNodeUnigramProperty(originalPtNodeParams, unigramProperty);
-    } else {
-        // Make the node terminal and write the probability.
-        *outAddedNewUnigram = true;
-        const int movedPos = mBuffer->getTailPosition();
-        int writingPos = movedPos;
-        const PtNodeParams ptNodeParamsToWrite(getUpdatedPtNodeParams(originalPtNodeParams,
-                unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
-                true /* isTerminal */, originalPtNodeParams->getParentPos(),
-                originalPtNodeParams->getCodePointCount(), originalPtNodeParams->getCodePoints(),
-                unigramProperty->getProbability()));
-        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
-                unigramProperty, &writingPos)) {
-            return false;
-        }
-        if (!mPtNodeWriter->markPtNodeAsMoved(originalPtNodeParams, movedPos, movedPos)) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool DynamicPtUpdatingHelper::createChildrenPtNodeArrayAndAChildPtNode(
-        const PtNodeParams *const parentPtNodeParams, const UnigramProperty *const unigramProperty,
-        const int *const codePoints, const int codePointCount) {
-    const int newPtNodeArrayPos = mBuffer->getTailPosition();
-    if (!mPtNodeWriter->updateChildrenPosition(parentPtNodeParams, newPtNodeArrayPos)) {
-        return false;
-    }
-    return createNewPtNodeArrayWithAChildPtNode(parentPtNodeParams->getHeadPos(), codePoints,
-            codePointCount, unigramProperty);
-}
-
-bool DynamicPtUpdatingHelper::createNewPtNodeArrayWithAChildPtNode(
-        const int parentPtNodePos, const int *const nodeCodePoints, const int nodeCodePointCount,
-        const UnigramProperty *const unigramProperty) {
-    int writingPos = mBuffer->getTailPosition();
-    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer,
-            1 /* arraySize */, &writingPos)) {
-        return false;
-    }
-    const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
-            unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(), true /* isTerminal */,
-            parentPtNodePos, nodeCodePointCount, nodeCodePoints,
-            unigramProperty->getProbability()));
-    if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
-            unigramProperty, &writingPos)) {
-        return false;
-    }
-    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
-            NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
-        return false;
-    }
-    return true;
-}
-
-// Returns whether the dictionary updating was succeeded or not.
-bool DynamicPtUpdatingHelper::reallocatePtNodeAndAddNewPtNodes(
-        const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
-        const UnigramProperty *const unigramProperty, const int *const newNodeCodePoints,
-        const int newNodeCodePointCount) {
-    // When addsExtraChild is true, split the reallocating PtNode and add new child.
-    // Reallocating PtNode: abcde, newNode: abcxy.
-    // abc (1st, not terminal) __ de (2nd)
-    //                         \_ xy (extra child, terminal)
-    // Otherwise, this method makes 1st part terminal and write information in unigramProperty.
-    // Reallocating PtNode: abcde, newNode: abc.
-    // abc (1st, terminal) __ de (2nd)
-    const bool addsExtraChild = newNodeCodePointCount > overlappingCodePointCount;
-    const int firstPartOfReallocatedPtNodePos = mBuffer->getTailPosition();
-    int writingPos = firstPartOfReallocatedPtNodePos;
-    // Write the 1st part of the reallocating node. The children position will be updated later
-    // with actual children position.
-    if (addsExtraChild) {
-        const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
-                false /* isNotAWord */, false /* isBlacklisted */, false /* isTerminal */,
-                reallocatingPtNodeParams->getParentPos(), overlappingCodePointCount,
-                reallocatingPtNodeParams->getCodePoints(), NOT_A_PROBABILITY));
-        if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&ptNodeParamsToWrite, &writingPos)) {
-            return false;
-        }
-    } else {
-        const PtNodeParams ptNodeParamsToWrite(getPtNodeParamsForNewPtNode(
-                unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
-                true /* isTerminal */, reallocatingPtNodeParams->getParentPos(),
-                overlappingCodePointCount, reallocatingPtNodeParams->getCodePoints(),
-                unigramProperty->getProbability()));
-        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&ptNodeParamsToWrite,
-                unigramProperty, &writingPos)) {
-            return false;
-        }
-    }
-    const int actualChildrenPos = writingPos;
-    // Create new children PtNode array.
-    const size_t newPtNodeCount = addsExtraChild ? 2 : 1;
-    if (!DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(mBuffer,
-            newPtNodeCount, &writingPos)) {
-        return false;
-    }
-    // Write the 2nd part of the reallocating node.
-    const int secondPartOfReallocatedPtNodePos = writingPos;
-    const PtNodeParams childPartPtNodeParams(getUpdatedPtNodeParams(reallocatingPtNodeParams,
-            reallocatingPtNodeParams->isNotAWord(), reallocatingPtNodeParams->isBlacklisted(),
-            reallocatingPtNodeParams->isTerminal(), firstPartOfReallocatedPtNodePos,
-            reallocatingPtNodeParams->getCodePointCount() - overlappingCodePointCount,
-            reallocatingPtNodeParams->getCodePoints() + overlappingCodePointCount,
-            reallocatingPtNodeParams->getProbability()));
-    if (!mPtNodeWriter->writePtNodeAndAdvancePosition(&childPartPtNodeParams, &writingPos)) {
-        return false;
-    }
-    if (addsExtraChild) {
-        const PtNodeParams extraChildPtNodeParams(getPtNodeParamsForNewPtNode(
-                unigramProperty->isNotAWord(), unigramProperty->isBlacklisted(),
-                true /* isTerminal */, firstPartOfReallocatedPtNodePos,
-                newNodeCodePointCount - overlappingCodePointCount,
-                newNodeCodePoints + overlappingCodePointCount, unigramProperty->getProbability()));
-        if (!mPtNodeWriter->writeNewTerminalPtNodeAndAdvancePosition(&extraChildPtNodeParams,
-                unigramProperty, &writingPos)) {
-            return false;
-        }
-    }
-    if (!DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(mBuffer,
-            NOT_A_DICT_POS /* forwardLinkPos */, &writingPos)) {
-        return false;
-    }
-    // Update original reallocating PtNode as moved.
-    if (!mPtNodeWriter->markPtNodeAsMoved(reallocatingPtNodeParams, firstPartOfReallocatedPtNodePos,
-            secondPartOfReallocatedPtNodePos)) {
-        return false;
-    }
-    // Load node info. Information of the 1st part will be fetched.
-    const PtNodeParams ptNodeParams(
-            mPtNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(firstPartOfReallocatedPtNodePos));
-    // Update children position.
-    return mPtNodeWriter->updateChildrenPosition(&ptNodeParams, actualChildrenPos);
-}
-
-const PtNodeParams DynamicPtUpdatingHelper::getUpdatedPtNodeParams(
-        const PtNodeParams *const originalPtNodeParams,
-        const bool isNotAWord, const bool isBlacklisted, const bool isTerminal, const int parentPos,
-        const int codePointCount, const int *const codePoints, const int probability) const {
-    const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
-            isBlacklisted, isNotAWord, isTerminal, false /* hasShortcutTargets */,
-            false /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */,
-            CHILDREN_POSITION_FIELD_SIZE);
-    return PtNodeParams(originalPtNodeParams, flags, parentPos, codePointCount, codePoints,
-            probability);
-}
-
-const PtNodeParams DynamicPtUpdatingHelper::getPtNodeParamsForNewPtNode(
-        const bool isNotAWord, const bool isBlacklisted, const bool isTerminal,
-        const int parentPos, const int codePointCount, const int *const codePoints,
-        const int probability) const {
-    const PatriciaTrieReadingUtils::NodeFlags flags = PatriciaTrieReadingUtils::createAndGetFlags(
-            isBlacklisted, isNotAWord, isTerminal, false /* hasShortcutTargets */,
-            false /* hasBigrams */, codePointCount > 1 /* hasMultipleChars */,
-            CHILDREN_POSITION_FIELD_SIZE);
-    return PtNodeParams(flags, parentPos, codePointCount, codePoints, probability);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
deleted file mode 100644
index 97c05c1..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h
+++ /dev/null
@@ -1,95 +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.
- */
-
-#ifndef LATINIME_DYNAMIC_PT_UPDATING_HELPER_H
-#define LATINIME_DYNAMIC_PT_UPDATING_HELPER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "utils/int_array_view.h"
-
-namespace latinime {
-
-class BigramProperty;
-class BufferWithExtendableBuffer;
-class DynamicPtReadingHelper;
-class PtNodeReader;
-class PtNodeWriter;
-class UnigramProperty;
-
-class DynamicPtUpdatingHelper {
- public:
-    DynamicPtUpdatingHelper(BufferWithExtendableBuffer *const buffer,
-            const PtNodeReader *const ptNodeReader, PtNodeWriter *const ptNodeWriter)
-            : mBuffer(buffer), mPtNodeReader(ptNodeReader), mPtNodeWriter(ptNodeWriter) {}
-
-    ~DynamicPtUpdatingHelper() {}
-
-    // Add a word to the dictionary. If the word already exists, update the probability.
-    bool addUnigramWord(DynamicPtReadingHelper *const readingHelper,
-            const int *const wordCodePoints, const int codePointCount,
-            const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
-
-    // Add an n-gram entry.
-    bool addNgramEntry(const PtNodePosArrayView prevWordsPtNodePos, const int wordPos,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    // Remove an n-gram entry.
-    bool removeNgramEntry(const PtNodePosArrayView prevWordsPtNodePos, const int wordPos);
-
-    // Add a shortcut target.
-    bool addShortcutTarget(const int wordPos, const int *const targetCodePoints,
-            const int targetCodePointCount, const int shortcutProbability);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtUpdatingHelper);
-
-    static const int CHILDREN_POSITION_FIELD_SIZE;
-
-    BufferWithExtendableBuffer *const mBuffer;
-    const PtNodeReader *const mPtNodeReader;
-    PtNodeWriter *const mPtNodeWriter;
-
-    bool createAndInsertNodeIntoPtNodeArray(const int parentPos, const int *const nodeCodePoints,
-            const int nodeCodePointCount, const UnigramProperty *const unigramProperty,
-            int *const forwardLinkFieldPos);
-
-    bool setPtNodeProbability(const PtNodeParams *const originalPtNodeParams,
-            const UnigramProperty *const unigramProperty, bool *const outAddedNewUnigram);
-
-    bool createChildrenPtNodeArrayAndAChildPtNode(const PtNodeParams *const parentPtNodeParams,
-            const UnigramProperty *const unigramProperty, const int *const codePoints,
-            const int codePointCount);
-
-    bool createNewPtNodeArrayWithAChildPtNode(const int parentPos, const int *const nodeCodePoints,
-            const int nodeCodePointCount, const UnigramProperty *const unigramProperty);
-
-    bool reallocatePtNodeAndAddNewPtNodes(
-            const PtNodeParams *const reallocatingPtNodeParams, const int overlappingCodePointCount,
-            const UnigramProperty *const unigramProperty, const int *const newNodeCodePoints,
-            const int newNodeCodePointCount);
-
-    const PtNodeParams getUpdatedPtNodeParams(const PtNodeParams *const originalPtNodeParams,
-            const bool isNotAWord, const bool isBlacklisted, const bool isTerminal,
-            const int parentPos, const int codePointCount,
-            const int *const codePoints, const int probability) const;
-
-    const PtNodeParams getPtNodeParamsForNewPtNode(const bool isNotAWord, const bool isBlacklisted,
-            const bool isTerminal, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability) const;
-};
-} // namespace latinime
-#endif /* LATINIME_DYNAMIC_PATRICIA_TRIE_UPDATING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp
deleted file mode 100644
index 664aeeb..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.cpp
+++ /dev/null
@@ -1,132 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const size_t DynamicPtWritingUtils::MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD = 0x7F;
-const size_t DynamicPtWritingUtils::MAX_PTNODE_ARRAY_SIZE = 0x7FFF;
-const int DynamicPtWritingUtils::SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE = 1;
-const int DynamicPtWritingUtils::LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE = 2;
-const int DynamicPtWritingUtils::LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG = 0x8000;
-const int DynamicPtWritingUtils::DICT_OFFSET_FIELD_SIZE = 3;
-const int DynamicPtWritingUtils::MAX_DICT_OFFSET_VALUE = 0x7FFFFF;
-const int DynamicPtWritingUtils::MIN_DICT_OFFSET_VALUE = -0x7FFFFF;
-const int DynamicPtWritingUtils::DICT_OFFSET_NEGATIVE_FLAG = 0x800000;
-const int DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE = 1;
-
-/* static */ bool DynamicPtWritingUtils::writeEmptyDictionary(
-        BufferWithExtendableBuffer *const buffer, const int rootPos) {
-    int writingPos = rootPos;
-    if (!writePtNodeArraySizeAndAdvancePosition(buffer, 0 /* arraySize */, &writingPos)) {
-        return false;
-    }
-    return writeForwardLinkPositionAndAdvancePosition(buffer, NOT_A_DICT_POS /* forwardLinkPos */,
-            &writingPos);
-}
-
-/* static */ bool DynamicPtWritingUtils::writeForwardLinkPositionAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
-        int *const forwardLinkFieldPos) {
-    return writeDictOffset(buffer, forwardLinkPos, (*forwardLinkFieldPos), forwardLinkFieldPos);
-}
-
-/* static */ bool DynamicPtWritingUtils::writePtNodeArraySizeAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer, const size_t arraySize,
-        int *const arraySizeFieldPos) {
-    // Currently, all array size field to be created has LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE to
-    // simplify updating process.
-    // TODO: Use SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE for small arrays.
-    /*if (arraySize <= MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD) {
-        return buffer->writeUintAndAdvancePosition(arraySize, SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE,
-                arraySizeFieldPos);
-    } else */
-    if (arraySize <= MAX_PTNODE_ARRAY_SIZE) {
-        uint32_t data = arraySize | LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG;
-        return buffer->writeUintAndAdvancePosition(data, LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE,
-                arraySizeFieldPos);
-    } else {
-        AKLOGI("PtNode array size cannot be written because arraySize is too large: %zd",
-                arraySize);
-        ASSERT(false);
-        return false;
-    }
-}
-
-/* static */ bool DynamicPtWritingUtils::writeFlagsAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer,
-        const DynamicPtReadingUtils::NodeFlags nodeFlags, int *const nodeFlagsFieldPos) {
-    return buffer->writeUintAndAdvancePosition(nodeFlags, NODE_FLAG_FIELD_SIZE, nodeFlagsFieldPos);
-}
-
-// Note that parentOffset is offset from node's head position.
-/* static */ bool DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer, const int parentPos, const int basePos,
-        int *const parentPosFieldPos) {
-    return writeDictOffset(buffer, parentPos, basePos, parentPosFieldPos);
-}
-
-/* static */ bool DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer, const int *const codePoints,
-        const int codePointCount, int *const codePointFieldPos) {
-    if (codePointCount <= 0) {
-        AKLOGI("code points cannot be written because codePointCount is invalid: %d",
-                codePointCount);
-        ASSERT(false);
-        return false;
-    }
-    const bool hasMultipleCodePoints = codePointCount > 1;
-    return buffer->writeCodePointsAndAdvancePosition(codePoints, codePointCount,
-            hasMultipleCodePoints, codePointFieldPos);
-}
-
-/* static */ bool DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(
-        BufferWithExtendableBuffer *const buffer, const int childrenPosition,
-        int *const childrenPositionFieldPos) {
-    return writeDictOffset(buffer, childrenPosition, (*childrenPositionFieldPos),
-            childrenPositionFieldPos);
-}
-
-/* static */ bool DynamicPtWritingUtils::writeDictOffset(BufferWithExtendableBuffer *const buffer,
-        const int targetPos, const int basePos, int *const offsetFieldPos) {
-    int offset = targetPos - basePos;
-    if (targetPos == NOT_A_DICT_POS) {
-        offset = DynamicPtReadingUtils::DICT_OFFSET_INVALID;
-    } else if (offset == 0) {
-        offset = DynamicPtReadingUtils::DICT_OFFSET_ZERO_OFFSET;
-    }
-    if (offset > MAX_DICT_OFFSET_VALUE || offset < MIN_DICT_OFFSET_VALUE) {
-        AKLOGI("offset cannot be written because the offset is too large or too small: %d",
-                offset);
-        ASSERT(false);
-        return false;
-    }
-    uint32_t data = 0;
-    if (offset >= 0) {
-        data = offset;
-    } else {
-        data = abs(offset) | DICT_OFFSET_NEGATIVE_FLAG;
-    }
-    return buffer->writeUintAndAdvancePosition(data, DICT_OFFSET_FIELD_SIZE, offsetFieldPos);
-}
-}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h
deleted file mode 100644
index 362fbd1..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h
+++ /dev/null
@@ -1,79 +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.
- */
-
-#ifndef LATINIME_DYNAMIC_PT_WRITING_UTILS_H
-#define LATINIME_DYNAMIC_PT_WRITING_UTILS_H
-
-#include <cstddef>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-
-class DynamicPtWritingUtils {
- public:
-    static const int NODE_FLAG_FIELD_SIZE;
-
-    static bool writeEmptyDictionary(BufferWithExtendableBuffer *const buffer, const int rootPos);
-
-    static bool writeForwardLinkPositionAndAdvancePosition(
-            BufferWithExtendableBuffer *const buffer, const int forwardLinkPos,
-            int *const forwardLinkFieldPos);
-
-    static bool writePtNodeArraySizeAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
-            const size_t arraySize, int *const arraySizeFieldPos);
-
-    static bool writeFlags(BufferWithExtendableBuffer *const buffer,
-            const DynamicPtReadingUtils::NodeFlags nodeFlags,
-            const int nodeFlagsFieldPos) {
-        int writingPos = nodeFlagsFieldPos;
-        return writeFlagsAndAdvancePosition(buffer, nodeFlags, &writingPos);
-    }
-
-    static bool writeFlagsAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
-            const DynamicPtReadingUtils::NodeFlags nodeFlags,
-            int *const nodeFlagsFieldPos);
-
-    static bool writeParentPosOffsetAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
-            const int parentPosition, const int basePos, int *const parentPosFieldPos);
-
-    static bool writeCodePointsAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
-            const int *const codePoints, const int codePointCount, int *const codePointFieldPos);
-
-    static bool writeChildrenPositionAndAdvancePosition(BufferWithExtendableBuffer *const buffer,
-            const int childrenPosition, int *const childrenPositionFieldPos);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicPtWritingUtils);
-
-    static const size_t MAX_PTNODE_ARRAY_SIZE_TO_USE_SMALL_SIZE_FIELD;
-    static const size_t MAX_PTNODE_ARRAY_SIZE;
-    static const int SMALL_PTNODE_ARRAY_SIZE_FIELD_SIZE;
-    static const int LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE;
-    static const int LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG;
-    static const int DICT_OFFSET_FIELD_SIZE;
-    static const int MAX_DICT_OFFSET_VALUE;
-    static const int MIN_DICT_OFFSET_VALUE;
-    static const int DICT_OFFSET_NEGATIVE_FLAG;
-
-    static bool writeDictOffset(BufferWithExtendableBuffer *const buffer, const int targetPos,
-            const int basePos, int *const offsetFieldPos);
-};
-} // namespace latinime
-#endif /* LATINIME_DYNAMIC_PT_WRITING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp
deleted file mode 100644
index e64a13c..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.cpp
+++ /dev/null
@@ -1,163 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-typedef PatriciaTrieReadingUtils PtReadingUtils;
-
-const PtReadingUtils::NodeFlags PtReadingUtils::MASK_CHILDREN_POSITION_TYPE = 0xC0;
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_NOPOSITION = 0x00;
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_ONEBYTE = 0x40;
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_TWOBYTES = 0x80;
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_CHILDREN_POSITION_TYPE_THREEBYTES = 0xC0;
-
-// Flag for single/multiple char group
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_MULTIPLE_CHARS = 0x20;
-// Flag for terminal PtNodes
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_TERMINAL = 0x10;
-// Flag for shortcut targets presence
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_SHORTCUT_TARGETS = 0x08;
-// Flag for bigram presence
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_HAS_BIGRAMS = 0x04;
-// Flag for non-words (typically, shortcut only entries)
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_NOT_A_WORD = 0x02;
-// Flag for blacklist
-const PtReadingUtils::NodeFlags PtReadingUtils::FLAG_IS_BLACKLISTED = 0x01;
-
-/* static */ int PtReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-        const uint8_t *const buffer, int *const pos) {
-    const uint8_t firstByte = ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
-    if (firstByte < 0x80) {
-        return firstByte;
-    } else {
-        return ((firstByte & 0x7F) << 8) ^ ByteArrayUtils::readUint8AndAdvancePosition(
-                buffer, pos);
-    }
-}
-
-/* static */ PtReadingUtils::NodeFlags PtReadingUtils::getFlagsAndAdvancePosition(
-        const uint8_t *const buffer, int *const pos) {
-    return ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
-}
-
-/* static */ int PtReadingUtils::getCodePointAndAdvancePosition(const uint8_t *const buffer,
-        int *const pos) {
-    return ByteArrayUtils::readCodePointAndAdvancePosition(buffer, pos);
-}
-
-// Returns the number of read characters.
-/* static */ int PtReadingUtils::getCharsAndAdvancePosition(const uint8_t *const buffer,
-        const NodeFlags flags, const int maxLength, int *const outBuffer, int *const pos) {
-    int length = 0;
-    if (hasMultipleChars(flags)) {
-        length = ByteArrayUtils::readStringAndAdvancePosition(buffer, maxLength, outBuffer,
-                pos);
-    } else {
-        const int codePoint = getCodePointAndAdvancePosition(buffer, pos);
-        if (codePoint == NOT_A_CODE_POINT) {
-            // CAVEAT: codePoint == NOT_A_CODE_POINT means the code point is
-            // CHARACTER_ARRAY_TERMINATOR. The code point must not be CHARACTER_ARRAY_TERMINATOR
-            // when the PtNode has a single code point.
-            length = 0;
-            AKLOGE("codePoint is NOT_A_CODE_POINT. pos: %d, codePoint: 0x%x, buffer[pos - 1]: 0x%x",
-                    *pos - 1, codePoint, buffer[*pos - 1]);
-            ASSERT(false);
-        } else if (maxLength > 0) {
-            outBuffer[0] = codePoint;
-            length = 1;
-        }
-    }
-    return length;
-}
-
-// Returns the number of skipped characters.
-/* static */ int PtReadingUtils::skipCharacters(const uint8_t *const buffer, const NodeFlags flags,
-        const int maxLength, int *const pos) {
-    if (hasMultipleChars(flags)) {
-        return ByteArrayUtils::advancePositionToBehindString(buffer, maxLength, pos);
-    } else {
-        if (maxLength > 0) {
-            getCodePointAndAdvancePosition(buffer, pos);
-            return 1;
-        } else {
-            return 0;
-        }
-    }
-}
-
-/* static */ int PtReadingUtils::readProbabilityAndAdvancePosition(const uint8_t *const buffer,
-        int *const pos) {
-    return ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
-}
-
-/* static */ int PtReadingUtils::readChildrenPositionAndAdvancePosition(
-        const uint8_t *const buffer, const NodeFlags flags, int *const pos) {
-    const int base = *pos;
-    int offset = 0;
-    switch (MASK_CHILDREN_POSITION_TYPE & flags) {
-        case FLAG_CHILDREN_POSITION_TYPE_ONEBYTE:
-            offset = ByteArrayUtils::readUint8AndAdvancePosition(buffer, pos);
-            break;
-        case FLAG_CHILDREN_POSITION_TYPE_TWOBYTES:
-            offset = ByteArrayUtils::readUint16AndAdvancePosition(buffer, pos);
-            break;
-        case FLAG_CHILDREN_POSITION_TYPE_THREEBYTES:
-            offset = ByteArrayUtils::readUint24AndAdvancePosition(buffer, pos);
-            break;
-        default:
-            // If we come here, it means we asked for the children of a word with
-            // no children.
-            return NOT_A_DICT_POS;
-    }
-    return base + offset;
-}
-
-/* static */ void PtReadingUtils::readPtNodeInfo(const uint8_t *const dictBuf, const int ptNodePos,
-        const DictionaryShortcutsStructurePolicy *const shortcutPolicy,
-        const DictionaryBigramsStructurePolicy *const bigramPolicy,
-        NodeFlags *const outFlags, int *const outCodePointCount, int *const outCodePoint,
-        int *const outProbability, int *const outChildrenPos, int *const outShortcutPos,
-        int *const outBigramPos, int *const outSiblingPos) {
-    int readingPos = ptNodePos;
-    const NodeFlags flags = getFlagsAndAdvancePosition(dictBuf, &readingPos);
-    *outFlags = flags;
-    *outCodePointCount = getCharsAndAdvancePosition(
-            dictBuf, flags, MAX_WORD_LENGTH, outCodePoint, &readingPos);
-    *outProbability = isTerminal(flags) ?
-            readProbabilityAndAdvancePosition(dictBuf, &readingPos) : NOT_A_PROBABILITY;
-    *outChildrenPos = hasChildrenInFlags(flags) ?
-            readChildrenPositionAndAdvancePosition(dictBuf, flags, &readingPos) : NOT_A_DICT_POS;
-    *outShortcutPos = NOT_A_DICT_POS;
-    if (hasShortcutTargets(flags)) {
-        *outShortcutPos = readingPos;
-        shortcutPolicy->skipAllShortcuts(&readingPos);
-    }
-    *outBigramPos = NOT_A_DICT_POS;
-    if (hasBigrams(flags)) {
-        *outBigramPos = readingPos;
-        bigramPolicy->skipAllBigrams(&readingPos);
-    }
-    *outSiblingPos = readingPos;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h
deleted file mode 100644
index c3f09c3..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h
+++ /dev/null
@@ -1,130 +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.
- */
-
-#ifndef LATINIME_PATRICIA_TRIE_READING_UTILS_H
-#define LATINIME_PATRICIA_TRIE_READING_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-
-namespace latinime {
-
-class DictionaryShortcutsStructurePolicy;
-class DictionaryBigramsStructurePolicy;
-
-class PatriciaTrieReadingUtils {
- public:
-    typedef uint8_t NodeFlags;
-
-    static int getPtNodeArraySizeAndAdvancePosition(const uint8_t *const buffer, int *const pos);
-
-    static NodeFlags getFlagsAndAdvancePosition(const uint8_t *const buffer, int *const pos);
-
-    static int getCodePointAndAdvancePosition(const uint8_t *const buffer, int *const pos);
-
-    // Returns the number of read characters.
-    static int getCharsAndAdvancePosition(const uint8_t *const buffer, const NodeFlags flags,
-            const int maxLength, int *const outBuffer, int *const pos);
-
-    // Returns the number of skipped characters.
-    static int skipCharacters(const uint8_t *const buffer, const NodeFlags flags,
-            const int maxLength, int *const pos);
-
-    static int readProbabilityAndAdvancePosition(const uint8_t *const buffer, int *const pos);
-
-    static int readChildrenPositionAndAdvancePosition(const uint8_t *const buffer,
-            const NodeFlags flags, int *const pos);
-
-    /**
-     * Node Flags
-     */
-    static AK_FORCE_INLINE bool isBlacklisted(const NodeFlags flags) {
-        return (flags & FLAG_IS_BLACKLISTED) != 0;
-    }
-
-    static AK_FORCE_INLINE bool isNotAWord(const NodeFlags flags) {
-        return (flags & FLAG_IS_NOT_A_WORD) != 0;
-    }
-
-    static AK_FORCE_INLINE bool isTerminal(const NodeFlags flags) {
-        return (flags & FLAG_IS_TERMINAL) != 0;
-    }
-
-    static AK_FORCE_INLINE bool hasShortcutTargets(const NodeFlags flags) {
-        return (flags & FLAG_HAS_SHORTCUT_TARGETS) != 0;
-    }
-
-    static AK_FORCE_INLINE bool hasBigrams(const NodeFlags flags) {
-        return (flags & FLAG_HAS_BIGRAMS) != 0;
-    }
-
-    static AK_FORCE_INLINE bool hasMultipleChars(const NodeFlags flags) {
-        return (flags & FLAG_HAS_MULTIPLE_CHARS) != 0;
-    }
-
-    static AK_FORCE_INLINE bool hasChildrenInFlags(const NodeFlags flags) {
-        return FLAG_CHILDREN_POSITION_TYPE_NOPOSITION != (MASK_CHILDREN_POSITION_TYPE & flags);
-    }
-
-    static AK_FORCE_INLINE NodeFlags createAndGetFlags(const bool isBlacklisted,
-            const bool isNotAWord, const bool isTerminal, const bool hasShortcutTargets,
-            const bool hasBigrams, const bool hasMultipleChars,
-            const int childrenPositionFieldSize) {
-        NodeFlags nodeFlags = 0;
-        nodeFlags = isBlacklisted ? (nodeFlags | FLAG_IS_BLACKLISTED) : nodeFlags;
-        nodeFlags = isNotAWord ? (nodeFlags | FLAG_IS_NOT_A_WORD) : nodeFlags;
-        nodeFlags = isTerminal ? (nodeFlags | FLAG_IS_TERMINAL) : nodeFlags;
-        nodeFlags = hasShortcutTargets ? (nodeFlags | FLAG_HAS_SHORTCUT_TARGETS) : nodeFlags;
-        nodeFlags = hasBigrams ? (nodeFlags | FLAG_HAS_BIGRAMS) : nodeFlags;
-        nodeFlags = hasMultipleChars ? (nodeFlags | FLAG_HAS_MULTIPLE_CHARS) : nodeFlags;
-        if (childrenPositionFieldSize == 1) {
-            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_ONEBYTE;
-        } else if (childrenPositionFieldSize == 2) {
-            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_TWOBYTES;
-        } else if (childrenPositionFieldSize == 3) {
-            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_THREEBYTES;
-        } else {
-            nodeFlags |= FLAG_CHILDREN_POSITION_TYPE_NOPOSITION;
-        }
-        return nodeFlags;
-    }
-
-    static void readPtNodeInfo(const uint8_t *const dictBuf, const int ptNodePos,
-            const DictionaryShortcutsStructurePolicy *const shortcutPolicy,
-            const DictionaryBigramsStructurePolicy *const bigramPolicy,
-            NodeFlags *const outFlags, int *const outCodePointCount, int *const outCodePoint,
-            int *const outProbability, int *const outChildrenPos, int *const outShortcutPos,
-            int *const outBigramPos, int *const outSiblingPos);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTrieReadingUtils);
-
-    static const NodeFlags MASK_CHILDREN_POSITION_TYPE;
-    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_NOPOSITION;
-    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_ONEBYTE;
-    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_TWOBYTES;
-    static const NodeFlags FLAG_CHILDREN_POSITION_TYPE_THREEBYTES;
-
-    static const NodeFlags FLAG_HAS_MULTIPLE_CHARS;
-    static const NodeFlags FLAG_IS_TERMINAL;
-    static const NodeFlags FLAG_HAS_SHORTCUT_TARGETS;
-    static const NodeFlags FLAG_HAS_BIGRAMS;
-    static const NodeFlags FLAG_IS_NOT_A_WORD;
-    static const NodeFlags FLAG_IS_BLACKLISTED;
-};
-} // namespace latinime
-#endif /* LATINIME_PATRICIA_TRIE_NODE_READING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
deleted file mode 100644
index b2e60a8..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h
+++ /dev/null
@@ -1,255 +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.
- */
-
-#ifndef LATINIME_PT_NODE_PARAMS_H
-#define LATINIME_PT_NODE_PARAMS_H
-
-#include <cstring>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "utils/char_utils.h"
-
-namespace latinime {
-
-// This class has information of a PtNode. This class is immutable.
-class PtNodeParams {
- public:
-    // Invalid PtNode.
-    PtNodeParams() : mHeadPos(NOT_A_DICT_POS), mFlags(0), mHasMovedFlag(false),
-            mParentPos(NOT_A_DICT_POS), mCodePointCount(0), mCodePoints(),
-            mTerminalIdFieldPos(NOT_A_DICT_POS), mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
-            mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(NOT_A_PROBABILITY),
-            mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
-            mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS),
-            mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_DICT_POS) {}
-
-    PtNodeParams(const PtNodeParams& ptNodeParams)
-            : mHeadPos(ptNodeParams.mHeadPos), mFlags(ptNodeParams.mFlags),
-              mHasMovedFlag(ptNodeParams.mHasMovedFlag), mParentPos(ptNodeParams.mParentPos),
-              mCodePointCount(ptNodeParams.mCodePointCount), mCodePoints(),
-              mTerminalIdFieldPos(ptNodeParams.mTerminalIdFieldPos),
-              mTerminalId(ptNodeParams.mTerminalId),
-              mProbabilityFieldPos(ptNodeParams.mProbabilityFieldPos),
-              mProbability(ptNodeParams.mProbability),
-              mChildrenPosFieldPos(ptNodeParams.mChildrenPosFieldPos),
-              mChildrenPos(ptNodeParams.mChildrenPos),
-              mBigramLinkedNodePos(ptNodeParams.mBigramLinkedNodePos),
-              mShortcutPos(ptNodeParams.mShortcutPos), mBigramPos(ptNodeParams.mBigramPos),
-              mSiblingPos(ptNodeParams.mSiblingPos) {
-        memcpy(mCodePoints, ptNodeParams.getCodePoints(), sizeof(int) * mCodePointCount);
-    }
-
-    // PtNode read from version 2 dictionary.
-    PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags,
-            const int codePointCount, const int *const codePoints, const int probability,
-            const int childrenPos, const int shortcutPos, const int bigramPos,
-            const int siblingPos)
-            : mHeadPos(headPos), mFlags(flags), mHasMovedFlag(false), mParentPos(NOT_A_DICT_POS),
-              mCodePointCount(codePointCount), mCodePoints(), mTerminalIdFieldPos(NOT_A_DICT_POS),
-              mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
-              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
-              mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(childrenPos),
-              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(shortcutPos),
-              mBigramPos(bigramPos), mSiblingPos(siblingPos) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
-    }
-
-    // PtNode with a terminal id.
-    PtNodeParams(const int headPos, const PatriciaTrieReadingUtils::NodeFlags flags,
-            const int parentPos, const int codePointCount, const int *const codePoints,
-            const int terminalIdFieldPos, const int terminalId, const int probability,
-            const int childrenPosFieldPos, const int childrenPos, const int siblingPos)
-            : mHeadPos(headPos), mFlags(flags), mHasMovedFlag(true), mParentPos(parentPos),
-              mCodePointCount(codePointCount), mCodePoints(),
-              mTerminalIdFieldPos(terminalIdFieldPos), mTerminalId(terminalId),
-              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
-              mChildrenPosFieldPos(childrenPosFieldPos), mChildrenPos(childrenPos),
-              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(terminalId),
-              mBigramPos(terminalId), mSiblingPos(siblingPos) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
-    }
-
-    // Construct new params by updating existing PtNode params.
-    PtNodeParams(const PtNodeParams *const ptNodeParams,
-            const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability)
-            : mHeadPos(ptNodeParams->getHeadPos()), mFlags(flags), mHasMovedFlag(true),
-              mParentPos(parentPos), mCodePointCount(codePointCount), mCodePoints(),
-              mTerminalIdFieldPos(ptNodeParams->getTerminalIdFieldPos()),
-              mTerminalId(ptNodeParams->getTerminalId()),
-              mProbabilityFieldPos(ptNodeParams->getProbabilityFieldPos()),
-              mProbability(probability),
-              mChildrenPosFieldPos(ptNodeParams->getChildrenPosFieldPos()),
-              mChildrenPos(ptNodeParams->getChildrenPos()),
-              mBigramLinkedNodePos(ptNodeParams->getBigramLinkedNodePos()),
-              mShortcutPos(ptNodeParams->getShortcutPos()),
-              mBigramPos(ptNodeParams->getBigramsPos()),
-              mSiblingPos(ptNodeParams->getSiblingNodePos()) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
-    }
-
-    PtNodeParams(const PatriciaTrieReadingUtils::NodeFlags flags, const int parentPos,
-            const int codePointCount, const int *const codePoints, const int probability)
-            : mHeadPos(NOT_A_DICT_POS), mFlags(flags), mHasMovedFlag(true), mParentPos(parentPos),
-              mCodePointCount(codePointCount), mCodePoints(),
-              mTerminalIdFieldPos(NOT_A_DICT_POS),
-              mTerminalId(Ver4DictConstants::NOT_A_TERMINAL_ID),
-              mProbabilityFieldPos(NOT_A_DICT_POS), mProbability(probability),
-              mChildrenPosFieldPos(NOT_A_DICT_POS), mChildrenPos(NOT_A_DICT_POS),
-              mBigramLinkedNodePos(NOT_A_DICT_POS), mShortcutPos(NOT_A_DICT_POS),
-              mBigramPos(NOT_A_DICT_POS), mSiblingPos(NOT_A_DICT_POS) {
-        memcpy(mCodePoints, codePoints, sizeof(int) * mCodePointCount);
-    }
-
-    AK_FORCE_INLINE bool isValid() const {
-        return mCodePointCount > 0;
-    }
-
-    // Head position of the PtNode
-    AK_FORCE_INLINE int getHeadPos() const {
-        return mHeadPos;
-    }
-
-    // Flags
-    AK_FORCE_INLINE bool isDeleted() const {
-        return mHasMovedFlag && DynamicPtReadingUtils::isDeleted(mFlags);
-    }
-
-    AK_FORCE_INLINE bool willBecomeNonTerminal() const {
-        return mHasMovedFlag && DynamicPtReadingUtils::willBecomeNonTerminal(mFlags);
-    }
-
-    AK_FORCE_INLINE bool hasChildren() const {
-        return mChildrenPos != NOT_A_DICT_POS;
-    }
-
-    AK_FORCE_INLINE bool isTerminal() const {
-        return PatriciaTrieReadingUtils::isTerminal(mFlags);
-    }
-
-    AK_FORCE_INLINE bool isBlacklisted() const {
-        return PatriciaTrieReadingUtils::isBlacklisted(mFlags);
-    }
-
-    AK_FORCE_INLINE bool isNotAWord() const {
-        return PatriciaTrieReadingUtils::isNotAWord(mFlags);
-    }
-
-    AK_FORCE_INLINE bool hasBigrams() const {
-        return PatriciaTrieReadingUtils::hasBigrams(mFlags);
-    }
-
-    AK_FORCE_INLINE bool hasShortcutTargets() const {
-        return PatriciaTrieReadingUtils::hasShortcutTargets(mFlags);
-    }
-
-    AK_FORCE_INLINE bool representsNonWordInfo() const {
-        return getCodePointCount() > 0 && !CharUtils::isInUnicodeSpace(getCodePoints()[0])
-                && isNotAWord();
-    }
-
-    AK_FORCE_INLINE int representsBeginningOfSentence() const {
-        return getCodePointCount() > 0 && getCodePoints()[0] == CODE_POINT_BEGINNING_OF_SENTENCE
-                && isNotAWord();
-    }
-
-    // Parent node position
-    AK_FORCE_INLINE int getParentPos() const {
-        return mParentPos;
-    }
-
-    // Number of code points
-    AK_FORCE_INLINE uint8_t getCodePointCount() const {
-        return mCodePointCount;
-    }
-
-    AK_FORCE_INLINE const int *getCodePoints() const {
-        return mCodePoints;
-    }
-
-    // Probability
-    AK_FORCE_INLINE int getTerminalIdFieldPos() const {
-        return mTerminalIdFieldPos;
-    }
-
-    AK_FORCE_INLINE int getTerminalId() const {
-        return mTerminalId;
-    }
-
-    // Probability
-    AK_FORCE_INLINE int getProbabilityFieldPos() const {
-        return mProbabilityFieldPos;
-    }
-
-    AK_FORCE_INLINE int getProbability() const {
-        return mProbability;
-    }
-
-    // Children PtNode array position
-    AK_FORCE_INLINE int getChildrenPosFieldPos() const {
-        return mChildrenPosFieldPos;
-    }
-
-    AK_FORCE_INLINE int getChildrenPos() const {
-        return mChildrenPos;
-    }
-
-    // Bigram linked node position.
-    AK_FORCE_INLINE int getBigramLinkedNodePos() const {
-        return mBigramLinkedNodePos;
-    }
-
-    // Shortcutlist position
-    AK_FORCE_INLINE int getShortcutPos() const {
-        return mShortcutPos;
-    }
-
-    // Bigrams position
-    AK_FORCE_INLINE int getBigramsPos() const {
-        return mBigramPos;
-    }
-
-    // Sibling node position
-    AK_FORCE_INLINE int getSiblingNodePos() const {
-        return mSiblingPos;
-    }
-
- private:
-    // This class have a public copy constructor to be used as a return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(PtNodeParams);
-
-    const int mHeadPos;
-    const PatriciaTrieReadingUtils::NodeFlags mFlags;
-    const bool mHasMovedFlag;
-    const int mParentPos;
-    const uint8_t mCodePointCount;
-    int mCodePoints[MAX_WORD_LENGTH];
-    const int mTerminalIdFieldPos;
-    const int mTerminalId;
-    const int mProbabilityFieldPos;
-    const int mProbability;
-    const int mChildrenPosFieldPos;
-    const int mChildrenPos;
-    const int mBigramLinkedNodePos;
-    const int mShortcutPos;
-    const int mBigramPos;
-    const int mSiblingPos;
-};
-} // namespace latinime
-#endif /* LATINIME_PT_NODE_PARAMS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
deleted file mode 100644
index 31299a7..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h
+++ /dev/null
@@ -1,40 +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.
- */
-
-#ifndef LATINIME_PT_NODE_READER_H
-#define LATINIME_PT_NODE_READER_H
-
-#include "defines.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-
-namespace latinime {
-
-// Interface class used to read PtNode information.
-class PtNodeReader {
- public:
-    virtual ~PtNodeReader() {}
-    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(
-            const int ptNodePos) const = 0;
-
- protected:
-    PtNodeReader() {};
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(PtNodeReader);
-};
-} // namespace latinime
-#endif /* LATINIME_PT_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
deleted file mode 100644
index 955d779..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
+++ /dev/null
@@ -1,97 +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.
- */
-
-#ifndef LATINIME_PT_NODE_WRITER_H
-#define LATINIME_PT_NODE_WRITER_H
-
-#include <unordered_map>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "utils/int_array_view.h"
-
-namespace latinime {
-
-class BigramProperty;
-class UnigramProperty;
-
-// Interface class used to write PtNode information.
-class PtNodeWriter {
- public:
-    typedef std::unordered_map<int, int> PtNodeArrayPositionRelocationMap;
-    typedef std::unordered_map<int, int> PtNodePositionRelocationMap;
-    struct DictPositionRelocationMap {
-     public:
-        DictPositionRelocationMap()
-                : mPtNodeArrayPositionRelocationMap(), mPtNodePositionRelocationMap() {}
-
-        PtNodeArrayPositionRelocationMap mPtNodeArrayPositionRelocationMap;
-        PtNodePositionRelocationMap mPtNodePositionRelocationMap;
-
-     private:
-        DISALLOW_COPY_AND_ASSIGN(DictPositionRelocationMap);
-    };
-
-    virtual ~PtNodeWriter() {}
-
-    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams) = 0;
-
-    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int movedPos, const int bigramLinkedNodePos) = 0;
-
-    virtual bool markPtNodeAsWillBecomeNonTerminal(
-            const PtNodeParams *const toBeUpdatedPtNodeParams) = 0;
-
-    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const UnigramProperty *const unigramProperty) = 0;
-
-    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-            const PtNodeParams *const toBeUpdatedPtNodeParams,
-            bool *const outNeedsToKeepPtNode) = 0;
-
-    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
-                const int newChildrenPosition) = 0;
-
-    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            int *const ptNodeWritingPos) = 0;
-
-    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos) = 0;
-
-    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) = 0;
-
-    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId) = 0;
-
-    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
-            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) = 0;
-
-    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const DictPositionRelocationMap *const dictPositionRelocationMap,
-            int *const outBigramEntryCount) = 0;
-
-    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
-            const int *const targetCodePoints, const int targetCodePointCount,
-            const int shortcutProbability) = 0;
-
- protected:
-    PtNodeWriter() {};
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(PtNodeWriter);
-};
-} // namespace latinime
-#endif /* LATINIME_PT_NODE_WRITER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
deleted file mode 100644
index 91c7694..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.cpp
+++ /dev/null
@@ -1,51 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-// Flag for presence of more attributes
-const ShortcutListReadingUtils::ShortcutFlags
-        ShortcutListReadingUtils::FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
-// Mask for attribute probability, stored on 4 bits inside the flags byte.
-const ShortcutListReadingUtils::ShortcutFlags
-        ShortcutListReadingUtils::MASK_ATTRIBUTE_PROBABILITY = 0x0F;
-const int ShortcutListReadingUtils::SHORTCUT_LIST_SIZE_FIELD_SIZE = 2;
-// The numeric value of the shortcut probability that means 'whitelist'.
-const int ShortcutListReadingUtils::WHITELIST_SHORTCUT_PROBABILITY = 15;
-
-/* static */ ShortcutListReadingUtils::ShortcutFlags
-        ShortcutListReadingUtils::getFlagsAndForwardPointer(const uint8_t *const dictRoot,
-                int *const pos) {
-    return ByteArrayUtils::readUint8AndAdvancePosition(dictRoot, pos);
-}
-
-/* static */ int ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(
-        const uint8_t *const dictRoot, int *const pos) {
-    // readUint16andAdvancePosition() returns an offset *including* the uint16 field itself.
-    return ByteArrayUtils::readUint16AndAdvancePosition(dictRoot, pos)
-            - SHORTCUT_LIST_SIZE_FIELD_SIZE;
-}
-
-/* static */ int ShortcutListReadingUtils::readShortcutTarget(
-        const uint8_t *const dictRoot, const int maxLength, int *const outWord, int *const pos) {
-    return ByteArrayUtils::readStringAndAdvancePosition(dictRoot, maxLength, outWord, pos);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
deleted file mode 100644
index d065bf7..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h
+++ /dev/null
@@ -1,69 +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.
- */
-
-#ifndef LATINIME_SHORTCUT_LIST_READING_UTILS_H
-#define LATINIME_SHORTCUT_LIST_READING_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-
-namespace latinime {
-
-class ShortcutListReadingUtils {
- public:
-    typedef uint8_t ShortcutFlags;
-
-    static ShortcutFlags getFlagsAndForwardPointer(const uint8_t *const dictRoot, int *const pos);
-
-    static AK_FORCE_INLINE int getProbabilityFromFlags(const ShortcutFlags flags) {
-        return flags & MASK_ATTRIBUTE_PROBABILITY;
-    }
-
-    static AK_FORCE_INLINE bool hasNext(const ShortcutFlags flags) {
-        return (flags & FLAG_ATTRIBUTE_HAS_NEXT) != 0;
-    }
-
-    // This method returns the size of the shortcut list region excluding the shortcut list size
-    // field at the beginning.
-    static int getShortcutListSizeAndForwardPointer(const uint8_t *const dictRoot, int *const pos);
-
-    static AK_FORCE_INLINE int getShortcutListSizeFieldSize() {
-        return SHORTCUT_LIST_SIZE_FIELD_SIZE;
-    }
-
-    static AK_FORCE_INLINE void skipShortcuts(const uint8_t *const dictRoot, int *const pos) {
-        const int shortcutListSize = getShortcutListSizeAndForwardPointer(dictRoot, pos);
-        *pos += shortcutListSize;
-    }
-
-    static AK_FORCE_INLINE bool isWhitelist(const ShortcutFlags flags) {
-        return getProbabilityFromFlags(flags) == WHITELIST_SHORTCUT_PROBABILITY;
-    }
-
-    static int readShortcutTarget(const uint8_t *const dictRoot, const int maxLength,
-            int *const outWord, int *const pos);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutListReadingUtils);
-
-    static const ShortcutFlags FLAG_ATTRIBUTE_HAS_NEXT;
-    static const ShortcutFlags MASK_ATTRIBUTE_PROBABILITY;
-    static const int SHORTCUT_LIST_SIZE_FIELD_SIZE;
-    static const int WHITELIST_SHORTCUT_PROBABILITY;
-};
-} // namespace latinime
-#endif // LATINIME_SHORTCUT_LIST_READING_UTILS_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
deleted file mode 100644
index 73e291e..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef LATINIME_BIGRAM_LIST_POLICY_H
-#define LATINIME_BIGRAM_LIST_POLICY_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
-
-namespace latinime {
-
-class BigramListPolicy : public DictionaryBigramsStructurePolicy {
- public:
-    BigramListPolicy(const uint8_t *const bigramsBuf, const int bufSize)
-            : mBigramsBuf(bigramsBuf), mBufSize(bufSize) {}
-
-    ~BigramListPolicy() {}
-
-    void getNextBigram(int *const outBigramPos, int *const outProbability, bool *const outHasNext,
-            int *const pos) const {
-        BigramListReadWriteUtils::BigramFlags flags;
-        if (!BigramListReadWriteUtils::getBigramEntryPropertiesAndAdvancePosition(mBigramsBuf,
-                mBufSize, &flags, outBigramPos, pos)) {
-            AKLOGE("Cannot read bigram entry. mBufSize: %d, pos: %d. ", mBufSize, *pos);
-            *outProbability = NOT_A_PROBABILITY;
-            *outHasNext = false;
-            return;
-        }
-        *outProbability = BigramListReadWriteUtils::getProbabilityFromFlags(flags);
-        *outHasNext = BigramListReadWriteUtils::hasNext(flags);
-    }
-
-    bool skipAllBigrams(int *const pos) const {
-        return BigramListReadWriteUtils::skipExistingBigrams(mBigramsBuf, mBufSize, pos);
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(BigramListPolicy);
-
-    const uint8_t *const mBigramsBuf;
-    const int mBufSize;
-};
-} // namespace latinime
-#endif // LATINIME_BIGRAM_LIST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
deleted file mode 100644
index ea32eb2..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ /dev/null
@@ -1,470 +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.
- */
-
-
-#include "suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h"
-
-#include "defines.h"
-#include "suggest/core/dicnode/dic_node.h"
-#include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/core/dictionary/binary_dictionary_bigrams_iterator.h"
-#include "suggest/core/dictionary/ngram_listener.h"
-#include "suggest/core/session/prev_words_info.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
-#include "utils/char_utils.h"
-
-namespace latinime {
-
-void PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
-        DicNodeVector *const childDicNodes) const {
-    if (!dicNode->hasChildren()) {
-        return;
-    }
-    int nextPos = dicNode->getChildrenPtNodeArrayPos();
-    if (nextPos < 0 || nextPos >= mDictBufferSize) {
-        AKLOGE("Children PtNode array position is invalid. pos: %d, dict size: %d",
-                nextPos, mDictBufferSize);
-        mIsCorrupted = true;
-        ASSERT(false);
-        return;
-    }
-    const int childCount = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-            mDictRoot, &nextPos);
-    for (int i = 0; i < childCount; i++) {
-        if (nextPos < 0 || nextPos >= mDictBufferSize) {
-            AKLOGE("Child PtNode position is invalid. pos: %d, dict size: %d, childCount: %d / %d",
-                    nextPos, mDictBufferSize, i, childCount);
-            mIsCorrupted = true;
-            ASSERT(false);
-            return;
-        }
-        nextPos = createAndGetLeavingChildNode(dicNode, nextPos, childDicNodes);
-    }
-}
-
-// This retrieves code points and the probability of the word by its terminal position.
-// Due to the fact that words are ordered in the dictionary in a strict breadth-first order,
-// it is possible to check for this with advantageous complexity. For each PtNode array, we search
-// for PtNodes with children and compare the children position with the position we look for.
-// When we shoot the position we look for, it means the word we look for is in the children
-// of the previous PtNode. The only tricky part is the fact that if we arrive at the end of a
-// PtNode array with the last PtNode's children position still less than what we are searching for,
-// we must descend the last PtNode's children (for example, if the word we are searching for starts
-// with a z, it's the last PtNode of the root array, so all children addresses will be smaller
-// than the position we look for, and we have to descend the z PtNode).
-/* Parameters :
- * ptNodePos: the byte position of the terminal PtNode of the word we are searching for (this is
- *   what is stored as the "bigram position" in each bigram)
- * outCodePoints: an array to write the found word, with MAX_WORD_LENGTH size.
- * outUnigramProbability: a pointer to an int to write the probability into.
- * Return value : the code point count, of 0 if the word was not found.
- */
-// TODO: Split this function to be more readable
-int PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
-        const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
-        int *const outUnigramProbability) const {
-    int pos = getRootPosition();
-    int wordPos = 0;
-    // One iteration of the outer loop iterates through PtNode arrays. As stated above, we will
-    // only traverse PtNodes that are actually a part of the terminal we are searching, so each
-    // time we enter this loop we are one depth level further than last time.
-    // The only reason we count PtNodes is because we want to reduce the probability of infinite
-    // looping in case there is a bug. Since we know there is an upper bound to the depth we are
-    // supposed to traverse, it does not hurt to count iterations.
-    for (int loopCount = maxCodePointCount; loopCount > 0; --loopCount) {
-        int lastCandidatePtNodePos = 0;
-        // Let's loop through PtNodes in this PtNode array searching for either the terminal
-        // or one of its ascendants.
-        if (pos < 0 || pos >= mDictBufferSize) {
-            AKLOGE("PtNode array position is invalid. pos: %d, dict size: %d",
-                    pos, mDictBufferSize);
-            mIsCorrupted = true;
-            ASSERT(false);
-            *outUnigramProbability = NOT_A_PROBABILITY;
-            return 0;
-        }
-        for (int ptNodeCount = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-                mDictRoot, &pos); ptNodeCount > 0; --ptNodeCount) {
-            const int startPos = pos;
-            if (pos < 0 || pos >= mDictBufferSize) {
-                AKLOGE("PtNode position is invalid. pos: %d, dict size: %d", pos, mDictBufferSize);
-                mIsCorrupted = true;
-                ASSERT(false);
-                *outUnigramProbability = NOT_A_PROBABILITY;
-                return 0;
-            }
-            const PatriciaTrieReadingUtils::NodeFlags flags =
-                    PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(mDictRoot, &pos);
-            const int character = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                    mDictRoot, &pos);
-            if (ptNodePos == startPos) {
-                // We found the position. Copy the rest of the code points in the buffer and return
-                // the length.
-                outCodePoints[wordPos] = character;
-                if (PatriciaTrieReadingUtils::hasMultipleChars(flags)) {
-                    int nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                            mDictRoot, &pos);
-                    // We count code points in order to avoid infinite loops if the file is broken
-                    // or if there is some other bug
-                    int charCount = maxCodePointCount;
-                    while (NOT_A_CODE_POINT != nextChar && --charCount > 0) {
-                        outCodePoints[++wordPos] = nextChar;
-                        nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                                mDictRoot, &pos);
-                    }
-                }
-                *outUnigramProbability =
-                        PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot,
-                                &pos);
-                return ++wordPos;
-            }
-            // We need to skip past this PtNode, so skip any remaining code points after the
-            // first and possibly the probability.
-            if (PatriciaTrieReadingUtils::hasMultipleChars(flags)) {
-                PatriciaTrieReadingUtils::skipCharacters(mDictRoot, flags, MAX_WORD_LENGTH, &pos);
-            }
-            if (PatriciaTrieReadingUtils::isTerminal(flags)) {
-                PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot, &pos);
-            }
-            // The fact that this PtNode has children is very important. Since we already know
-            // that this PtNode does not match, if it has no children we know it is irrelevant
-            // to what we are searching for.
-            const bool hasChildren = PatriciaTrieReadingUtils::hasChildrenInFlags(flags);
-            // We will write in `found' whether we have passed the children position we are
-            // searching for. For example if we search for "beer", the children of b are less
-            // than the address we are searching for and the children of c are greater. When we
-            // come here for c, we realize this is too big, and that we should descend b.
-            bool found;
-            if (hasChildren) {
-                int currentPos = pos;
-                // Here comes the tricky part. First, read the children position.
-                const int childrenPos = PatriciaTrieReadingUtils
-                        ::readChildrenPositionAndAdvancePosition(mDictRoot, flags, &currentPos);
-                if (childrenPos > ptNodePos) {
-                    // If the children pos is greater than the position, it means the previous
-                    // PtNode, which position is stored in lastCandidatePtNodePos, was the right
-                    // one.
-                    found = true;
-                } else if (1 >= ptNodeCount) {
-                    // However if we are on the LAST PtNode of this array, and we have NOT shot the
-                    // position we should descend THIS PtNode. So we trick the
-                    // lastCandidatePtNodePos so that we will descend this PtNode, not the previous
-                    // one.
-                    lastCandidatePtNodePos = startPos;
-                    found = true;
-                } else {
-                    // Else, we should continue looking.
-                    found = false;
-                }
-            } else {
-                // Even if we don't have children here, we could still be on the last PtNode of
-                // this array. If this is the case, we should descend the last PtNode that had
-                // children, and their position is already in lastCandidatePtNodePos.
-                found = (1 >= ptNodeCount);
-            }
-
-            if (found) {
-                // Okay, we found the PtNode we should descend. Its position is in
-                // the lastCandidatePtNodePos variable, so we just re-read it.
-                if (0 != lastCandidatePtNodePos) {
-                    const PatriciaTrieReadingUtils::NodeFlags lastFlags =
-                            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(
-                                    mDictRoot, &lastCandidatePtNodePos);
-                    const int lastChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                            mDictRoot, &lastCandidatePtNodePos);
-                    // We copy all the characters in this PtNode to the buffer
-                    outCodePoints[wordPos] = lastChar;
-                    if (PatriciaTrieReadingUtils::hasMultipleChars(lastFlags)) {
-                        int nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                                mDictRoot, &lastCandidatePtNodePos);
-                        int charCount = maxCodePointCount;
-                        while (-1 != nextChar && --charCount > 0) {
-                            outCodePoints[++wordPos] = nextChar;
-                            nextChar = PatriciaTrieReadingUtils::getCodePointAndAdvancePosition(
-                                    mDictRoot, &lastCandidatePtNodePos);
-                        }
-                    }
-                    ++wordPos;
-                    // Now we only need to branch to the children address. Skip the probability if
-                    // it's there, read pos, and break to resume the search at pos.
-                    if (PatriciaTrieReadingUtils::isTerminal(lastFlags)) {
-                        PatriciaTrieReadingUtils::readProbabilityAndAdvancePosition(mDictRoot,
-                                &lastCandidatePtNodePos);
-                    }
-                    pos = PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
-                            mDictRoot, lastFlags, &lastCandidatePtNodePos);
-                    break;
-                } else {
-                    // Here is a little tricky part: we come here if we found out that all children
-                    // addresses in this PtNode are bigger than the address we are searching for.
-                    // Should we conclude the word is not in the dictionary? No! It could still be
-                    // one of the remaining PtNodes in this array, so we have to keep looking in
-                    // this array until we find it (or we realize it's not there either, in which
-                    // case it's actually not in the dictionary). Pass the end of this PtNode,
-                    // ready to start the next one.
-                    if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) {
-                        PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
-                                mDictRoot, flags, &pos);
-                    }
-                    if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) {
-                        mShortcutListPolicy.skipAllShortcuts(&pos);
-                    }
-                    if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
-                        if (!mBigramListPolicy.skipAllBigrams(&pos)) {
-                            AKLOGE("Cannot skip bigrams. BufSize: %d, pos: %d.", mDictBufferSize,
-                                    pos);
-                            mIsCorrupted = true;
-                            ASSERT(false);
-                            *outUnigramProbability = NOT_A_PROBABILITY;
-                            return 0;
-                        }
-                    }
-                }
-            } else {
-                // If we did not find it, we should record the last children address for the next
-                // iteration.
-                if (hasChildren) lastCandidatePtNodePos = startPos;
-                // Now skip the end of this PtNode (children pos and the attributes if any) so that
-                // our pos is after the end of this PtNode, at the start of the next one.
-                if (PatriciaTrieReadingUtils::hasChildrenInFlags(flags)) {
-                    PatriciaTrieReadingUtils::readChildrenPositionAndAdvancePosition(
-                            mDictRoot, flags, &pos);
-                }
-                if (PatriciaTrieReadingUtils::hasShortcutTargets(flags)) {
-                    mShortcutListPolicy.skipAllShortcuts(&pos);
-                }
-                if (PatriciaTrieReadingUtils::hasBigrams(flags)) {
-                    if (!mBigramListPolicy.skipAllBigrams(&pos)) {
-                        AKLOGE("Cannot skip bigrams. BufSize: %d, pos: %d.", mDictBufferSize, pos);
-                        mIsCorrupted = true;
-                        ASSERT(false);
-                        *outUnigramProbability = NOT_A_PROBABILITY;
-                        return 0;
-                    }
-                }
-            }
-
-        }
-    }
-    // If we have looked through all the PtNodes and found no match, the ptNodePos is
-    // not the position of a terminal in this dictionary.
-    return 0;
-}
-
-// This function gets the position of the terminal PtNode of the exact matching word in the
-// dictionary. If no match is found, it returns NOT_A_DICT_POS.
-int PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
-    DynamicPtReadingHelper readingHelper(&mPtNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
-    }
-    return ptNodePos;
-}
-
-int PatriciaTriePolicy::getProbability(const int unigramProbability,
-        const int bigramProbability) const {
-    // Due to space constraints, the probability for bigrams is approximate - the lower the unigram
-    // probability, the worse the precision. The theoritical maximum error in resulting probability
-    // is 8 - although in the practice it's never bigger than 3 or 4 in very bad cases. This means
-    // that sometimes, we'll see some bigrams interverted here, but it can't get too bad.
-    if (unigramProbability == NOT_A_PROBABILITY) {
-        return NOT_A_PROBABILITY;
-    } else if (bigramProbability == NOT_A_PROBABILITY) {
-        return ProbabilityUtils::backoff(unigramProbability);
-    } else {
-        return ProbabilityUtils::computeProbabilityForBigram(unigramProbability,
-                bigramProbability);
-    }
-}
-
-int PatriciaTriePolicy::getProbabilityOfPtNode(const int *const prevWordsPtNodePos,
-        const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_PROBABILITY;
-    }
-    const PtNodeParams ptNodeParams =
-            mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    if (ptNodeParams.isNotAWord() || ptNodeParams.isBlacklisted()) {
-        // If this is not a word, or if it's a blacklisted entry, it should behave as
-        // having no probability outside of the suggestion process (where it should be used
-        // for shortcuts).
-        return NOT_A_PROBABILITY;
-    }
-    if (prevWordsPtNodePos) {
-        const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-        BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramsPosition);
-        while (bigramsIt.hasNext()) {
-            bigramsIt.next();
-            if (bigramsIt.getBigramPos() == ptNodePos
-                    && bigramsIt.getProbability() != NOT_A_PROBABILITY) {
-                return getProbability(ptNodeParams.getProbability(), bigramsIt.getProbability());
-            }
-        }
-        return NOT_A_PROBABILITY;
-    }
-    return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
-}
-
-void PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordsPtNodePos,
-        NgramListener *const listener) const {
-    if (!prevWordsPtNodePos) {
-        return;
-    }
-    const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-    BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramsPosition);
-    while (bigramsIt.hasNext()) {
-        bigramsIt.next();
-        listener->onVisitEntry(bigramsIt.getProbability(), bigramsIt.getBigramPos());
-    }
-}
-
-int PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getShortcutPos();
-}
-
-int PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    return mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos).getBigramsPos();
-}
-
-int PatriciaTriePolicy::createAndGetLeavingChildNode(const DicNode *const dicNode,
-        const int ptNodePos, DicNodeVector *childDicNodes) const {
-    PatriciaTrieReadingUtils::NodeFlags flags;
-    int mergedNodeCodePointCount = 0;
-    int mergedNodeCodePoints[MAX_WORD_LENGTH];
-    int probability = NOT_A_PROBABILITY;
-    int childrenPos = NOT_A_DICT_POS;
-    int shortcutPos = NOT_A_DICT_POS;
-    int bigramPos = NOT_A_DICT_POS;
-    int siblingPos = NOT_A_DICT_POS;
-    PatriciaTrieReadingUtils::readPtNodeInfo(mDictRoot, ptNodePos, getShortcutsStructurePolicy(),
-            &mBigramListPolicy, &flags, &mergedNodeCodePointCount, mergedNodeCodePoints,
-            &probability, &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
-    // Skip PtNodes don't start with Unicode code point because they represent non-word information.
-    if (CharUtils::isInUnicodeSpace(mergedNodeCodePoints[0])) {
-        childDicNodes->pushLeavingChild(dicNode, ptNodePos, childrenPos, probability,
-                PatriciaTrieReadingUtils::isTerminal(flags),
-                PatriciaTrieReadingUtils::hasChildrenInFlags(flags),
-                PatriciaTrieReadingUtils::isBlacklisted(flags)
-                        || PatriciaTrieReadingUtils::isNotAWord(flags),
-                mergedNodeCodePointCount, mergedNodeCodePoints);
-    }
-    return siblingPos;
-}
-
-const WordProperty PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
-            false /* forceLowerCaseSearch */);
-    if (ptNodePos == NOT_A_DICT_POS) {
-        AKLOGE("getWordProperty was called for invalid word.");
-        return WordProperty();
-    }
-    const PtNodeParams ptNodeParams =
-            mPtNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
-            ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
-    // Fetch bigram information.
-    std::vector<BigramProperty> bigrams;
-    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
-    int bigramWord1CodePoints[MAX_WORD_LENGTH];
-    BinaryDictionaryBigramsIterator bigramsIt(&mBigramListPolicy, bigramListPos);
-    while (bigramsIt.hasNext()) {
-        // Fetch the next bigram information and forward the iterator.
-        bigramsIt.next();
-        // Skip the entry if the entry has been deleted. This never happens for ver2 dicts.
-        if (bigramsIt.getBigramPos() != NOT_A_DICT_POS) {
-            int word1Probability = NOT_A_PROBABILITY;
-            const int word1CodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-                    bigramsIt.getBigramPos(), MAX_WORD_LENGTH, bigramWord1CodePoints,
-                    &word1Probability);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + word1CodePointCount);
-            const int probability = getProbability(word1Probability, bigramsIt.getProbability());
-            bigrams.emplace_back(&word1, probability,
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */);
-        }
-    }
-    // Fetch shortcut information.
-    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-    int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
-    if (shortcutPos != NOT_A_DICT_POS) {
-        int shortcutTargetCodePoints[MAX_WORD_LENGTH];
-        ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(mDictRoot, &shortcutPos);
-        bool hasNext = true;
-        while (hasNext) {
-            const ShortcutListReadingUtils::ShortcutFlags shortcutFlags =
-                    ShortcutListReadingUtils::getFlagsAndForwardPointer(mDictRoot, &shortcutPos);
-            hasNext = ShortcutListReadingUtils::hasNext(shortcutFlags);
-            const int shortcutTargetLength = ShortcutListReadingUtils::readShortcutTarget(
-                    mDictRoot, MAX_WORD_LENGTH, shortcutTargetCodePoints, &shortcutPos);
-            const std::vector<int> shortcutTarget(shortcutTargetCodePoints,
-                    shortcutTargetCodePoints + shortcutTargetLength);
-            const int shortcutProbability =
-                    ShortcutListReadingUtils::getProbabilityFromFlags(shortcutFlags);
-            shortcuts.emplace_back(&shortcutTarget, shortcutProbability);
-        }
-    }
-    const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
-            ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
-            NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
-    return WordProperty(&codePointVector, &unigramProperty, &bigrams);
-}
-
-int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
-        int *const outCodePointCount) {
-    *outCodePointCount = 0;
-    if (token == 0) {
-        // Start iterating the dictionary.
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
-                &mTerminalPtNodePositionsForIteratingWords);
-        DynamicPtReadingHelper readingHelper(&mPtNodeReader, &mPtNodeArrayReader);
-        readingHelper.initWithPtNodeArrayPos(getRootPosition());
-        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
-    }
-    const int terminalPtNodePositionsVectorSize =
-            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
-    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
-        AKLOGE("Given token %d is invalid.", token);
-        return 0;
-    }
-    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
-    int unigramProbability = NOT_A_PROBABILITY;
-    *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(terminalPtNodePos,
-            MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
-    const int nextToken = token + 1;
-    if (nextToken >= terminalPtNodePositionsVectorSize) {
-        // All words have been iterated.
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        return 0;
-    }
-    return nextToken;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
deleted file mode 100644
index 70351d1..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h
+++ /dev/null
@@ -1,167 +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.
- */
-
-#ifndef LATINIME_PATRICIA_TRIE_POLICY_H
-#define LATINIME_PATRICIA_TRIE_POLICY_H
-
-#include <cstdint>
-#include <vector>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v2/bigram/bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-class DicNode;
-class DicNodeVector;
-
-class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
- public:
-    PatriciaTriePolicy(MmappedBuffer::MmappedBufferPtr mmappedBuffer)
-            : mMmappedBuffer(std::move(mmappedBuffer)),
-              mHeaderPolicy(mMmappedBuffer->getReadOnlyByteArrayView().data(),
-                      FormatUtils::VERSION_2),
-              mDictRoot(mMmappedBuffer->getReadOnlyByteArrayView().data()
-                      + mHeaderPolicy.getSize()),
-              mDictBufferSize(mMmappedBuffer->getReadOnlyByteArrayView().size()
-                      - mHeaderPolicy.getSize()),
-              mBigramListPolicy(mDictRoot, mDictBufferSize), mShortcutListPolicy(mDictRoot),
-              mPtNodeReader(mDictRoot, mDictBufferSize, &mBigramListPolicy, &mShortcutListPolicy),
-              mPtNodeArrayReader(mDictRoot, mDictBufferSize),
-              mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {}
-
-    AK_FORCE_INLINE int getRootPosition() const {
-        return 0;
-    }
-
-    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
-            DicNodeVector *const childDicNodes) const;
-
-    int getCodePointsAndProbabilityAndReturnCodePointCount(
-            const int terminalNodePos, const int maxCodePointCount, int *const outCodePoints,
-            int *const outUnigramProbability) const;
-
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
-
-    int getProbability(const int unigramProbability, const int bigramProbability) const;
-
-    int getProbabilityOfPtNode(const int *const prevWordsPtNodePos, const int ptNodePos) const;
-
-    void iterateNgramEntries(const int *const prevWordsPtNodePos,
-            NgramListener *const listener) const;
-
-    int getShortcutPositionOfPtNode(const int ptNodePos) const;
-
-    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
-        return &mHeaderPolicy;
-    }
-
-    const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const {
-        return &mShortcutListPolicy;
-    }
-
-    bool addUnigramEntry(const int *const word, const int length,
-            const UnigramProperty *const unigramProperty) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool removeUnigramEntry(const int *const word, const int length) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const BigramProperty *const bigramProperty) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word,
-            const int length) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool flush(const char *const filePath) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: flush() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool flushWithGC(const char *const filePath) {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    bool needsToRunGC(const bool mindsBlockByGC) const {
-        // This method should not be called for non-updatable dictionary.
-        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
-        return false;
-    }
-
-    void getProperty(const char *const query, const int queryLength, char *const outResult,
-            const int maxResultLength) {
-        // getProperty is not supported for this class.
-        if (maxResultLength > 0) {
-            outResult[0] = '\0';
-        }
-    }
-
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
-
-    int getNextWordAndNextToken(const int token, int *const outCodePoints,
-            int *const outCodePointCount);
-
-    bool isCorrupted() const {
-        return mIsCorrupted;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(PatriciaTriePolicy);
-
-    const MmappedBuffer::MmappedBufferPtr mMmappedBuffer;
-    const HeaderPolicy mHeaderPolicy;
-    const uint8_t *const mDictRoot;
-    const int mDictBufferSize;
-    const BigramListPolicy mBigramListPolicy;
-    const ShortcutListPolicy mShortcutListPolicy;
-    const Ver2ParticiaTrieNodeReader mPtNodeReader;
-    const Ver2PtNodeArrayReader mPtNodeArrayReader;
-    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
-    mutable bool mIsCorrupted;
-
-    int getBigramsPositionOfPtNode(const int ptNodePos) const;
-    int createAndGetLeavingChildNode(const DicNode *const dicNode, const int ptNodePos,
-            DicNodeVector *const childDicNodes) const;
-};
-} // namespace latinime
-#endif // LATINIME_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h
deleted file mode 100644
index 8e16ccc..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/shortcut/shortcut_list_policy.h
+++ /dev/null
@@ -1,73 +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.
- */
-
-#ifndef LATINIME_SHORTCUT_LIST_POLICY_H
-#define LATINIME_SHORTCUT_LIST_POLICY_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
-
-namespace latinime {
-
-class ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
- public:
-    explicit ShortcutListPolicy(const uint8_t *const shortcutBuf)
-            : mShortcutsBuf(shortcutBuf) {}
-
-    ~ShortcutListPolicy() {}
-
-    int getStartPos(const int pos) const {
-        if (pos == NOT_A_DICT_POS) {
-            return NOT_A_DICT_POS;
-        }
-        int listPos = pos;
-        ShortcutListReadingUtils::getShortcutListSizeAndForwardPointer(mShortcutsBuf, &listPos);
-        return listPos;
-    }
-
-    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
-            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
-            int *const pos) const {
-        const ShortcutListReadingUtils::ShortcutFlags flags =
-                ShortcutListReadingUtils::getFlagsAndForwardPointer(mShortcutsBuf, pos);
-        if (outHasNext) {
-            *outHasNext = ShortcutListReadingUtils::hasNext(flags);
-        }
-        if (outIsWhitelist) {
-            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(flags);
-        }
-        if (outCodePoint) {
-            *outCodePointCount = ShortcutListReadingUtils::readShortcutTarget(
-                        mShortcutsBuf, maxCodePointCount, outCodePoint, pos);
-        }
-    }
-
-    void skipAllShortcuts(int *const pos) const {
-        const int shortcutListSize = ShortcutListReadingUtils
-                ::getShortcutListSizeAndForwardPointer(mShortcutsBuf, pos);
-        *pos += shortcutListSize;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ShortcutListPolicy);
-
-    const uint8_t *const mShortcutsBuf;
-};
-} // namespace latinime
-#endif // LATINIME_SHORTCUT_LIST_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
deleted file mode 100644
index c1e9387..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-
-namespace latinime {
-
-const PtNodeParams Ver2ParticiaTrieNodeReader::fetchPtNodeParamsInBufferFromPtNodePos(
-        const int ptNodePos) const {
-    if (ptNodePos < 0 || ptNodePos >= mDictSize) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
-                ptNodePos, mDictSize);
-        ASSERT(false);
-        return PtNodeParams();
-    }
-    PatriciaTrieReadingUtils::NodeFlags flags;
-    int mergedNodeCodePointCount = 0;
-    int mergedNodeCodePoints[MAX_WORD_LENGTH];
-    int probability = NOT_A_PROBABILITY;
-    int childrenPos = NOT_A_DICT_POS;
-    int shortcutPos = NOT_A_DICT_POS;
-    int bigramPos = NOT_A_DICT_POS;
-    int siblingPos = NOT_A_DICT_POS;
-    PatriciaTrieReadingUtils::readPtNodeInfo(mDictBuffer, ptNodePos, mShortuctPolicy,
-            mBigramPolicy, &flags, &mergedNodeCodePointCount, mergedNodeCodePoints, &probability,
-            &childrenPos, &shortcutPos, &bigramPos, &siblingPos);
-    if (mergedNodeCodePointCount <= 0) {
-        AKLOGE("Empty PtNode is not allowed. Code point count: %d", mergedNodeCodePointCount);
-        ASSERT(false);
-        return PtNodeParams();
-    }
-    return PtNodeParams(ptNodePos, flags, mergedNodeCodePointCount, mergedNodeCodePoints,
-            probability, childrenPos, shortcutPos, bigramPos, siblingPos);
-}
-
-}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
deleted file mode 100644
index f0725b6..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_patricia_trie_node_reader.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H
-#define LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
-
-namespace latinime {
-
-class DictionaryBigramsStructurePolicy;
-class DictionaryShortcutsStructurePolicy;
-
-class Ver2ParticiaTrieNodeReader : public PtNodeReader {
- public:
-    Ver2ParticiaTrieNodeReader(const uint8_t *const dictBuffer, const int dictSize,
-            const DictionaryBigramsStructurePolicy *const bigramPolicy,
-            const DictionaryShortcutsStructurePolicy *const shortcutPolicy)
-            : mDictBuffer(dictBuffer), mDictSize(dictSize), mBigramPolicy(bigramPolicy),
-              mShortuctPolicy(shortcutPolicy) {}
-
-    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const;
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver2ParticiaTrieNodeReader);
-
-    const uint8_t *const mDictBuffer;
-    const int mDictSize;
-    const DictionaryBigramsStructurePolicy *const mBigramPolicy;
-    const DictionaryShortcutsStructurePolicy *const mShortuctPolicy;
-};
-} // namespace latinime
-#endif /* LATINIME_VER2_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.cpp
deleted file mode 100644
index b46617d..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-
-namespace latinime {
-
-bool Ver2PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
-    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mDictSize) {
-        // Reading invalid position because of a bug or a broken dictionary.
-        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
-                ptNodeArrayPos, mDictSize);
-        ASSERT(false);
-        return false;
-    }
-    int readingPos = ptNodeArrayPos;
-    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-            mDictBuffer, &readingPos);
-    *outPtNodeCount = ptNodeCountInArray;
-    *outFirstPtNodePos = readingPos;
-    return true;
-}
-
-bool Ver2PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-        int *const outNextPtNodeArrayPos) const {
-    if (forwordLinkPos < 0 || forwordLinkPos >= mDictSize) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
-                forwordLinkPos, mDictSize);
-        ASSERT(false);
-        return false;
-    }
-    // Ver2 dicts don't have forward links.
-    *outNextPtNodeArrayPos = NOT_A_DICT_POS;
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h
deleted file mode 100644
index 5482721..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/ver2_pt_node_array_reader.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_VER2_PT_NODE_ARRAY_READER_H
-#define LATINIME_VER2_PT_NODE_ARRAY_READER_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h"
-
-namespace latinime {
-
-class Ver2PtNodeArrayReader : public PtNodeArrayReader {
- public:
-    Ver2PtNodeArrayReader(const uint8_t *const dictBuffer, const int dictSize)
-            : mDictBuffer(dictBuffer), mDictSize(dictSize) {};
-
-    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
-    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-            int *const outNextPtNodeArrayPos) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver2PtNodeArrayReader);
-
-    const uint8_t *const mDictBuffer;
-    const int mDictSize;
-};
-} // namespace latinime
-#endif /* LATINIME_VER2_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
deleted file mode 100644
index 08dc107..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.cpp
+++ /dev/null
@@ -1,282 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/bigram/bigram_list_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-
-void Ver4BigramListPolicy::getNextBigram(int *const outBigramPos, int *const outProbability,
-        bool *const outHasNext, int *const bigramEntryPos) const {
-    const BigramEntry bigramEntry =
-            mBigramDictContent->getBigramEntryAndAdvancePosition(bigramEntryPos);
-    if (outBigramPos) {
-        // Lookup target PtNode position.
-        *outBigramPos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-    }
-    if (outProbability) {
-        if (bigramEntry.hasHistoricalInfo()) {
-            *outProbability =
-                    ForgettingCurveUtils::decodeProbability(bigramEntry.getHistoricalInfo(),
-                            mHeaderPolicy);
-        } else {
-            *outProbability = bigramEntry.getProbability();
-        }
-    }
-    if (outHasNext) {
-        *outHasNext = bigramEntry.hasNext();
-    }
-}
-
-bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId,
-        const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) {
-    // 1. The word has no bigrams yet.
-    // 2. The word has bigrams, and there is the target in the list.
-    // 3. The word has bigrams, and there is an invalid entry that can be reclaimed.
-    // 4. The word has bigrams. We have to append new bigram entry to the list.
-    // 5. Same as 4, but the list is the last entry of the content file.
-    if (outAddedNewEntry) {
-        *outAddedNewEntry = false;
-    }
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Case 1. PtNode that doesn't have a bigram list.
-        // Create new bigram list.
-        if (!mBigramDictContent->createNewBigramList(terminalId)) {
-            return false;
-        }
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry,
-                bigramProperty);
-        // Write an entry.
-        int writingPos =  mBigramDictContent->getBigramListHeadPos(terminalId);
-        if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite,
-                &writingPos)) {
-            AKLOGE("Cannot write bigram entry. pos: %d.", writingPos);
-            return false;
-        }
-        if (!mBigramDictContent->writeTerminator(writingPos)) {
-            AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos);
-            return false;
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    int tailEntryPos = NOT_A_DICT_POS;
-    const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos,
-            &tailEntryPos);
-    if (entryPosToUpdate == NOT_A_DICT_POS) {
-        // Case 4, 5. Add new entry to the bigram list.
-        const int contentTailPos = mBigramDictContent->getContentTailPos();
-        // If the tail entry is at the tail of content buffer, the new entry can be written without
-        // link (Case 5).
-        const bool canAppendEntry =
-                contentTailPos == tailEntryPos + mBigramDictContent->getBigramEntrySize();
-        const int newEntryPos = canAppendEntry ? tailEntryPos : contentTailPos;
-        int writingPos = newEntryPos;
-        // Write new entry at the tail position of the bigram content.
-        const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                newTargetTerminalId);
-        const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-                &newBigramEntry, bigramProperty);
-        if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite,
-                &writingPos)) {
-            AKLOGE("Cannot write bigram entry. pos: %d.", writingPos);
-            return false;
-        }
-        if (!mBigramDictContent->writeTerminator(writingPos)) {
-            AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos);
-            return false;
-        }
-        if (!canAppendEntry) {
-            // Update link of the current tail entry.
-            if (!mBigramDictContent->writeLink(newEntryPos, tailEntryPos)) {
-                AKLOGE("Cannot update bigram entry link. pos: %d, linked entry pos: %d.",
-                        tailEntryPos, newEntryPos);
-                return false;
-            }
-        }
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-        return true;
-    }
-
-    // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry.
-    const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (!originalBigramEntry.isValid()) {
-        // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing
-        // entry is updated.
-        if (outAddedNewEntry) {
-            *outAddedNewEntry = true;
-        }
-    }
-    const BigramEntry updatedBigramEntry =
-            originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId);
-    const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(
-            &updatedBigramEntry, bigramProperty);
-    return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return false;
-    }
-    const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos,
-            nullptr /* outTailEntryPos */);
-    if (entryPosToUpdate == NOT_A_DICT_POS) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate);
-    if (targetTerminalId != bigramEntry.getTargetTerminalId()) {
-        // Bigram entry doesn't exist.
-        return false;
-    }
-    // Remove bigram entry by marking it as invalid entry and overwriting the original entry.
-    const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-    return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate);
-}
-
-bool Ver4BigramListPolicy::updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-        int *const outBigramCount) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return true;
-    }
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        const int entryPos = readingPos - mBigramDictContent->getBigramEntrySize();
-        hasNext = bigramEntry.hasNext();
-        if (!bigramEntry.isValid()) {
-            continue;
-        }
-        const int targetPtNodePos = mTerminalPositionLookupTable->getTerminalPtNodePosition(
-                bigramEntry.getTargetTerminalId());
-        if (targetPtNodePos == NOT_A_DICT_POS) {
-            // Invalidate bigram entry.
-            const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-            if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                return false;
-            }
-        } else if (bigramEntry.hasHistoricalInfo()) {
-            const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
-                    bigramEntry.getHistoricalInfo(), mHeaderPolicy);
-            if (ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy)) {
-                const BigramEntry updatedBigramEntry =
-                        bigramEntry.updateHistoricalInfoAndGetEntry(&historicalInfo);
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-                *outBigramCount += 1;
-            } else {
-                // Remove entry.
-                const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry();
-                if (!mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPos)) {
-                    return false;
-                }
-            }
-        } else {
-            *outBigramCount += 1;
-        }
-    }
-    return true;
-}
-
-int Ver4BigramListPolicy::getBigramEntryConut(const int terminalId) {
-    const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId);
-    if (bigramListPos == NOT_A_DICT_POS) {
-        // Bigram list doesn't exist.
-        return 0;
-    }
-    int bigramCount = 0;
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    while (hasNext) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = bigramEntry.hasNext();
-        if (bigramEntry.isValid()) {
-            bigramCount++;
-        }
-    }
-    return bigramCount;
-}
-
-int Ver4BigramListPolicy::getEntryPosToUpdate(const int targetTerminalIdToFind,
-        const int bigramListPos, int *const outTailEntryPos) const {
-    if (outTailEntryPos) {
-        *outTailEntryPos = NOT_A_DICT_POS;
-    }
-    int invalidEntryPos = NOT_A_DICT_POS;
-    int readingPos = bigramListPos;
-    while (true) {
-        const BigramEntry bigramEntry =
-                mBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        const int entryPos = readingPos - mBigramDictContent->getBigramEntrySize();
-        if (!bigramEntry.hasNext()) {
-            if (outTailEntryPos) {
-                *outTailEntryPos = entryPos;
-            }
-            break;
-        }
-        if (bigramEntry.getTargetTerminalId() == targetTerminalIdToFind) {
-            // Entry with same target is found.
-            return entryPos;
-        } else if (!bigramEntry.isValid()) {
-            // Invalid entry that can be reused is found.
-            invalidEntryPos = entryPos;
-        }
-    }
-    return invalidEntryPos;
-}
-
-const BigramEntry Ver4BigramListPolicy::createUpdatedBigramEntryFrom(
-        const BigramEntry *const originalBigramEntry,
-        const BigramProperty *const bigramProperty) const {
-    // TODO: Consolidate historical info and probability.
-    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(bigramProperty->getTimestamp(),
-                bigramProperty->getLevel(), bigramProperty->getCount());
-        const HistoricalInfo updatedHistoricalInfo =
-                ForgettingCurveUtils::createUpdatedHistoricalInfo(
-                        originalBigramEntry->getHistoricalInfo(), bigramProperty->getProbability(),
-                        &historicalInfoForUpdate, mHeaderPolicy);
-        return originalBigramEntry->updateHistoricalInfoAndGetEntry(&updatedHistoricalInfo);
-    } else {
-        return originalBigramEntry->updateProbabilityAndGetEntry(bigramProperty->getProbability());
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
deleted file mode 100644
index 4b3bb37..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h
+++ /dev/null
@@ -1,72 +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.
- */
-
-#ifndef LATINIME_VER4_BIGRAM_LIST_POLICY_H
-#define LATINIME_VER4_BIGRAM_LIST_POLICY_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_bigrams_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h"
-
-namespace latinime {
-
-class BigramDictContent;
-class BigramProperty;
-class HeaderPolicy;
-class TerminalPositionLookupTable;
-
-class Ver4BigramListPolicy : public DictionaryBigramsStructurePolicy {
- public:
-    Ver4BigramListPolicy(BigramDictContent *const bigramDictContent,
-            const TerminalPositionLookupTable *const terminalPositionLookupTable,
-            const HeaderPolicy *const headerPolicy)
-            : mBigramDictContent(bigramDictContent),
-              mTerminalPositionLookupTable(terminalPositionLookupTable),
-              mHeaderPolicy(headerPolicy) {}
-
-    void getNextBigram(int *const outBigramPos, int *const outProbability,
-            bool *const outHasNext, int *const bigramEntryPos) const;
-
-    bool skipAllBigrams(int *const pos) const {
-        // Do nothing because we don't need to skip bigram lists in ver4 dictionaries.
-        return true;
-    }
-
-    bool addNewEntry(const int terminalId, const int newTargetTerminalId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    bool removeEntry(const int terminalId, const int targetTerminalId);
-
-    bool updateAllBigramEntriesAndDeleteUselessEntries(const int terminalId,
-            int *const outBigramCount);
-
-    int getBigramEntryConut(const int terminalId);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4BigramListPolicy);
-
-    int getEntryPosToUpdate(const int targetTerminalIdToFind, const int bigramListPos,
-            int *const outTailEntryPos) const;
-
-    const BigramEntry createUpdatedBigramEntryFrom(const BigramEntry *const originalBigramEntry,
-            const BigramProperty *const bigramProperty) const;
-
-    BigramDictContent *const mBigramDictContent;
-    const TerminalPositionLookupTable *const mTerminalPositionLookupTable;
-    const HeaderPolicy *const mHeaderPolicy;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_BIGRAM_LIST_POLICY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
deleted file mode 100644
index d7e1952..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.cpp
+++ /dev/null
@@ -1,219 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const int BigramDictContent::INVALID_LINKED_ENTRY_POS = Ver4DictConstants::NOT_A_TERMINAL_ID;
-
-const BigramEntry BigramDictContent::getBigramEntryAndAdvancePosition(
-        int *const bigramEntryPos) const {
-    const BufferWithExtendableBuffer *const bigramListBuffer = getContentBuffer();
-    const int bigramEntryTailPos = (*bigramEntryPos) + getBigramEntrySize();
-    if (*bigramEntryPos < 0 || bigramEntryTailPos > bigramListBuffer->getTailPosition()) {
-        AKLOGE("Invalid bigram entry position. bigramEntryPos: %d, bigramEntryTailPos: %d, "
-                "bufSize: %d", *bigramEntryPos, bigramEntryTailPos,
-                        bigramListBuffer->getTailPosition());
-        ASSERT(false);
-        return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-    const int bigramFlags = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, bigramEntryPos);
-    const bool isLink = (bigramFlags & Ver4DictConstants::BIGRAM_IS_LINK_MASK) != 0;
-    int probability = NOT_A_PROBABILITY;
-    int timestamp = NOT_A_TIMESTAMP;
-    int level = 0;
-    int count = 0;
-    if (mHasHistoricalInfo) {
-        timestamp = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, bigramEntryPos);
-        level = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, bigramEntryPos);
-        count = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, bigramEntryPos);
-    } else {
-        probability = bigramListBuffer->readUintAndAdvancePosition(
-                Ver4DictConstants::PROBABILITY_SIZE, bigramEntryPos);
-    }
-    const int encodedTargetTerminalId = bigramListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, bigramEntryPos);
-    const int targetTerminalId =
-            (encodedTargetTerminalId == Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID) ?
-                    Ver4DictConstants::NOT_A_TERMINAL_ID : encodedTargetTerminalId;
-    if (isLink) {
-        const int linkedEntryPos = targetTerminalId;
-        if (linkedEntryPos == INVALID_LINKED_ENTRY_POS) {
-            // Bigram list terminator is found.
-            return BigramEntry(false /* hasNext */, NOT_A_PROBABILITY,
-                    Ver4DictConstants::NOT_A_TERMINAL_ID);
-        }
-        *bigramEntryPos = linkedEntryPos;
-        return getBigramEntryAndAdvancePosition(bigramEntryPos);
-    }
-    // hasNext is always true because we should continue to read the next entry until the terminator
-    // is found.
-    if (mHasHistoricalInfo) {
-        const HistoricalInfo historicalInfo(timestamp, level, count);
-        return BigramEntry(true /* hasNext */, probability, &historicalInfo, targetTerminalId);
-    } else {
-        return BigramEntry(true /* hasNext */, probability, targetTerminalId);
-    }
-}
-
-bool BigramDictContent::writeBigramEntryAndAdvancePosition(
-        const BigramEntry *const bigramEntryToWrite, int *const entryWritingPos) {
-    return writeBigramEntryAttributesAndAdvancePosition(false /* isLink */,
-            bigramEntryToWrite->getProbability(), bigramEntryToWrite->getTargetTerminalId(),
-            bigramEntryToWrite->getHistoricalInfo()->getTimeStamp(),
-            bigramEntryToWrite->getHistoricalInfo()->getLevel(),
-            bigramEntryToWrite->getHistoricalInfo()->getCount(),
-            entryWritingPos);
-}
-
-bool BigramDictContent::writeBigramEntryAttributesAndAdvancePosition(
-        const bool isLink, const int probability, const int targetTerminalId,
-        const int timestamp, const int level, const int count, int *const entryWritingPos) {
-    BufferWithExtendableBuffer *const bigramListBuffer = getWritableContentBuffer();
-    const int bigramFlags = isLink ? Ver4DictConstants::BIGRAM_IS_LINK_MASK : 0;
-    if (!bigramListBuffer->writeUintAndAdvancePosition(bigramFlags,
-            Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram flags. pos: %d, flags: %x", *entryWritingPos, bigramFlags);
-        return false;
-    }
-    if (mHasHistoricalInfo) {
-        if (!bigramListBuffer->writeUintAndAdvancePosition(timestamp,
-                Ver4DictConstants::TIME_STAMP_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram timestamps. pos: %d, timestamp: %d", *entryWritingPos,
-                    timestamp);
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(level,
-                Ver4DictConstants::WORD_LEVEL_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram level. pos: %d, level: %d", *entryWritingPos,
-                    level);
-            return false;
-        }
-        if (!bigramListBuffer->writeUintAndAdvancePosition(count,
-                Ver4DictConstants::WORD_COUNT_FIELD_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram count. pos: %d, count: %d", *entryWritingPos,
-                    count);
-            return false;
-        }
-    } else {
-        if (!bigramListBuffer->writeUintAndAdvancePosition(probability,
-                Ver4DictConstants::PROBABILITY_SIZE, entryWritingPos)) {
-            AKLOGE("Cannot write bigram probability. pos: %d, probability: %d", *entryWritingPos,
-                    probability);
-            return false;
-        }
-    }
-    const int targetTerminalIdToWrite = (targetTerminalId == Ver4DictConstants::NOT_A_TERMINAL_ID) ?
-            Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID : targetTerminalId;
-    if (!bigramListBuffer->writeUintAndAdvancePosition(targetTerminalIdToWrite,
-            Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE, entryWritingPos)) {
-        AKLOGE("Cannot write bigram target terminal id. pos: %d, target terminal id: %d",
-                *entryWritingPos, targetTerminalId);
-        return false;
-    }
-    return true;
-}
-
-bool BigramDictContent::writeLink(const int linkedEntryPos, const int writingPos) {
-    const int targetTerminalId = linkedEntryPos;
-    int pos = writingPos;
-    return writeBigramEntryAttributesAndAdvancePosition(true /* isLink */,
-            NOT_A_PROBABILITY /* probability */, targetTerminalId, NOT_A_TIMESTAMP, 0 /* level */,
-            0 /* count */, &pos);
-}
-
-bool BigramDictContent::runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const BigramDictContent *const originalBigramDictContent,
-        int *const outBigramEntryCount) {
-    for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-            it != terminalIdMap->end(); ++it) {
-        const int originalBigramListPos =
-                originalBigramDictContent->getBigramListHeadPos(it->first);
-        if (originalBigramListPos == NOT_A_DICT_POS) {
-            // This terminal does not have a bigram list.
-            continue;
-        }
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        int bigramEntryCount = 0;
-        // Copy bigram list with GC from original content.
-        if (!runGCBigramList(originalBigramListPos, originalBigramDictContent, bigramListPos,
-                terminalIdMap, &bigramEntryCount)) {
-            AKLOGE("Cannot complete GC for the bigram list. original pos: %d, pos: %d",
-                    originalBigramListPos, bigramListPos);
-            return false;
-        }
-        if (bigramEntryCount == 0) {
-            // All bigram entries are useless. This terminal does not have a bigram list.
-            continue;
-        }
-        *outBigramEntryCount += bigramEntryCount;
-        // Set bigram list position to the lookup table.
-        if (!getUpdatableAddressLookupTable()->set(it->second, bigramListPos)) {
-            AKLOGE("Cannot set bigram list position. terminal id: %d, pos: %d",
-                    it->second, bigramListPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-// Returns whether GC for the bigram list was succeeded or not.
-bool BigramDictContent::runGCBigramList(const int bigramListPos,
-        const BigramDictContent *const sourceBigramDictContent, const int toPos,
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        int *const outEntryCount) {
-    bool hasNext = true;
-    int readingPos = bigramListPos;
-    int writingPos = toPos;
-    while (hasNext) {
-        const BigramEntry originalBigramEntry =
-                sourceBigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-        hasNext = originalBigramEntry.hasNext();
-        if (!originalBigramEntry.isValid()) {
-            continue;
-        }
-        TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
-                terminalIdMap->find(originalBigramEntry.getTargetTerminalId());
-        if (it == terminalIdMap->end()) {
-            // Target word has been removed.
-            continue;
-        }
-        const BigramEntry updatedBigramEntry =
-                originalBigramEntry.updateTargetTerminalIdAndGetEntry(it->second);
-        if (!writeBigramEntryAndAdvancePosition(&updatedBigramEntry, &writingPos)) {
-            AKLOGE("Cannot write bigram entry to run GC. pos: %d", writingPos);
-            return false;
-        }
-        *outEntryCount += 1;
-    }
-    if (*outEntryCount > 0) {
-        if (!writeTerminator(writingPos)) {
-            AKLOGE("Cannot write terminator to run GC. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
deleted file mode 100644
index 361dd2c..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h
+++ /dev/null
@@ -1,128 +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.
- */
-
-#ifndef LATINIME_BIGRAM_DICT_CONTENT_H
-#define LATINIME_BIGRAM_DICT_CONTENT_H
-
-#include <cstdint>
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-
-namespace latinime {
-
-class BigramDictContent : public SparseTableDictContent {
- public:
-    BigramDictContent(uint8_t *const *buffers, const int *bufferSizes, const bool hasHistoricalInfo)
-            : SparseTableDictContent(buffers, bufferSizes,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    BigramDictContent(const bool hasHistoricalInfo)
-            : SparseTableDictContent(Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE),
-              mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    int getContentTailPos() const {
-        return getContentBuffer()->getTailPosition();
-    }
-
-    const BigramEntry getBigramEntry(const int bigramEntryPos) const {
-        int readingPos = bigramEntryPos;
-        return getBigramEntryAndAdvancePosition(&readingPos);
-    }
-
-    const BigramEntry getBigramEntryAndAdvancePosition(int *const bigramEntryPos) const;
-
-    // Returns head position of bigram list for a PtNode specified by terminalId.
-    int getBigramListHeadPos(const int terminalId) const {
-        const SparseTable *const addressLookupTable = getAddressLookupTable();
-        if (!addressLookupTable->contains(terminalId)) {
-            return NOT_A_DICT_POS;
-        }
-        return addressLookupTable->get(terminalId);
-    }
-
-    bool writeBigramEntryAtTail(const BigramEntry *const bigramEntryToWrite) {
-        int writingPos = getContentBuffer()->getTailPosition();
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntry(const BigramEntry *const bigramEntryToWrite, const int entryWritingPos) {
-        int writingPos = entryWritingPos;
-        return writeBigramEntryAndAdvancePosition(bigramEntryToWrite, &writingPos);
-    }
-
-    bool writeBigramEntryAndAdvancePosition(const BigramEntry *const bigramEntryToWrite,
-            int *const entryWritingPos);
-
-    bool writeTerminator(const int writingPos) {
-        // Terminator is a link to the invalid position.
-        return writeLink(INVALID_LINKED_ENTRY_POS, writingPos);
-    }
-
-    bool writeLink(const int linkedPos, const int writingPos);
-
-    bool createNewBigramList(const int terminalId) {
-        const int bigramListPos = getContentBuffer()->getTailPosition();
-        return getUpdatableAddressLookupTable()->set(terminalId, bigramListPos);
-    }
-
-    bool flushToFile(FILE *const file) const {
-        return flush(file);
-    }
-
-    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const BigramDictContent *const originalBigramDictContent,
-            int *const outBigramEntryCount);
-
-    int getBigramEntrySize() const {
-        if (mHasHistoricalInfo) {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::TIME_STAMP_FIELD_SIZE
-                    + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                    + Ver4DictConstants::WORD_COUNT_FIELD_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        } else {
-            return Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE
-                    + Ver4DictConstants::PROBABILITY_SIZE
-                    + Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-        }
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(BigramDictContent);
-
-    static const int INVALID_LINKED_ENTRY_POS;
-
-    bool writeBigramEntryAttributesAndAdvancePosition(
-            const bool isLink, const int probability, const int targetTerminalId,
-            const int timestamp, const int level, const int count, int *const entryWritingPos);
-
-    bool runGCBigramList(const int bigramListPos,
-            const BigramDictContent *const sourceBigramDictContent, const int toPos,
-            const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            int *const outEntryCount);
-
-    bool mHasHistoricalInfo;
-};
-} // namespace latinime
-#endif /* LATINIME_BIGRAM_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
deleted file mode 100644
index 2b0cbd9..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/bigram_entry.h
+++ /dev/null
@@ -1,99 +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.
- */
-
-#ifndef LATINIME_BIGRAM_ENTRY_H
-#define LATINIME_BIGRAM_ENTRY_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-
-class BigramEntry {
- public:
-    BigramEntry(const BigramEntry& bigramEntry)
-            : mHasNext(bigramEntry.mHasNext), mProbability(bigramEntry.mProbability),
-              mHistoricalInfo(), mTargetTerminalId(bigramEntry.mTargetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(),
-              mTargetTerminalId(targetTerminalId) {}
-
-    // Entry with historical information.
-    BigramEntry(const bool hasNext, const int probability,
-            const HistoricalInfo *const historicalInfo, const int targetTerminalId)
-            : mHasNext(hasNext), mProbability(probability), mHistoricalInfo(*historicalInfo),
-              mTargetTerminalId(targetTerminalId) {}
-
-    const BigramEntry getInvalidatedEntry() const {
-        return updateTargetTerminalIdAndGetEntry(Ver4DictConstants::NOT_A_TERMINAL_ID);
-    }
-
-    const BigramEntry updateHasNextAndGetEntry(const bool hasNext) const {
-        return BigramEntry(hasNext, mProbability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateTargetTerminalIdAndGetEntry(const int newTargetTerminalId) const {
-        return BigramEntry(mHasNext, mProbability, &mHistoricalInfo, newTargetTerminalId);
-    }
-
-    const BigramEntry updateProbabilityAndGetEntry(const int probability) const {
-        return BigramEntry(mHasNext, probability, &mHistoricalInfo, mTargetTerminalId);
-    }
-
-    const BigramEntry updateHistoricalInfoAndGetEntry(
-            const HistoricalInfo *const historicalInfo) const {
-        return BigramEntry(mHasNext, mProbability, historicalInfo, mTargetTerminalId);
-    }
-
-    bool isValid() const {
-        return mTargetTerminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
-    }
-
-    bool hasNext() const {
-        return mHasNext;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    bool hasHistoricalInfo() const {
-        return mHistoricalInfo.isValid();
-    }
-
-    const HistoricalInfo *getHistoricalInfo() const {
-        return &mHistoricalInfo;
-    }
-
-    int getTargetTerminalId() const {
-        return mTargetTerminalId;
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_DEFAULT_CONSTRUCTOR(BigramEntry);
-    DISALLOW_ASSIGNMENT_OPERATOR(BigramEntry);
-
-    const bool mHasNext;
-    const int mProbability;
-    const HistoricalInfo mHistoricalInfo;
-    const int mTargetTerminalId;
-};
-} // namespace latinime
-#endif /* LATINIME_BIGRAM_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
deleted file mode 100644
index 5dc91ba..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h"
-
-namespace latinime {
-
-bool LanguageModelDictContent::save(FILE *const file) const {
-    return mTrieMap.save(file);
-}
-
-bool LanguageModelDictContent::runGC(
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const LanguageModelDictContent *const originalContent,
-        int *const outNgramCount) {
-    return runGCInner(terminalIdMap, originalContent->mTrieMap.getEntriesInRootLevel(),
-            0 /* nextLevelBitmapEntryIndex */, outNgramCount);
-}
-
-ProbabilityEntry LanguageModelDictContent::getNgramProbabilityEntry(
-        const WordIdArrayView prevWordIds, const int wordId) const {
-    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
-    if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
-        return ProbabilityEntry();
-    }
-    const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndex);
-    if (!result.mIsValid) {
-        // Not found.
-        return ProbabilityEntry();
-    }
-    return ProbabilityEntry::decode(result.mValue, mHasHistoricalInfo);
-}
-
-bool LanguageModelDictContent::setNgramProbabilityEntry(const WordIdArrayView prevWordIds,
-        const int terminalId, const ProbabilityEntry *const probabilityEntry) {
-    const int bitmapEntryIndex = getBitmapEntryIndex(prevWordIds);
-    if (bitmapEntryIndex == TrieMap::INVALID_INDEX) {
-        return false;
-    }
-    return mTrieMap.put(terminalId, probabilityEntry->encode(mHasHistoricalInfo), bitmapEntryIndex);
-}
-
-bool LanguageModelDictContent::runGCInner(
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const TrieMap::TrieMapRange trieMapRange,
-        const int nextLevelBitmapEntryIndex, int *const outNgramCount) {
-    for (auto &entry : trieMapRange) {
-        const auto it = terminalIdMap->find(entry.key());
-        if (it == terminalIdMap->end() || it->second == Ver4DictConstants::NOT_A_TERMINAL_ID) {
-            // The word has been removed.
-            continue;
-        }
-        if (!mTrieMap.put(it->second, entry.value(), nextLevelBitmapEntryIndex)) {
-            return false;
-        }
-        if (outNgramCount) {
-            *outNgramCount += 1;
-        }
-        if (entry.hasNextLevelMap()) {
-            if (!runGCInner(terminalIdMap, entry.getEntriesInNextLevel(),
-                    mTrieMap.getNextLevelBitmapEntryIndex(it->second, nextLevelBitmapEntryIndex),
-                    outNgramCount)) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-int LanguageModelDictContent::getBitmapEntryIndex(const WordIdArrayView prevWordIds) const {
-    int bitmapEntryIndex = mTrieMap.getRootBitmapEntryIndex();
-    for (const int wordId : prevWordIds) {
-        const TrieMap::Result result = mTrieMap.get(wordId, bitmapEntryIndex);
-        if (!result.mIsValid) {
-            return TrieMap::INVALID_INDEX;
-        }
-        bitmapEntryIndex = result.mNextLevelBitmapEntryIndex;
-    }
-    return bitmapEntryIndex;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
deleted file mode 100644
index 18f2e01..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H
-#define LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H
-
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/trie_map.h"
-#include "utils/byte_array_view.h"
-#include "utils/int_array_view.h"
-
-namespace latinime {
-
-/**
- * Class representing language model.
- *
- * This class provides methods to get and store unigram/n-gram probability information and flags.
- */
-class LanguageModelDictContent {
- public:
-    LanguageModelDictContent(const ReadWriteByteArrayView trieMapBuffer,
-            const bool hasHistoricalInfo)
-            : mTrieMap(trieMapBuffer), mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    explicit LanguageModelDictContent(const bool hasHistoricalInfo)
-            : mTrieMap(), mHasHistoricalInfo(hasHistoricalInfo) {}
-
-    bool isNearSizeLimit() const {
-        return mTrieMap.isNearSizeLimit();
-    }
-
-    bool save(FILE *const file) const;
-
-    bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const LanguageModelDictContent *const originalContent,
-            int *const outNgramCount);
-
-    ProbabilityEntry getProbabilityEntry(const int wordId) const {
-        return getNgramProbabilityEntry(WordIdArrayView(), wordId);
-    }
-
-    bool setProbabilityEntry(const int wordId, const ProbabilityEntry *const probabilityEntry) {
-        return setNgramProbabilityEntry(WordIdArrayView(), wordId, probabilityEntry);
-    }
-
-    ProbabilityEntry getNgramProbabilityEntry(const WordIdArrayView prevWordIds,
-            const int wordId) const;
-
-    bool setNgramProbabilityEntry(const WordIdArrayView prevWordIds, const int wordId,
-            const ProbabilityEntry *const probabilityEntry);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(LanguageModelDictContent);
-
-    TrieMap mTrieMap;
-    const bool mHasHistoricalInfo;
-
-    bool runGCInner(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-            const TrieMap::TrieMapRange trieMapRange, const int nextLevelBitmapEntryIndex,
-            int *const outNgramCount);
-
-    int getBitmapEntryIndex(const WordIdArrayView prevWordIds) const;
-};
-} // namespace latinime
-#endif /* LATINIME_LANGUAGE_MODEL_DICT_CONTENT_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
deleted file mode 100644
index feff6b5..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h
+++ /dev/null
@@ -1,131 +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.
- */
-
-#ifndef LATINIME_PROBABILITY_ENTRY_H
-#define LATINIME_PROBABILITY_ENTRY_H
-
-#include <climits>
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-
-class ProbabilityEntry {
- public:
-    ProbabilityEntry(const ProbabilityEntry &probabilityEntry)
-            : mFlags(probabilityEntry.mFlags), mProbability(probabilityEntry.mProbability),
-              mHistoricalInfo(probabilityEntry.mHistoricalInfo) {}
-
-    // Dummy entry
-    ProbabilityEntry()
-            : mFlags(0), mProbability(NOT_A_PROBABILITY), mHistoricalInfo() {}
-
-    // Entry without historical information
-    ProbabilityEntry(const int flags, const int probability)
-            : mFlags(flags), mProbability(probability), mHistoricalInfo() {}
-
-    // Entry with historical information.
-    ProbabilityEntry(const int flags, const int probability,
-            const HistoricalInfo *const historicalInfo)
-            : mFlags(flags), mProbability(probability), mHistoricalInfo(*historicalInfo) {}
-
-    const ProbabilityEntry createEntryWithUpdatedProbability(const int probability) const {
-        return ProbabilityEntry(mFlags, probability, &mHistoricalInfo);
-    }
-
-    const ProbabilityEntry createEntryWithUpdatedHistoricalInfo(
-            const HistoricalInfo *const historicalInfo) const {
-        return ProbabilityEntry(mFlags, mProbability, historicalInfo);
-    }
-
-    bool hasHistoricalInfo() const {
-        return mHistoricalInfo.isValid();
-    }
-
-    int getFlags() const {
-        return mFlags;
-    }
-
-    int getProbability() const {
-        return mProbability;
-    }
-
-    const HistoricalInfo *getHistoricalInfo() const {
-        return &mHistoricalInfo;
-    }
-
-    uint64_t encode(const bool hasHistoricalInfo) const {
-        uint64_t encodedEntry = static_cast<uint64_t>(mFlags);
-        if (hasHistoricalInfo) {
-            encodedEntry = (encodedEntry << (Ver4DictConstants::TIME_STAMP_FIELD_SIZE * CHAR_BIT))
-                    ^ static_cast<uint64_t>(mHistoricalInfo.getTimeStamp());
-            encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_LEVEL_FIELD_SIZE * CHAR_BIT))
-                    ^ static_cast<uint64_t>(mHistoricalInfo.getLevel());
-            encodedEntry = (encodedEntry << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT))
-                    ^ static_cast<uint64_t>(mHistoricalInfo.getCount());
-        } else {
-            encodedEntry = (encodedEntry << (Ver4DictConstants::PROBABILITY_SIZE * CHAR_BIT))
-                    ^ static_cast<uint64_t>(mProbability);
-        }
-        return encodedEntry;
-    }
-
-    static ProbabilityEntry decode(const uint64_t encodedEntry, const bool hasHistoricalInfo) {
-        if (hasHistoricalInfo) {
-            const int flags = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
-                    Ver4DictConstants::TIME_STAMP_FIELD_SIZE
-                            + Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                            + Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
-            const int timestamp = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::TIME_STAMP_FIELD_SIZE,
-                    Ver4DictConstants::WORD_LEVEL_FIELD_SIZE
-                            + Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
-            const int level = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::WORD_LEVEL_FIELD_SIZE,
-                    Ver4DictConstants::WORD_COUNT_FIELD_SIZE);
-            const int count = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::WORD_COUNT_FIELD_SIZE, 0 /* pos */);
-            const HistoricalInfo historicalInfo(timestamp, level, count);
-            return ProbabilityEntry(flags, NOT_A_PROBABILITY, &historicalInfo);
-        } else {
-            const int flags = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE,
-                    Ver4DictConstants::PROBABILITY_SIZE);
-            const int probability = readFromEncodedEntry(encodedEntry,
-                    Ver4DictConstants::PROBABILITY_SIZE, 0 /* pos */);
-            return ProbabilityEntry(flags, probability);
-        }
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(ProbabilityEntry);
-
-    const int mFlags;
-    const int mProbability;
-    const HistoricalInfo mHistoricalInfo;
-
-    static int readFromEncodedEntry(const uint64_t encodedEntry, const int size, const int pos) {
-        return static_cast<int>(
-                (encodedEntry >> (pos * CHAR_BIT)) & ((1ull << (size * CHAR_BIT)) - 1));
-    }
-};
-} // namespace latinime
-#endif /* LATINIME_PROBABILITY_ENTRY_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp
deleted file mode 100644
index 41d9c54..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.cpp
+++ /dev/null
@@ -1,182 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-void ShortcutDictContent::getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
-        int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
-        bool *const outhasNext, int *const shortcutEntryPos) const {
-    const BufferWithExtendableBuffer *const shortcutListBuffer = getContentBuffer();
-    if (*shortcutEntryPos < 0 || *shortcutEntryPos >=  shortcutListBuffer->getTailPosition()) {
-        AKLOGE("Invalid shortcut entry position. shortcutEntryPos: %d, bufSize: %d",
-                *shortcutEntryPos, shortcutListBuffer->getTailPosition());
-        ASSERT(false);
-        if (outhasNext) {
-            *outhasNext = false;
-        }
-        if (outCodePointCount) {
-            *outCodePointCount = 0;
-        }
-        return;
-    }
-
-    const int shortcutFlags = shortcutListBuffer->readUintAndAdvancePosition(
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-    if (outProbability) {
-        *outProbability = shortcutFlags & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK;
-    }
-    if (outhasNext) {
-        *outhasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
-    }
-    if (outCodePoint && outCodePointCount) {
-        shortcutListBuffer->readCodePointsAndAdvancePosition(
-                maxCodePointCount, outCodePoint, outCodePointCount, shortcutEntryPos);
-    }
-}
-
-int ShortcutDictContent::getShortcutListHeadPos(const int terminalId) const {
-    const SparseTable *const addressLookupTable = getAddressLookupTable();
-    if (!addressLookupTable->contains(terminalId)) {
-        return NOT_A_DICT_POS;
-    }
-    return addressLookupTable->get(terminalId);
-}
-
-bool ShortcutDictContent::runGC(
-        const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-        const ShortcutDictContent *const originalShortcutDictContent) {
-   for (TerminalPositionLookupTable::TerminalIdMap::const_iterator it = terminalIdMap->begin();
-           it != terminalIdMap->end(); ++it) {
-       const int originalShortcutListPos =
-               originalShortcutDictContent->getShortcutListHeadPos(it->first);
-       if (originalShortcutListPos == NOT_A_DICT_POS) {
-           continue;
-       }
-       const int shortcutListPos = getContentBuffer()->getTailPosition();
-       // Copy shortcut list from original content.
-       if (!copyShortcutListFromDictContent(originalShortcutListPos, originalShortcutDictContent,
-               shortcutListPos)) {
-           AKLOGE("Cannot copy shortcut list during GC. original pos: %d, pos: %d",
-                   originalShortcutListPos, shortcutListPos);
-           return false;
-       }
-       // Set shortcut list position to the lookup table.
-       if (!getUpdatableAddressLookupTable()->set(it->second, shortcutListPos)) {
-           AKLOGE("Cannot set shortcut list position. terminal id: %d, pos: %d",
-                   it->second, shortcutListPos);
-           return false;
-       }
-   }
-   return true;
-}
-
-bool ShortcutDictContent::createNewShortcutList(const int terminalId) {
-    const int shortcutListListPos = getContentBuffer()->getTailPosition();
-    return getUpdatableAddressLookupTable()->set(terminalId, shortcutListListPos);
-}
-
-bool ShortcutDictContent::copyShortcutList(const int shortcutListPos, const int toPos) {
-    return copyShortcutListFromDictContent(shortcutListPos, this, toPos);
-}
-
-bool ShortcutDictContent::copyShortcutListFromDictContent(const int shortcutListPos,
-        const ShortcutDictContent *const sourceShortcutDictContent, const int toPos) {
-    bool hasNext = true;
-    int readingPos = shortcutListPos;
-    int writingPos = toPos;
-    int codePoints[MAX_WORD_LENGTH];
-    while (hasNext) {
-        int probability = 0;
-        int codePointCount = 0;
-        sourceShortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH,
-                codePoints, &codePointCount, &probability, &hasNext, &readingPos);
-        if (!writeShortcutEntryAndAdvancePosition(codePoints, codePointCount, probability,
-                hasNext, &writingPos)) {
-            AKLOGE("Cannot write shortcut entry to copy. pos: %d", writingPos);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool ShortcutDictContent::setProbability(const int probability, const int shortcutEntryPos) {
-    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
-    const int shortcutFlags = shortcutListBuffer->readUint(
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-    const bool hasNext = shortcutFlags & Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK;
-    const int shortcutFlagsToWrite = createAndGetShortcutFlags(probability, hasNext);
-    return shortcutListBuffer->writeUint(shortcutFlagsToWrite,
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos);
-}
-
-bool ShortcutDictContent::writeShortcutEntryAndAdvancePosition(const int *const codePoint,
-        const int codePointCount, const int probability, const bool hasNext,
-        int *const shortcutEntryPos) {
-    BufferWithExtendableBuffer *const shortcutListBuffer = getWritableContentBuffer();
-    const int shortcutFlags = createAndGetShortcutFlags(probability, hasNext);
-    if (!shortcutListBuffer->writeUintAndAdvancePosition(shortcutFlags,
-            Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE, shortcutEntryPos)) {
-        AKLOGE("Cannot write shortcut flags. flags; %x, pos: %d", shortcutFlags, *shortcutEntryPos);
-        return false;
-    }
-    if (!shortcutListBuffer->writeCodePointsAndAdvancePosition(codePoint, codePointCount,
-            true /* writesTerminator */, shortcutEntryPos)) {
-        AKLOGE("Cannot write shortcut target code points. pos: %d", *shortcutEntryPos);
-        return false;
-    }
-    return true;
-}
-
-// Find a shortcut entry that has specified target and return its position.
-int ShortcutDictContent::findShortcutEntryAndGetPos(const int shortcutListPos,
-        const int *const targetCodePointsToFind, const int codePointCount) const {
-    bool hasNext = true;
-    int readingPos = shortcutListPos;
-    int targetCodePoints[MAX_WORD_LENGTH];
-    while (hasNext) {
-        const int entryPos = readingPos;
-        int probability = 0;
-        int targetCodePointCount = 0;
-        getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, targetCodePoints, &targetCodePointCount,
-                &probability, &hasNext, &readingPos);
-        if (targetCodePointCount != codePointCount) {
-            continue;
-        }
-        bool matched = true;
-        for (int i = 0; i < codePointCount; ++i) {
-            if (targetCodePointsToFind[i] != targetCodePoints[i]) {
-                matched = false;
-                break;
-            }
-        }
-        if (matched) {
-            return entryPos;
-        }
-    }
-    return NOT_A_DICT_POS;
-}
-
-int ShortcutDictContent::createAndGetShortcutFlags(const int probability,
-        const bool hasNext) const {
-    return (probability & Ver4DictConstants::SHORTCUT_PROBABILITY_MASK)
-            | (hasNext ? Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK : 0);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h
deleted file mode 100644
index 7b12aff..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h
+++ /dev/null
@@ -1,92 +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.
- */
-
-#ifndef LATINIME_SHORTCUT_DICT_CONTENT_H
-#define LATINIME_SHORTCUT_DICT_CONTENT_H
-
-#include <cstdint>
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-
-namespace latinime {
-
-class ShortcutDictContent : public SparseTableDictContent {
- public:
-    ShortcutDictContent(uint8_t *const *buffers, const int *bufferSizes)
-            : SparseTableDictContent(buffers, bufferSizes,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
-
-    ShortcutDictContent()
-            : SparseTableDictContent(Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE,
-                      Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE) {}
-
-    void getShortcutEntry(const int maxCodePointCount, int *const outCodePoint,
-            int *const outCodePointCount, int *const outProbability, bool *const outhasNext,
-            const int shortcutEntryPos) {
-        int readingPos = shortcutEntryPos;
-        return getShortcutEntryAndAdvancePosition(maxCodePointCount, outCodePoint,
-                outCodePointCount, outProbability, outhasNext, &readingPos);
-    }
-
-    void getShortcutEntryAndAdvancePosition(const int maxCodePointCount,
-            int *const outCodePoint, int *const outCodePointCount, int *const outProbability,
-            bool *const outhasNext, int *const shortcutEntryPos) const;
-
-   // Returns head position of shortcut list for a PtNode specified by terminalId.
-   int getShortcutListHeadPos(const int terminalId) const;
-
-   bool flushToFile(FILE *const file) const {
-       return flush(file);
-   }
-
-   bool runGC(const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap,
-           const ShortcutDictContent *const originalShortcutDictContent);
-
-   bool createNewShortcutList(const int terminalId);
-
-   bool copyShortcutList(const int shortcutListPos, const int toPos);
-
-   bool setProbability(const int probability, const int shortcutEntryPos);
-
-   bool writeShortcutEntry(const int *const codePoint, const int codePointCount,
-           const int probability, const bool hasNext, const int shortcutEntryPos) {
-       int writingPos = shortcutEntryPos;
-       return writeShortcutEntryAndAdvancePosition(codePoint, codePointCount, probability,
-               hasNext, &writingPos);
-   }
-
-   bool writeShortcutEntryAndAdvancePosition(const int *const codePoint,
-           const int codePointCount, const int probability, const bool hasNext,
-           int *const shortcutEntryPos);
-
-   int findShortcutEntryAndGetPos(const int shortcutListPos,
-           const int *const targetCodePointsToFind, const int codePointCount) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(ShortcutDictContent);
-
-    bool copyShortcutListFromDictContent(const int shortcutListPos,
-            const ShortcutDictContent *const sourceShortcutDictContent, const int toPos);
-
-    int createAndGetShortcutFlags(const int probability, const bool hasNext) const;
-};
-} // namespace latinime
-#endif /* LATINIME_SHORTCUT_DICT_CONTENT_H */
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
deleted file mode 100644
index 9217741..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h
+++ /dev/null
@@ -1,65 +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.
- */
-
-#ifndef LATINIME_SINGLE_DICT_CONTENT_H
-#define LATINIME_SINGLE_DICT_CONTENT_H
-
-#include <cstdint>
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-class SingleDictContent {
- public:
-    SingleDictContent(uint8_t *const buffer, const int bufferSize)
-            : mExpandableContentBuffer(ReadWriteByteArrayView(buffer, bufferSize),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
-
-    SingleDictContent()
-            : mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE) {}
-
-    virtual ~SingleDictContent() {}
-
-    bool isNearSizeLimit() const {
-        return mExpandableContentBuffer.isNearSizeLimit();
-    }
-
- protected:
-    BufferWithExtendableBuffer *getWritableBuffer() {
-        return &mExpandableContentBuffer;
-    }
-
-    const BufferWithExtendableBuffer *getBuffer() const {
-        return &mExpandableContentBuffer;
-    }
-
-    bool flush(FILE *const file) const {
-        return DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableContentBuffer);
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(SingleDictContent);
-
-    BufferWithExtendableBuffer mExpandableContentBuffer;
-};
-} // namespace latinime
-#endif /* LATINIME_SINGLE_DICT_CONTENT_H */
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
deleted file mode 100644
index 896ce6b..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.cpp
+++ /dev/null
@@ -1,40 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h"
-
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-
-namespace latinime {
-
-const int SparseTableDictContent::LOOKUP_TABLE_BUFFER_INDEX = 0;
-const int SparseTableDictContent::ADDRESS_TABLE_BUFFER_INDEX = 1;
-const int SparseTableDictContent::CONTENT_BUFFER_INDEX = 2;
-
-bool SparseTableDictContent::flush(FILE *const file) const {
-    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableLookupTableBuffer)) {
-        return false;
-    }
-    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableAddressTableBuffer)) {
-        return false;
-    }
-    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableContentBuffer)) {
-        return false;
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
deleted file mode 100644
index c98dd11..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/sparse_table_dict_content.h
+++ /dev/null
@@ -1,98 +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.
- */
-
-#ifndef LATINIME_SPARSE_TABLE_DICT_CONTENT_H
-#define LATINIME_SPARSE_TABLE_DICT_CONTENT_H
-
-#include <cstdint>
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/sparse_table.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-// TODO: Support multiple contents.
-class SparseTableDictContent {
- public:
-    AK_FORCE_INLINE SparseTableDictContent(uint8_t *const *buffers, const int *bufferSizes,
-            const int sparseTableBlockSize, const int sparseTableDataSize)
-            : mExpandableLookupTableBuffer(
-                      ReadWriteByteArrayView(buffers[LOOKUP_TABLE_BUFFER_INDEX],
-                              bufferSizes[LOOKUP_TABLE_BUFFER_INDEX]),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mExpandableAddressTableBuffer(
-                      ReadWriteByteArrayView(buffers[ADDRESS_TABLE_BUFFER_INDEX],
-                              bufferSizes[ADDRESS_TABLE_BUFFER_INDEX]),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mExpandableContentBuffer(
-                      ReadWriteByteArrayView(buffers[CONTENT_BUFFER_INDEX],
-                              bufferSizes[CONTENT_BUFFER_INDEX]),
-                      BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
-                      sparseTableBlockSize, sparseTableDataSize) {}
-
-    SparseTableDictContent(const int sparseTableBlockSize, const int sparseTableDataSize)
-            : mExpandableLookupTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mExpandableAddressTableBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mExpandableContentBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-              mAddressLookupTable(&mExpandableLookupTableBuffer, &mExpandableAddressTableBuffer,
-                      sparseTableBlockSize, sparseTableDataSize) {}
-
-    virtual ~SparseTableDictContent() {}
-
-    bool isNearSizeLimit() const {
-        return mExpandableLookupTableBuffer.isNearSizeLimit()
-                || mExpandableAddressTableBuffer.isNearSizeLimit()
-                || mExpandableContentBuffer.isNearSizeLimit();
-    }
-
- protected:
-    SparseTable *getUpdatableAddressLookupTable() {
-        return &mAddressLookupTable;
-    }
-
-    const SparseTable *getAddressLookupTable() const {
-        return &mAddressLookupTable;
-    }
-
-    BufferWithExtendableBuffer *getWritableContentBuffer() {
-        return &mExpandableContentBuffer;
-    }
-
-    const BufferWithExtendableBuffer *getContentBuffer() const {
-        return &mExpandableContentBuffer;
-    }
-
-    bool flush(FILE *const file) const;
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTableDictContent);
-
-    static const int LOOKUP_TABLE_BUFFER_INDEX;
-    static const int ADDRESS_TABLE_BUFFER_INDEX;
-    static const int CONTENT_BUFFER_INDEX;
-
-    BufferWithExtendableBuffer mExpandableLookupTableBuffer;
-    BufferWithExtendableBuffer mExpandableAddressTableBuffer;
-    BufferWithExtendableBuffer mExpandableContentBuffer;
-    SparseTable mAddressLookupTable;
-};
-} // namespace latinime
-#endif /* LATINIME_SPARSE_TABLE_DICT_CONTENT_H */
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
deleted file mode 100644
index cf238ee..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.cpp
+++ /dev/null
@@ -1,99 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-int TerminalPositionLookupTable::getTerminalPtNodePosition(const int terminalId) const {
-    if (terminalId < 0 || terminalId >= mSize) {
-        return NOT_A_DICT_POS;
-    }
-    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;
-}
-
-bool TerminalPositionLookupTable::setTerminalPtNodePosition(
-        const int terminalId, const int terminalPtNodePos) {
-    if (terminalId < 0) {
-        return NOT_A_DICT_POS;
-    }
-    while (terminalId >= mSize) {
-        // Write new entry.
-        if (!getWritableBuffer()->writeUint(Ver4DictConstants::NOT_A_TERMINAL_ADDRESS,
-                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(mSize))) {
-            return false;
-        }
-        mSize++;
-    }
-    const int terminalPos = (terminalPtNodePos != NOT_A_DICT_POS) ?
-            terminalPtNodePos : Ver4DictConstants::NOT_A_TERMINAL_ADDRESS;
-    return getWritableBuffer()->writeUint(terminalPos,
-            Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(terminalId));
-}
-
-bool TerminalPositionLookupTable::flushToFile(FILE *const file) 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)) {
-                AKLOGE("Cannot set terminal position to lookupTableToWrite."
-                        " terminalId: %d, position: %d", i, terminalPtNodePosition);
-                return false;
-            }
-        }
-        return lookupTableToWrite.flush(file);
-    } else {
-        // We can simply use this lookup table because the buffer size has not been
-        // changed.
-        return flush(file);
-    }
-}
-
-bool TerminalPositionLookupTable::runGCTerminalIds(TerminalIdMap *const terminalIdMap) {
-    int removedEntryCount = 0;
-    int nextNewTerminalId = 0;
-    for (int i = 0; i < mSize; ++i) {
-        const int terminalPos = getBuffer()->readUint(
-                Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE, getEntryPos(i));
-        if (terminalPos == Ver4DictConstants::NOT_A_TERMINAL_ADDRESS) {
-            // This entry is a garbage.
-            removedEntryCount++;
-        } else {
-            // Give a new terminal id to the entry.
-            if (!getWritableBuffer()->writeUint(terminalPos,
-                    Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE,
-                    getEntryPos(nextNewTerminalId))) {
-                return false;
-            }
-            // Memorize the mapping to the old terminal id to the new terminal id.
-            terminalIdMap->insert(TerminalIdMap::value_type(i, nextNewTerminalId));
-            nextNewTerminalId++;
-        }
-    }
-    mSize = nextNewTerminalId;
-    return true;
-}
-
-} // namespace latinime
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
deleted file mode 100644
index b2262bf..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h
+++ /dev/null
@@ -1,63 +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.
- */
-
-#ifndef LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
-#define LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
-
-#include <cstdint>
-#include <cstdio>
-#include <unordered_map>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/single_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-
-namespace latinime {
-
-class TerminalPositionLookupTable : public SingleDictContent {
- public:
-    typedef std::unordered_map<int, int> TerminalIdMap;
-
-    TerminalPositionLookupTable(uint8_t *const buffer, const int bufferSize)
-            : SingleDictContent(buffer, bufferSize),
-              mSize(getBuffer()->getTailPosition()
-                      / Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE) {}
-
-    TerminalPositionLookupTable() : mSize(0) {}
-
-    int getTerminalPtNodePosition(const int terminalId) const;
-
-    bool setTerminalPtNodePosition(const int terminalId, const int terminalPtNodePos);
-
-    int getNextTerminalId() const {
-        return mSize;
-    }
-
-    bool flushToFile(FILE *const file) const;
-
-    bool runGCTerminalIds(TerminalIdMap *const terminalIdMap);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(TerminalPositionLookupTable);
-
-    int getEntryPos(const int terminalId) const {
-        return terminalId * Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
-    }
-
-    int mSize;
-};
-} // namespace latinime
-#endif // LATINIME_TERMINAL_POSITION_LOOKUP_TABLE_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
deleted file mode 100644
index 7902735..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h
+++ /dev/null
@@ -1,106 +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.
- */
-
-#ifndef LATINIME_VER4_SHORTCUT_LIST_POLICY_H
-#define LATINIME_VER4_SHORTCUT_LIST_POLICY_H
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_shortcuts_structure_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/shortcut/shortcut_list_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-
-namespace latinime {
-
-class Ver4ShortcutListPolicy : public DictionaryShortcutsStructurePolicy {
- public:
-    Ver4ShortcutListPolicy(ShortcutDictContent *const shortcutDictContent,
-            const TerminalPositionLookupTable *const terminalPositionLookupTable)
-            : mShortcutDictContent(shortcutDictContent) {}
-
-    ~Ver4ShortcutListPolicy() {}
-
-    int getStartPos(const int pos) const {
-        // The first shortcut entry is located at the head position of the shortcut list.
-        return pos;
-    }
-
-    void getNextShortcut(const int maxCodePointCount, int *const outCodePoint,
-            int *const outCodePointCount, bool *const outIsWhitelist, bool *const outHasNext,
-            int *const pos) const {
-        int probability = 0;
-        mShortcutDictContent->getShortcutEntryAndAdvancePosition(maxCodePointCount,
-                outCodePoint, outCodePointCount, &probability, outHasNext, pos);
-        if (outIsWhitelist) {
-            *outIsWhitelist = ShortcutListReadingUtils::isWhitelist(probability);
-        }
-    }
-
-    void skipAllShortcuts(int *const pos) const {
-        // Do nothing because we don't need to skip shortcut lists in ver4 dictionaries.
-    }
-
-    bool addNewShortcut(const int terminalId, const int *const codePoints, const int codePointCount,
-            const int probability) {
-        const int shortcutListPos = mShortcutDictContent->getShortcutListHeadPos(terminalId);
-        if (shortcutListPos == NOT_A_DICT_POS) {
-            // Create shortcut list.
-            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
-                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
-                return false;
-            }
-            const int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
-            return mShortcutDictContent->writeShortcutEntry(codePoints, codePointCount, probability,
-                    false /* hasNext */, writingPos);
-        }
-        const int entryPos = mShortcutDictContent->findShortcutEntryAndGetPos(shortcutListPos,
-                codePoints, codePointCount);
-        if (entryPos == NOT_A_DICT_POS) {
-            // Add new entry to the shortcut list.
-            // Create new shortcut list.
-            if (!mShortcutDictContent->createNewShortcutList(terminalId)) {
-                AKLOGE("Cannot create new shortcut list. terminal id: %d", terminalId);
-                return false;
-            }
-            int writingPos =  mShortcutDictContent->getShortcutListHeadPos(terminalId);
-            if (!mShortcutDictContent->writeShortcutEntryAndAdvancePosition(codePoints,
-                    codePointCount, probability, true /* hasNext */, &writingPos)) {
-                AKLOGE("Cannot write shortcut entry. terminal id: %d, pos: %d", terminalId,
-                        writingPos);
-                return false;
-            }
-            return mShortcutDictContent->copyShortcutList(shortcutListPos, writingPos);
-        }
-        // Overwrite existing entry.
-        bool hasNext = false;
-        mShortcutDictContent->getShortcutEntry(MAX_WORD_LENGTH, 0 /* outCodePoint */,
-                0 /* outCodePointCount */ , 0 /* probability */, &hasNext, entryPos);
-        if (!mShortcutDictContent->writeShortcutEntry(codePoints,
-                codePointCount, probability, hasNext, entryPos)) {
-            AKLOGE("Cannot overwrite shortcut entry. terminal id: %d, pos: %d", terminalId,
-                    entryPos);
-            return false;
-        }
-        return true;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4ShortcutListPolicy);
-
-    ShortcutDictContent *const mShortcutDictContent;
-};
-} // namespace latinime
-#endif // LATINIME_VER4_SHORTCUT_LIST_POLICY_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
deleted file mode 100644
index 3c8008d..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.cpp
+++ /dev/null
@@ -1,214 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-
-#include <cerrno>
-#include <cstring>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <vector>
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-/* static */ Ver4DictBuffers::Ver4DictBuffersPtr Ver4DictBuffers::openVer4DictBuffers(
-        const char *const dictPath, MmappedBuffer::MmappedBufferPtr &&headerBuffer,
-        const FormatUtils::FORMAT_VERSION formatVersion) {
-    if (!headerBuffer) {
-        ASSERT(false);
-        AKLOGE("The header buffer must be valid to open ver4 dict buffers.");
-        return Ver4DictBuffersPtr(nullptr);
-    }
-    // TODO: take only dictDirPath, and open both header and trie files in the constructor below
-    const bool isUpdatable = headerBuffer->isUpdatable();
-    MmappedBuffer::MmappedBufferPtr bodyBuffer = MmappedBuffer::openBuffer(dictPath,
-            Ver4DictConstants::BODY_FILE_EXTENSION, isUpdatable);
-    if (!bodyBuffer) {
-        return Ver4DictBuffersPtr(nullptr);
-    }
-    std::vector<uint8_t *> buffers;
-    std::vector<int> bufferSizes;
-    const ReadWriteByteArrayView buffer = bodyBuffer->getReadWriteByteArrayView();
-    int position = 0;
-    while (position < static_cast<int>(buffer.size())) {
-        const int bufferSize = ByteArrayUtils::readUint32AndAdvancePosition(
-                buffer.data(), &position);
-        const ReadWriteByteArrayView subBuffer = buffer.subView(position, bufferSize);
-        buffers.push_back(subBuffer.data());
-        bufferSizes.push_back(subBuffer.size());
-        position += bufferSize;
-        if (bufferSize < 0 || position < 0 || position > static_cast<int>(buffer.size())) {
-            AKLOGE("The dict body file is corrupted.");
-            return Ver4DictBuffersPtr(nullptr);
-        }
-    }
-    if (buffers.size() != Ver4DictConstants::NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE) {
-        AKLOGE("The dict body file is corrupted.");
-        return Ver4DictBuffersPtr(nullptr);
-    }
-    return Ver4DictBuffersPtr(new Ver4DictBuffers(std::move(headerBuffer), std::move(bodyBuffer),
-            formatVersion, buffers, bufferSizes));
-}
-
-bool Ver4DictBuffers::flushHeaderAndDictBuffers(const char *const dictDirPath,
-        const BufferWithExtendableBuffer *const headerBuffer) const {
-    // Create temporary directory.
-    const int tmpDirPathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictDirPath,
-            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE);
-    char tmpDirPath[tmpDirPathBufSize];
-    FileUtils::getFilePathWithSuffix(dictDirPath,
-            DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE, tmpDirPathBufSize,
-            tmpDirPath);
-    if (FileUtils::existsDir(tmpDirPath)) {
-        if (!FileUtils::removeDirAndFiles(tmpDirPath)) {
-            AKLOGE("Existing directory %s cannot be removed.", tmpDirPath);
-            ASSERT(false);
-            return false;
-        }
-    }
-    umask(S_IWGRP | S_IWOTH);
-    if (mkdir(tmpDirPath, S_IRWXU) == -1) {
-        AKLOGE("Cannot create directory: %s. errno: %d.", tmpDirPath, errno);
-        return false;
-    }
-    // Get dictionary base path.
-    const int dictNameBufSize = strlen(dictDirPath) + 1 /* terminator */;
-    char dictName[dictNameBufSize];
-    FileUtils::getBasename(dictDirPath, dictNameBufSize, dictName);
-    const int dictPathBufSize = FileUtils::getFilePathBufSize(tmpDirPath, dictName);
-    char dictPath[dictPathBufSize];
-    FileUtils::getFilePath(tmpDirPath, dictName, dictPathBufSize, dictPath);
-
-    // Write header file.
-    if (!DictFileWritingUtils::flushBufferToFileWithSuffix(dictPath,
-            Ver4DictConstants::HEADER_FILE_EXTENSION, headerBuffer)) {
-        AKLOGE("Dictionary header file %s%s cannot be written.", tmpDirPath,
-                Ver4DictConstants::HEADER_FILE_EXTENSION);
-        return false;
-    }
-
-    // Write body file.
-    const int bodyFilePathBufSize = FileUtils::getFilePathWithSuffixBufSize(dictPath,
-            Ver4DictConstants::BODY_FILE_EXTENSION);
-    char bodyFilePath[bodyFilePathBufSize];
-    FileUtils::getFilePathWithSuffix(dictPath, Ver4DictConstants::BODY_FILE_EXTENSION,
-            bodyFilePathBufSize, bodyFilePath);
-
-    const int fd = open(bodyFilePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-    if (fd == -1) {
-        AKLOGE("File %s cannot be opened. errno: %d", bodyFilePath, errno);
-        ASSERT(false);
-        return false;
-    }
-    FILE *const file = fdopen(fd, "wb");
-    if (!file) {
-        AKLOGE("fdopen failed for the file %s. errno: %d", bodyFilePath, errno);
-        ASSERT(false);
-        return false;
-    }
-
-    if (!flushDictBuffers(file)) {
-        fclose(file);
-        return false;
-    }
-    fclose(file);
-    // Remove existing dictionary.
-    if (!FileUtils::removeDirAndFiles(dictDirPath)) {
-        AKLOGE("Existing directory %s cannot be removed.", dictDirPath);
-        ASSERT(false);
-        return false;
-    }
-    // Rename temporary directory.
-    if (rename(tmpDirPath, dictDirPath) != 0) {
-        AKLOGE("%s cannot be renamed to %s", tmpDirPath, dictDirPath);
-        ASSERT(false);
-        return false;
-    }
-    return true;
-}
-
-bool Ver4DictBuffers::flushDictBuffers(FILE *const file) const {
-    // Write trie.
-    if (!DictFileWritingUtils::writeBufferToFileTail(file, &mExpandableTrieBuffer)) {
-        AKLOGE("Trie cannot be written.");
-        return false;
-    }
-    // Write terminal position lookup table.
-    if (!mTerminalPositionLookupTable.flushToFile(file)) {
-        AKLOGE("Terminal position lookup table cannot be written.");
-        return false;
-    }
-    // Write language model content.
-    if (!mLanguageModelDictContent.save(file)) {
-        AKLOGE("Language model dict content cannot be written.");
-        return false;
-    }
-    // Write bigram dict content.
-    if (!mBigramDictContent.flushToFile(file)) {
-        AKLOGE("Bigram dict content cannot be written.");
-        return false;
-    }
-    // Write shortcut dict content.
-    if (!mShortcutDictContent.flushToFile(file)) {
-        AKLOGE("Shortcut dict content cannot be written.");
-        return false;
-    }
-    return true;
-}
-
-Ver4DictBuffers::Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer,
-        MmappedBuffer::MmappedBufferPtr &&bodyBuffer,
-        const FormatUtils::FORMAT_VERSION formatVersion,
-        const std::vector<uint8_t *> &contentBuffers, const std::vector<int> &contentBufferSizes)
-        : mHeaderBuffer(std::move(headerBuffer)), mDictBuffer(std::move(bodyBuffer)),
-          mHeaderPolicy(mHeaderBuffer->getReadOnlyByteArrayView().data(), formatVersion),
-          mExpandableHeaderBuffer(mHeaderBuffer->getReadWriteByteArrayView(),
-                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-          mExpandableTrieBuffer(
-                  ReadWriteByteArrayView(contentBuffers[Ver4DictConstants::TRIE_BUFFER_INDEX],
-                          contentBufferSizes[Ver4DictConstants::TRIE_BUFFER_INDEX]),
-                  BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE),
-          mTerminalPositionLookupTable(
-                  contentBuffers[Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX],
-                  contentBufferSizes[
-                          Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX]),
-          mLanguageModelDictContent(
-                  ReadWriteByteArrayView(
-                          contentBuffers[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX],
-                          contentBufferSizes[Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX]),
-                  mHeaderPolicy.hasHistoricalInfoOfWords()),
-          mBigramDictContent(&contentBuffers[Ver4DictConstants::BIGRAM_BUFFERS_INDEX],
-                  &contentBufferSizes[Ver4DictConstants::BIGRAM_BUFFERS_INDEX],
-                  mHeaderPolicy.hasHistoricalInfoOfWords()),
-          mShortcutDictContent(&contentBuffers[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX],
-                  &contentBufferSizes[Ver4DictConstants::SHORTCUT_BUFFERS_INDEX]),
-          mIsUpdatable(mDictBuffer->isUpdatable()) {}
-
-Ver4DictBuffers::Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize)
-        : mHeaderBuffer(nullptr), mDictBuffer(nullptr), mHeaderPolicy(headerPolicy),
-          mExpandableHeaderBuffer(Ver4DictConstants::MAX_DICTIONARY_SIZE),
-          mExpandableTrieBuffer(maxTrieSize), mTerminalPositionLookupTable(),
-          mLanguageModelDictContent(headerPolicy->hasHistoricalInfoOfWords()),
-          mBigramDictContent(headerPolicy->hasHistoricalInfoOfWords()), mShortcutDictContent(),
-          mIsUpdatable(true) {}
-
-} // namespace latinime
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
deleted file mode 100644
index 68027dc..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h
+++ /dev/null
@@ -1,144 +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.
- */
-
-#ifndef LATINIME_VER4_DICT_BUFFER_H
-#define LATINIME_VER4_DICT_BUFFER_H
-
-#include <cstdio>
-#include <memory>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/bigram_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/shortcut_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-
-namespace latinime {
-
-class Ver4DictBuffers {
- public:
-    typedef std::unique_ptr<Ver4DictBuffers> Ver4DictBuffersPtr;
-
-    static Ver4DictBuffersPtr openVer4DictBuffers(const char *const dictDirPath,
-            MmappedBuffer::MmappedBufferPtr &&headerBuffer,
-            const FormatUtils::FORMAT_VERSION formatVersion);
-
-    static AK_FORCE_INLINE Ver4DictBuffersPtr createVer4DictBuffers(
-            const HeaderPolicy *const headerPolicy, const int maxTrieSize) {
-        return Ver4DictBuffersPtr(new Ver4DictBuffers(headerPolicy, maxTrieSize));
-    }
-
-    AK_FORCE_INLINE bool isValid() const {
-        return mHeaderBuffer && mDictBuffer && mHeaderPolicy.isValid();
-    }
-
-    AK_FORCE_INLINE bool isNearSizeLimit() const {
-        return mExpandableTrieBuffer.isNearSizeLimit()
-                || mTerminalPositionLookupTable.isNearSizeLimit()
-                || mLanguageModelDictContent.isNearSizeLimit()
-                || mBigramDictContent.isNearSizeLimit()
-                || mShortcutDictContent.isNearSizeLimit();
-    }
-
-    AK_FORCE_INLINE const HeaderPolicy *getHeaderPolicy() const {
-        return &mHeaderPolicy;
-    }
-
-    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableHeaderBuffer() {
-        return &mExpandableHeaderBuffer;
-    }
-
-    AK_FORCE_INLINE BufferWithExtendableBuffer *getWritableTrieBuffer() {
-        return &mExpandableTrieBuffer;
-    }
-
-    AK_FORCE_INLINE const BufferWithExtendableBuffer *getTrieBuffer() const {
-        return &mExpandableTrieBuffer;
-    }
-
-    AK_FORCE_INLINE TerminalPositionLookupTable *getMutableTerminalPositionLookupTable() {
-        return &mTerminalPositionLookupTable;
-    }
-
-    AK_FORCE_INLINE const TerminalPositionLookupTable *getTerminalPositionLookupTable() const {
-        return &mTerminalPositionLookupTable;
-    }
-
-    AK_FORCE_INLINE LanguageModelDictContent *getMutableLanguageModelDictContent() {
-        return &mLanguageModelDictContent;
-    }
-
-    AK_FORCE_INLINE const LanguageModelDictContent *getLanguageModelDictContent() const {
-        return &mLanguageModelDictContent;
-    }
-
-    AK_FORCE_INLINE BigramDictContent *getMutableBigramDictContent() {
-        return &mBigramDictContent;
-    }
-
-    AK_FORCE_INLINE const BigramDictContent *getBigramDictContent() const {
-        return &mBigramDictContent;
-    }
-
-    AK_FORCE_INLINE ShortcutDictContent *getMutableShortcutDictContent() {
-        return &mShortcutDictContent;
-    }
-
-    AK_FORCE_INLINE const ShortcutDictContent *getShortcutDictContent() const {
-        return &mShortcutDictContent;
-    }
-
-    AK_FORCE_INLINE bool isUpdatable() const {
-        return mIsUpdatable;
-    }
-
-    bool flush(const char *const dictDirPath) const {
-        return flushHeaderAndDictBuffers(dictDirPath, &mExpandableHeaderBuffer);
-    }
-
-    bool flushHeaderAndDictBuffers(const char *const dictDirPath,
-            const BufferWithExtendableBuffer *const headerBuffer) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4DictBuffers);
-
-    Ver4DictBuffers(MmappedBuffer::MmappedBufferPtr &&headerBuffer,
-            MmappedBuffer::MmappedBufferPtr &&bodyBuffer,
-            const FormatUtils::FORMAT_VERSION formatVersion,
-            const std::vector<uint8_t *> &contentBuffers,
-            const std::vector<int> &contentBufferSizes);
-
-    Ver4DictBuffers(const HeaderPolicy *const headerPolicy, const int maxTrieSize);
-
-    bool flushDictBuffers(FILE *const file) const;
-
-    const MmappedBuffer::MmappedBufferPtr mHeaderBuffer;
-    const MmappedBuffer::MmappedBufferPtr mDictBuffer;
-    const HeaderPolicy mHeaderPolicy;
-    BufferWithExtendableBuffer mExpandableHeaderBuffer;
-    BufferWithExtendableBuffer mExpandableTrieBuffer;
-    TerminalPositionLookupTable mTerminalPositionLookupTable;
-    LanguageModelDictContent mLanguageModelDictContent;
-    BigramDictContent mBigramDictContent;
-    ShortcutDictContent mShortcutDictContent;
-    const int mIsUpdatable;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_DICT_BUFFER_H */
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
deleted file mode 100644
index 93d4e56..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.cpp
+++ /dev/null
@@ -1,80 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-
-namespace latinime {
-
-const char *const Ver4DictConstants::BODY_FILE_EXTENSION = ".body";
-const char *const Ver4DictConstants::HEADER_FILE_EXTENSION = ".header";
-
-// Version 4 dictionary size is implicitly limited to 8MB due to 3-byte offsets.
-const int Ver4DictConstants::MAX_DICTIONARY_SIZE = 8 * 1024 * 1024;
-// Extended region size, which is not GCed region size in dict file + additional buffer size, is
-// limited to 1MB to prevent from inefficient traversing.
-const int Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE = 1 * 1024 * 1024;
-
-// NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT for Trie and TerminalAddressLookupTable.
-// NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT for language model.
-// NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT for bigram and shortcut.
-const size_t Ver4DictConstants::NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE =
-        NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT * 2
-                + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT
-                + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT * 2;
-const int Ver4DictConstants::TRIE_BUFFER_INDEX = 0;
-const int Ver4DictConstants::TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX =
-        TRIE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
-const int Ver4DictConstants::LANGUAGE_MODEL_BUFFER_INDEX =
-        TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
-const int Ver4DictConstants::BIGRAM_BUFFERS_INDEX =
-        LANGUAGE_MODEL_BUFFER_INDEX + NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
-const int Ver4DictConstants::SHORTCUT_BUFFERS_INDEX =
-        BIGRAM_BUFFERS_INDEX + NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
-
-const int Ver4DictConstants::NOT_A_TERMINAL_ID = -1;
-const int Ver4DictConstants::PROBABILITY_SIZE = 1;
-const int Ver4DictConstants::FLAGS_IN_PROBABILITY_FILE_SIZE = 1;
-const int Ver4DictConstants::TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE = 3;
-const int Ver4DictConstants::NOT_A_TERMINAL_ADDRESS = 0;
-const int Ver4DictConstants::TERMINAL_ID_FIELD_SIZE = 4;
-const int Ver4DictConstants::TIME_STAMP_FIELD_SIZE = 4;
-const int Ver4DictConstants::WORD_LEVEL_FIELD_SIZE = 1;
-const int Ver4DictConstants::WORD_COUNT_FIELD_SIZE = 1;
-
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_BLOCK_SIZE = 16;
-const int Ver4DictConstants::BIGRAM_ADDRESS_TABLE_DATA_SIZE = 4;
-const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE = 64;
-const int Ver4DictConstants::SHORTCUT_ADDRESS_TABLE_DATA_SIZE = 4;
-
-const int Ver4DictConstants::BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE = 3;
-// Unsigned int max value of BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE-byte is used for representing
-// invalid terminal ID in bigram lists.
-const int Ver4DictConstants::INVALID_BIGRAM_TARGET_TERMINAL_ID =
-        (1 << (BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE * 8)) - 1;
-const int Ver4DictConstants::BIGRAM_FLAGS_FIELD_SIZE = 1;
-const int Ver4DictConstants::BIGRAM_PROBABILITY_MASK = 0x0F;
-const int Ver4DictConstants::BIGRAM_IS_LINK_MASK = 0x80;
-const int Ver4DictConstants::BIGRAM_LARGE_PROBABILITY_FIELD_SIZE = 1;
-
-const int Ver4DictConstants::SHORTCUT_FLAGS_FIELD_SIZE = 1;
-const int Ver4DictConstants::SHORTCUT_PROBABILITY_MASK = 0x0F;
-const int Ver4DictConstants::SHORTCUT_HAS_NEXT_MASK = 0x80;
-
-const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT = 1;
-const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT = 3;
-const size_t Ver4DictConstants::NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT = 1;
-
-} // namespace latinime
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
deleted file mode 100644
index 6950ca7..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h
+++ /dev/null
@@ -1,77 +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.
- */
-
-#ifndef LATINIME_VER4_DICT_CONSTANTS_H
-#define LATINIME_VER4_DICT_CONSTANTS_H
-
-#include "defines.h"
-
-#include <cstddef>
-
-namespace latinime {
-
-// TODO: Create PtConstants under the pt_common and move some constant values there.
-// Note that there are corresponding definitions in FormatSpec.java.
-class Ver4DictConstants {
- public:
-    static const char *const BODY_FILE_EXTENSION;
-    static const char *const HEADER_FILE_EXTENSION;
-    static const int MAX_DICTIONARY_SIZE;
-    static const int MAX_DICT_EXTENDED_REGION_SIZE;
-
-    static const size_t NUM_OF_CONTENT_BUFFERS_IN_BODY_FILE;
-    static const int TRIE_BUFFER_INDEX;
-    static const int TERMINAL_ADDRESS_LOOKUP_TABLE_BUFFER_INDEX;
-    static const int LANGUAGE_MODEL_BUFFER_INDEX;
-    static const int BIGRAM_BUFFERS_INDEX;
-    static const int SHORTCUT_BUFFERS_INDEX;
-
-    static const int NOT_A_TERMINAL_ID;
-    static const int PROBABILITY_SIZE;
-    static const int FLAGS_IN_PROBABILITY_FILE_SIZE;
-    static const int TERMINAL_ADDRESS_TABLE_ADDRESS_SIZE;
-    static const int NOT_A_TERMINAL_ADDRESS;
-    static const int TERMINAL_ID_FIELD_SIZE;
-    static const int TIME_STAMP_FIELD_SIZE;
-    static const int WORD_LEVEL_FIELD_SIZE;
-    static const int WORD_COUNT_FIELD_SIZE;
-
-    static const int BIGRAM_ADDRESS_TABLE_BLOCK_SIZE;
-    static const int BIGRAM_ADDRESS_TABLE_DATA_SIZE;
-    static const int SHORTCUT_ADDRESS_TABLE_BLOCK_SIZE;
-    static const int SHORTCUT_ADDRESS_TABLE_DATA_SIZE;
-
-    static const int BIGRAM_FLAGS_FIELD_SIZE;
-    static const int BIGRAM_TARGET_TERMINAL_ID_FIELD_SIZE;
-    static const int INVALID_BIGRAM_TARGET_TERMINAL_ID;
-    static const int BIGRAM_IS_LINK_MASK;
-    static const int BIGRAM_PROBABILITY_MASK;
-    // Used when bigram list has time stamp.
-    static const int BIGRAM_LARGE_PROBABILITY_FIELD_SIZE;
-
-    static const int SHORTCUT_FLAGS_FIELD_SIZE;
-    static const int SHORTCUT_PROBABILITY_MASK;
-    static const int SHORTCUT_HAS_NEXT_MASK;
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4DictConstants);
-
-    static const size_t NUM_OF_BUFFERS_FOR_SINGLE_DICT_CONTENT;
-    static const size_t NUM_OF_BUFFERS_FOR_SPARSE_TABLE_DICT_CONTENT;
-    static const size_t NUM_OF_BUFFERS_FOR_LANGUAGE_MODEL_DICT_CONTENT;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_DICT_CONSTANTS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
deleted file mode 100644
index 731092e..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
+++ /dev/null
@@ -1,99 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-
-const PtNodeParams Ver4PatriciaTrieNodeReader::fetchPtNodeInfoFromBufferAndProcessMovedPtNode(
-        const int ptNodePos, const int siblingNodePos) const {
-    if (ptNodePos < 0 || ptNodePos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Fetching PtNode info from invalid dictionary position: %d, dictionary size: %d",
-                ptNodePos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return PtNodeParams();
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodePos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int pos = ptNodePos;
-    const int headPos = ptNodePos;
-    if (usesAdditionalBuffer) {
-        pos -= mBuffer->getOriginalBufferSize();
-    }
-    const PatriciaTrieReadingUtils::NodeFlags flags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const int parentPosOffset =
-            DynamicPtReadingUtils::getParentPtNodePosOffsetAndAdvancePosition(
-                    dictBuf, &pos);
-    const int parentPos =
-            DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
-    int codePoints[MAX_WORD_LENGTH];
-    const int codePonitCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
-            dictBuf, flags, MAX_WORD_LENGTH, codePoints, &pos);
-    int terminalIdFieldPos = NOT_A_DICT_POS;
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    int probability = NOT_A_PROBABILITY;
-    if (PatriciaTrieReadingUtils::isTerminal(flags)) {
-        terminalIdFieldPos = pos;
-        if (usesAdditionalBuffer) {
-            terminalIdFieldPos += mBuffer->getOriginalBufferSize();
-        }
-        terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
-        // TODO: Quit reading probability here.
-        const ProbabilityEntry probabilityEntry =
-                mLanguageModelDictContent->getProbabilityEntry(terminalId);
-        if (probabilityEntry.hasHistoricalInfo()) {
-            probability = ForgettingCurveUtils::decodeProbability(
-                    probabilityEntry.getHistoricalInfo(), mHeaderPolicy);
-        } else {
-            probability = probabilityEntry.getProbability();
-        }
-    }
-    int childrenPosFieldPos = pos;
-    if (usesAdditionalBuffer) {
-        childrenPosFieldPos += mBuffer->getOriginalBufferSize();
-    }
-    int childrenPos = DynamicPtReadingUtils::readChildrenPositionAndAdvancePosition(
-            dictBuf, &pos);
-    if (usesAdditionalBuffer && childrenPos != NOT_A_DICT_POS) {
-        childrenPos += mBuffer->getOriginalBufferSize();
-    }
-    if (usesAdditionalBuffer) {
-        pos += mBuffer->getOriginalBufferSize();
-    }
-    // Sibling position is the tail position of original PtNode.
-    int newSiblingNodePos = (siblingNodePos == NOT_A_DICT_POS) ? pos : siblingNodePos;
-    // Read destination node if the read node is a moved node.
-    if (DynamicPtReadingUtils::isMoved(flags)) {
-        // The destination position is stored at the same place as the parent position.
-        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
-    } else {
-        return PtNodeParams(headPos, flags, parentPos, codePonitCount, codePoints,
-                terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos,
-                newSiblingNodePos);
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
deleted file mode 100644
index a91ad57..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H
-#define LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_reader.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-class HeaderPolicy;
-class LanguageModelDictContent;
-
-/*
- * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
- * node and reads node attributes including probability form language model.
- */
-class Ver4PatriciaTrieNodeReader : public PtNodeReader {
- public:
-    Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
-            const LanguageModelDictContent *const languageModelDictContent,
-            const HeaderPolicy *const headerPolicy)
-            : mBuffer(buffer), mLanguageModelDictContent(languageModelDictContent),
-              mHeaderPolicy(headerPolicy) {}
-
-    ~Ver4PatriciaTrieNodeReader() {}
-
-    virtual const PtNodeParams fetchPtNodeParamsInBufferFromPtNodePos(const int ptNodePos) const {
-        return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(ptNodePos,
-                NOT_A_DICT_POS /* siblingNodePos */);
-    }
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
-
-    const BufferWithExtendableBuffer *const mBuffer;
-    const LanguageModelDictContent *const mLanguageModelDictContent;
-    const HeaderPolicy *const mHeaderPolicy;
-
-    const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
-            const int siblingNodePos) const;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
deleted file mode 100644
index 857222f..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+++ /dev/null
@@ -1,387 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
-
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
-#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-
-const int Ver4PatriciaTrieNodeWriter::CHILDREN_POSITION_FIELD_SIZE = 3;
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsDeleted(
-        const PtNodeParams *const toBeUpdatedPtNodeParams) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
-                    true /* isDeleted */, false /* willBecomeNonTerminal */);
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    // Update flags.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos)) {
-        return false;
-    }
-    if (toBeUpdatedPtNodeParams->isTerminal()) {
-        // The PtNode is a terminal. Delete entry from the terminal position lookup table.
-        return mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-                toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */);
-    } else {
-        return true;
-    }
-}
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsMoved(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const int movedPos, const int bigramLinkedNodePos) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, true /* isMoved */,
-                    false /* isDeleted */, false /* willBecomeNonTerminal */);
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    // Update flags.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos)) {
-        return false;
-    }
-    // Update moved position, which is stored in the parent offset field.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
-            mTrieBuffer, movedPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
-        return false;
-    }
-    if (toBeUpdatedPtNodeParams->hasChildren()) {
-        // Update children's parent position.
-        mReadingHelper.initWithPtNodeArrayPos(toBeUpdatedPtNodeParams->getChildrenPos());
-        while (!mReadingHelper.isEnd()) {
-            const PtNodeParams childPtNodeParams(mReadingHelper.getPtNodeParams());
-            int parentOffsetFieldPos = childPtNodeParams.getHeadPos()
-                    + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
-            if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(
-                    mTrieBuffer, bigramLinkedNodePos, childPtNodeParams.getHeadPos(),
-                    &parentOffsetFieldPos)) {
-                // Parent offset cannot be written because of a bug or a broken dictionary; thus,
-                // we give up to update dictionary.
-                return false;
-            }
-            mReadingHelper.readNextSiblingNode(childPtNodeParams);
-        }
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::markPtNodeAsWillBecomeNonTerminal(
-        const PtNodeParams *const toBeUpdatedPtNodeParams) {
-    int pos = toBeUpdatedPtNodeParams->getHeadPos();
-    const bool usesAdditionalBuffer = mTrieBuffer->isInAdditionalBuffer(pos);
-    const uint8_t *const dictBuf = mTrieBuffer->getBuffer(usesAdditionalBuffer);
-    if (usesAdditionalBuffer) {
-        pos -= mTrieBuffer->getOriginalBufferSize();
-    }
-    // Read original flags
-    const PatriciaTrieReadingUtils::NodeFlags originalFlags =
-            PatriciaTrieReadingUtils::getFlagsAndAdvancePosition(dictBuf, &pos);
-    const PatriciaTrieReadingUtils::NodeFlags updatedFlags =
-            DynamicPtReadingUtils::updateAndGetFlags(originalFlags, false /* isMoved */,
-                    false /* isDeleted */, true /* willBecomeNonTerminal */);
-    if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-            toBeUpdatedPtNodeParams->getTerminalId(), NOT_A_DICT_POS /* ptNodePos */)) {
-        AKLOGE("Cannot update terminal position lookup table. terminal id: %d",
-                toBeUpdatedPtNodeParams->getTerminalId());
-        return false;
-    }
-    // Update flags.
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos();
-    return DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer, updatedFlags,
-            &writingPos);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeUnigramProperty(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const UnigramProperty *const unigramProperty) {
-    // Update probability and historical information.
-    // TODO: Update other information in the unigram property.
-    if (!toBeUpdatedPtNodeParams->isTerminal()) {
-        return false;
-    }
-    const ProbabilityEntry originalProbabilityEntry =
-            mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
-                    toBeUpdatedPtNodeParams->getTerminalId());
-    const ProbabilityEntry probabilityEntry = createUpdatedEntryFrom(&originalProbabilityEntry,
-            unigramProperty);
-    return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
-            toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-        const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
-    if (!toBeUpdatedPtNodeParams->isTerminal()) {
-        AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
-        return false;
-    }
-    const ProbabilityEntry originalProbabilityEntry =
-            mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
-                    toBeUpdatedPtNodeParams->getTerminalId());
-    if (originalProbabilityEntry.hasHistoricalInfo()) {
-        const HistoricalInfo historicalInfo = ForgettingCurveUtils::createHistoricalInfoToSave(
-                originalProbabilityEntry.getHistoricalInfo(), mHeaderPolicy);
-        const ProbabilityEntry probabilityEntry =
-                originalProbabilityEntry.createEntryWithUpdatedHistoricalInfo(&historicalInfo);
-        if (!mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
-                toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) {
-            AKLOGE("Cannot write updated probability entry. terminalId: %d",
-                    toBeUpdatedPtNodeParams->getTerminalId());
-            return false;
-        }
-        const bool isValid = ForgettingCurveUtils::needsToKeep(&historicalInfo, mHeaderPolicy);
-        if (!isValid) {
-            if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
-                AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
-                return false;
-            }
-        }
-        *outNeedsToKeepPtNode = isValid;
-    } else {
-        // No need to update probability.
-        *outNeedsToKeepPtNode = true;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
-        const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
-    int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
-    return DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
-            newChildrenPosition, &childrenPosFieldPos);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const int newTerminalId) {
-    return mTrieBuffer->writeUint(newTerminalId, Ver4DictConstants::TERMINAL_ID_FIELD_SIZE,
-            toBeUpdatedPtNodeParams->getTerminalIdFieldPos());
-}
-
-bool Ver4PatriciaTrieNodeWriter::writePtNodeAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, int *const ptNodeWritingPos) {
-    return writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, 0 /* outTerminalId */,
-            ptNodeWritingPos);
-}
-
-
-bool Ver4PatriciaTrieNodeWriter::writeNewTerminalPtNodeAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, const UnigramProperty *const unigramProperty,
-        int *const ptNodeWritingPos) {
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (!writePtNodeAndGetTerminalIdAndAdvancePosition(ptNodeParams, &terminalId,
-            ptNodeWritingPos)) {
-        return false;
-    }
-    // Write probability.
-    ProbabilityEntry newProbabilityEntry;
-    const ProbabilityEntry probabilityEntryToWrite = createUpdatedEntryFrom(
-            &newProbabilityEntry, unigramProperty);
-    return mBuffers->getMutableLanguageModelDictContent()->setProbabilityEntry(
-            terminalId, &probabilityEntryToWrite);
-}
-
-bool Ver4PatriciaTrieNodeWriter::addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
-        const BigramProperty *const bigramProperty, bool *const outAddedNewBigram) {
-    if (!mBigramPolicy->addNewEntry(prevWordIds[0], wordId, bigramProperty, outAddedNewBigram)) {
-        AKLOGE("Cannot add new bigram entry. terminalId: %d, targetTerminalId: %d",
-                prevWordIds[0], wordId);
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::removeNgramEntry(const WordIdArrayView prevWordIds,
-        const int wordId) {
-    return mBigramPolicy->removeEntry(prevWordIds[0], wordId);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateAllBigramEntriesAndDeleteUselessEntries(
-            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount) {
-    return mBigramPolicy->updateAllBigramEntriesAndDeleteUselessEntries(
-            sourcePtNodeParams->getTerminalId(), outBigramEntryCount);
-}
-
-bool Ver4PatriciaTrieNodeWriter::updateAllPositionFields(
-        const PtNodeParams *const toBeUpdatedPtNodeParams,
-        const DictPositionRelocationMap *const dictPositionRelocationMap,
-        int *const outBigramEntryCount) {
-    int parentPos = toBeUpdatedPtNodeParams->getParentPos();
-    if (parentPos != NOT_A_DICT_POS) {
-        PtNodeWriter::PtNodePositionRelocationMap::const_iterator it =
-                dictPositionRelocationMap->mPtNodePositionRelocationMap.find(parentPos);
-        if (it != dictPositionRelocationMap->mPtNodePositionRelocationMap.end()) {
-            parentPos = it->second;
-        }
-    }
-    int writingPos = toBeUpdatedPtNodeParams->getHeadPos()
-            + DynamicPtWritingUtils::NODE_FLAG_FIELD_SIZE;
-    // Write updated parent offset.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
-            parentPos, toBeUpdatedPtNodeParams->getHeadPos(), &writingPos)) {
-        return false;
-    }
-
-    // Updates children position.
-    int childrenPos = toBeUpdatedPtNodeParams->getChildrenPos();
-    if (childrenPos != NOT_A_DICT_POS) {
-        PtNodeWriter::PtNodeArrayPositionRelocationMap::const_iterator it =
-                dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.find(childrenPos);
-        if (it != dictPositionRelocationMap->mPtNodeArrayPositionRelocationMap.end()) {
-            childrenPos = it->second;
-        }
-    }
-    if (!updateChildrenPosition(toBeUpdatedPtNodeParams, childrenPos)) {
-        return false;
-    }
-
-    // Counts bigram entries.
-    if (outBigramEntryCount) {
-        *outBigramEntryCount = mBigramPolicy->getBigramEntryConut(
-                toBeUpdatedPtNodeParams->getTerminalId());
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::addShortcutTarget(const PtNodeParams *const ptNodeParams,
-        const int *const targetCodePoints, const int targetCodePointCount,
-        const int shortcutProbability) {
-    if (!mShortcutPolicy->addNewShortcut(ptNodeParams->getTerminalId(),
-            targetCodePoints, targetCodePointCount, shortcutProbability)) {
-        AKLOGE("Cannot add new shortuct entry. terminalId: %d", ptNodeParams->getTerminalId());
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieNodeWriter::writePtNodeAndGetTerminalIdAndAdvancePosition(
-        const PtNodeParams *const ptNodeParams, int *const outTerminalId,
-        int *const ptNodeWritingPos) {
-    const int nodePos = *ptNodeWritingPos;
-    // Write dummy flags. The Node flags are updated with appropriate flags at the last step of the
-    // PtNode writing.
-    if (!DynamicPtWritingUtils::writeFlagsAndAdvancePosition(mTrieBuffer,
-            0 /* nodeFlags */, ptNodeWritingPos)) {
-        return false;
-    }
-    // Calculate a parent offset and write the offset.
-    if (!DynamicPtWritingUtils::writeParentPosOffsetAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getParentPos(), nodePos, ptNodeWritingPos)) {
-        return false;
-    }
-    // Write code points
-    if (!DynamicPtWritingUtils::writeCodePointsAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getCodePoints(), ptNodeParams->getCodePointCount(), ptNodeWritingPos)) {
-        return false;
-    }
-    int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (!ptNodeParams->willBecomeNonTerminal()) {
-        if (ptNodeParams->getTerminalId() != Ver4DictConstants::NOT_A_TERMINAL_ID) {
-            terminalId = ptNodeParams->getTerminalId();
-        } else if (ptNodeParams->isTerminal()) {
-            // Write terminal information using a new terminal id.
-            // Get a new unused terminal id.
-            terminalId = mBuffers->getTerminalPositionLookupTable()->getNextTerminalId();
-        }
-    }
-    const int isTerminal = terminalId != Ver4DictConstants::NOT_A_TERMINAL_ID;
-    if (isTerminal) {
-        // Update the lookup table.
-        if (!mBuffers->getMutableTerminalPositionLookupTable()->setTerminalPtNodePosition(
-                terminalId, nodePos)) {
-            return false;
-        }
-        // Write terminal Id.
-        if (!mTrieBuffer->writeUintAndAdvancePosition(terminalId,
-                Ver4DictConstants::TERMINAL_ID_FIELD_SIZE, ptNodeWritingPos)) {
-            return false;
-        }
-        if (outTerminalId) {
-            *outTerminalId = terminalId;
-        }
-    }
-    // Write children position
-    if (!DynamicPtWritingUtils::writeChildrenPositionAndAdvancePosition(mTrieBuffer,
-            ptNodeParams->getChildrenPos(), ptNodeWritingPos)) {
-        return false;
-    }
-    return updatePtNodeFlags(nodePos, ptNodeParams->isBlacklisted(), ptNodeParams->isNotAWord(),
-            isTerminal, ptNodeParams->getCodePointCount() > 1 /* hasMultipleChars */);
-}
-
-const ProbabilityEntry Ver4PatriciaTrieNodeWriter::createUpdatedEntryFrom(
-        const ProbabilityEntry *const originalProbabilityEntry,
-        const UnigramProperty *const unigramProperty) const {
-    // TODO: Consolidate historical info and probability.
-    if (mHeaderPolicy->hasHistoricalInfoOfWords()) {
-        const HistoricalInfo historicalInfoForUpdate(unigramProperty->getTimestamp(),
-                unigramProperty->getLevel(), unigramProperty->getCount());
-        const HistoricalInfo updatedHistoricalInfo =
-                ForgettingCurveUtils::createUpdatedHistoricalInfo(
-                        originalProbabilityEntry->getHistoricalInfo(),
-                        unigramProperty->getProbability(), &historicalInfoForUpdate, mHeaderPolicy);
-        return originalProbabilityEntry->createEntryWithUpdatedHistoricalInfo(
-                &updatedHistoricalInfo);
-    } else {
-        return originalProbabilityEntry->createEntryWithUpdatedProbability(
-                unigramProperty->getProbability());
-    }
-}
-
-bool Ver4PatriciaTrieNodeWriter::updatePtNodeFlags(const int ptNodePos,
-        const bool isBlacklisted, const bool isNotAWord, const bool isTerminal,
-        const bool hasMultipleChars) {
-    // Create node flags and write them.
-    PatriciaTrieReadingUtils::NodeFlags nodeFlags =
-            PatriciaTrieReadingUtils::createAndGetFlags(isBlacklisted, isNotAWord, isTerminal,
-                    false /* hasShortcutTargets */, false /* hasBigrams */, hasMultipleChars,
-                    CHILDREN_POSITION_FIELD_SIZE);
-    if (!DynamicPtWritingUtils::writeFlags(mTrieBuffer, nodeFlags, ptNodePos)) {
-        AKLOGE("Cannot write PtNode flags. flags: %x, pos: %d", nodeFlags, ptNodePos);
-        return false;
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
deleted file mode 100644
index 6703dba..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+++ /dev/null
@@ -1,121 +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.
- */
-
-#ifndef LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H
-#define LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_params.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-class HeaderPolicy;
-class Ver4BigramListPolicy;
-class Ver4DictBuffers;
-class Ver4PatriciaTrieNodeReader;
-class Ver4PtNodeArrayReader;
-class Ver4ShortcutListPolicy;
-
-/*
- * This class is used for helping to writes nodes of ver4 patricia trie.
- */
-class Ver4PatriciaTrieNodeWriter : public PtNodeWriter {
- public:
-    Ver4PatriciaTrieNodeWriter(BufferWithExtendableBuffer *const trieBuffer,
-            Ver4DictBuffers *const buffers, const HeaderPolicy *const headerPolicy,
-            const PtNodeReader *const ptNodeReader,
-            const PtNodeArrayReader *const ptNodeArrayReader,
-            Ver4BigramListPolicy *const bigramPolicy, Ver4ShortcutListPolicy *const shortcutPolicy)
-            : mTrieBuffer(trieBuffer), mBuffers(buffers), mHeaderPolicy(headerPolicy),
-              mReadingHelper(ptNodeReader, ptNodeArrayReader), mBigramPolicy(bigramPolicy),
-              mShortcutPolicy(shortcutPolicy) {}
-
-    virtual ~Ver4PatriciaTrieNodeWriter() {}
-
-    virtual bool markPtNodeAsDeleted(const PtNodeParams *const toBeUpdatedPtNodeParams);
-
-    virtual bool markPtNodeAsMoved(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int movedPos, const int bigramLinkedNodePos);
-
-    virtual bool markPtNodeAsWillBecomeNonTerminal(
-            const PtNodeParams *const toBeUpdatedPtNodeParams);
-
-    virtual bool updatePtNodeUnigramProperty(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const UnigramProperty *const unigramProperty);
-
-    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
-            const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
-
-    virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int newChildrenPosition);
-
-    bool updateTerminalId(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const int newTerminalId);
-
-    virtual bool writePtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            int *const ptNodeWritingPos);
-
-    virtual bool writeNewTerminalPtNodeAndAdvancePosition(const PtNodeParams *const ptNodeParams,
-            const UnigramProperty *const unigramProperty, int *const ptNodeWritingPos);
-
-    virtual bool addNgramEntry(const WordIdArrayView prevWordIds, const int wordId,
-            const BigramProperty *const bigramProperty, bool *const outAddedNewEntry);
-
-    virtual bool removeNgramEntry(const WordIdArrayView prevWordIds, const int wordId);
-
-    virtual bool updateAllBigramEntriesAndDeleteUselessEntries(
-            const PtNodeParams *const sourcePtNodeParams, int *const outBigramEntryCount);
-
-    virtual bool updateAllPositionFields(const PtNodeParams *const toBeUpdatedPtNodeParams,
-            const DictPositionRelocationMap *const dictPositionRelocationMap,
-            int *const outBigramEntryCount);
-
-    virtual bool addShortcutTarget(const PtNodeParams *const ptNodeParams,
-            const int *const targetCodePoints, const int targetCodePointCount,
-            const int shortcutProbability);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeWriter);
-
-    bool writePtNodeAndGetTerminalIdAndAdvancePosition(
-            const PtNodeParams *const ptNodeParams, int *const outTerminalId,
-            int *const ptNodeWritingPos);
-
-    // Create updated probability entry using given unigram property. In addition to the
-    // probability, this method updates historical information if needed.
-    // TODO: Update flags belonging to the unigram property.
-    const ProbabilityEntry createUpdatedEntryFrom(
-            const ProbabilityEntry *const originalProbabilityEntry,
-            const UnigramProperty *const unigramProperty) const;
-
-    bool updatePtNodeFlags(const int ptNodePos, const bool isBlacklisted, const bool isNotAWord,
-            const bool isTerminal, const bool hasMultipleChars);
-
-    static const int CHILDREN_POSITION_FIELD_SIZE;
-
-    BufferWithExtendableBuffer *const mTrieBuffer;
-    Ver4DictBuffers *const mBuffers;
-    const HeaderPolicy *const mHeaderPolicy;
-    DynamicPtReadingHelper mReadingHelper;
-    Ver4BigramListPolicy *const mBigramPolicy;
-    Ver4ShortcutListPolicy *const mShortcutPolicy;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_PATRICIA_TRIE_NODE_WRITER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
deleted file mode 100644
index 7238083..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ /dev/null
@@ -1,551 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h"
-
-#include <vector>
-
-#include "suggest/core/dicnode/dic_node.h"
-#include "suggest/core/dicnode/dic_node_vector.h"
-#include "suggest/core/dictionary/ngram_listener.h"
-#include "suggest/core/dictionary/property/bigram_property.h"
-#include "suggest/core/dictionary/property/unigram_property.h"
-#include "suggest/core/dictionary/property/word_property.h"
-#include "suggest/core/session/prev_words_info.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_helper.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
-
-namespace latinime {
-
-// Note that there are corresponding definitions in Java side in BinaryDictionaryTests and
-// BinaryDictionaryDecayingTests.
-const char *const Ver4PatriciaTriePolicy::UNIGRAM_COUNT_QUERY = "UNIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::BIGRAM_COUNT_QUERY = "BIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM_COUNT";
-const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT";
-const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024;
-const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS =
-        Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
-
-void Ver4PatriciaTriePolicy::createAndGetAllChildDicNodes(const DicNode *const dicNode,
-        DicNodeVector *const childDicNodes) const {
-    if (!dicNode->hasChildren()) {
-        return;
-    }
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(dicNode->getChildrenPtNodeArrayPos());
-    while (!readingHelper.isEnd()) {
-        const PtNodeParams ptNodeParams = readingHelper.getPtNodeParams();
-        if (!ptNodeParams.isValid()) {
-            break;
-        }
-        bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
-        if (isTerminal && mHeaderPolicy->isDecayingDict()) {
-            // A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
-            // probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
-            // valid terminal DicNode.
-            isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
-        }
-        readingHelper.readNextSiblingNode(ptNodeParams);
-        if (ptNodeParams.representsNonWordInfo()) {
-            // Skip PtNodes that represent non-word information.
-            continue;
-        }
-        childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getHeadPos(),
-                ptNodeParams.getChildrenPos(), ptNodeParams.getProbability(), isTerminal,
-                ptNodeParams.hasChildren(),
-                ptNodeParams.isBlacklisted()
-                        || ptNodeParams.isNotAWord() /* isBlacklistedOrNotAWord */,
-                ptNodeParams.getCodePointCount(), ptNodeParams.getCodePoints());
-    }
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
-    }
-}
-
-int Ver4PatriciaTriePolicy::getCodePointsAndProbabilityAndReturnCodePointCount(
-        const int ptNodePos, const int maxCodePointCount, int *const outCodePoints,
-        int *const outUnigramProbability) const {
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodePos(ptNodePos);
-    const int codePointCount =  readingHelper.getCodePointsAndProbabilityAndReturnCodePointCount(
-            maxCodePointCount, outCodePoints, outUnigramProbability);
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in getCodePointsAndProbabilityAndReturnCodePointCount().");
-    }
-    return codePointCount;
-}
-
-int Ver4PatriciaTriePolicy::getTerminalPtNodePositionOfWord(const int *const inWord,
-        const int length, const bool forceLowerCaseSearch) const {
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    const int ptNodePos =
-            readingHelper.getTerminalPtNodePositionOfWord(inWord, length, forceLowerCaseSearch);
-    if (readingHelper.isError()) {
-        mIsCorrupted = true;
-        AKLOGE("Dictionary reading error in createAndGetAllChildDicNodes().");
-    }
-    return ptNodePos;
-}
-
-int Ver4PatriciaTriePolicy::getProbability(const int unigramProbability,
-        const int bigramProbability) const {
-    if (mHeaderPolicy->isDecayingDict()) {
-        // Both probabilities are encoded. Decode them and get probability.
-        return ForgettingCurveUtils::getProbability(unigramProbability, bigramProbability);
-    } else {
-        if (unigramProbability == NOT_A_PROBABILITY) {
-            return NOT_A_PROBABILITY;
-        } else if (bigramProbability == NOT_A_PROBABILITY) {
-            return ProbabilityUtils::backoff(unigramProbability);
-        } else {
-            return bigramProbability;
-        }
-    }
-}
-
-int Ver4PatriciaTriePolicy::getProbabilityOfPtNode(const int *const prevWordsPtNodePos,
-        const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_PROBABILITY;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted() || ptNodeParams.isBlacklisted() || ptNodeParams.isNotAWord()) {
-        return NOT_A_PROBABILITY;
-    }
-    if (prevWordsPtNodePos) {
-        const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-        BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
-        while (bigramsIt.hasNext()) {
-            bigramsIt.next();
-            if (bigramsIt.getBigramPos() == ptNodePos
-                    && bigramsIt.getProbability() != NOT_A_PROBABILITY) {
-                return getProbability(ptNodeParams.getProbability(), bigramsIt.getProbability());
-            }
-        }
-        return NOT_A_PROBABILITY;
-    }
-    return getProbability(ptNodeParams.getProbability(), NOT_A_PROBABILITY);
-}
-
-void Ver4PatriciaTriePolicy::iterateNgramEntries(const int *const prevWordsPtNodePos,
-        NgramListener *const listener) const {
-    if (!prevWordsPtNodePos) {
-        return;
-    }
-    const int bigramsPosition = getBigramsPositionOfPtNode(prevWordsPtNodePos[0]);
-    BinaryDictionaryBigramsIterator bigramsIt(&mBigramPolicy, bigramsPosition);
-    while (bigramsIt.hasNext()) {
-        bigramsIt.next();
-        listener->onVisitEntry(bigramsIt.getProbability(), bigramsIt.getBigramPos());
-    }
-}
-
-int Ver4PatriciaTriePolicy::getShortcutPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted()) {
-        return NOT_A_DICT_POS;
-    }
-    return mBuffers->getShortcutDictContent()->getShortcutListHeadPos(
-            ptNodeParams.getTerminalId());
-}
-
-int Ver4PatriciaTriePolicy::getBigramsPositionOfPtNode(const int ptNodePos) const {
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return NOT_A_DICT_POS;
-    }
-    const PtNodeParams ptNodeParams(mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos));
-    if (ptNodeParams.isDeleted()) {
-        return NOT_A_DICT_POS;
-    }
-    return mBuffers->getBigramDictContent()->getBigramListHeadPos(
-            ptNodeParams.getTerminalId());
-}
-
-bool Ver4PatriciaTriePolicy::addUnigramEntry(const int *const word, const int length,
-        const UnigramProperty *const unigramProperty) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: addUnigramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert to the dictionary, length: %d", length);
-        return false;
-    }
-    for (const auto &shortcut : unigramProperty->getShortcuts()) {
-        if (shortcut.getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-            AKLOGE("One of shortcut targets is too long to insert to the dictionary, length: %d",
-                    shortcut.getTargetCodePoints()->size());
-            return false;
-        }
-    }
-    DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(getRootPosition());
-    bool addedNewUnigram = false;
-    int codePointsToAdd[MAX_WORD_LENGTH];
-    int codePointCountToAdd = length;
-    memmove(codePointsToAdd, word, sizeof(int) * length);
-    if (unigramProperty->representsBeginningOfSentence()) {
-        codePointCountToAdd = CharUtils::attachBeginningOfSentenceMarker(codePointsToAdd,
-                codePointCountToAdd, MAX_WORD_LENGTH);
-    }
-    if (codePointCountToAdd <= 0) {
-        return false;
-    }
-    if (mUpdatingHelper.addUnigramWord(&readingHelper, codePointsToAdd, codePointCountToAdd,
-            unigramProperty, &addedNewUnigram)) {
-        if (addedNewUnigram && !unigramProperty->representsBeginningOfSentence()) {
-            mUnigramCount++;
-        }
-        if (unigramProperty->getShortcuts().size() > 0) {
-            // Add shortcut target.
-            const int wordPos = getTerminalPtNodePositionOfWord(word, length,
-                    false /* forceLowerCaseSearch */);
-            if (wordPos == NOT_A_DICT_POS) {
-                AKLOGE("Cannot find terminal PtNode position to add shortcut target.");
-                return false;
-            }
-            for (const auto &shortcut : unigramProperty->getShortcuts()) {
-                if (!mUpdatingHelper.addShortcutTarget(wordPos,
-                        shortcut.getTargetCodePoints()->data(),
-                        shortcut.getTargetCodePoints()->size(), shortcut.getProbability())) {
-                    AKLOGE("Cannot add new shortcut target. PtNodePos: %d, length: %d, "
-                            "probability: %d", wordPos, shortcut.getTargetCodePoints()->size(),
-                            shortcut.getProbability());
-                    return false;
-                }
-            }
-        }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::removeUnigramEntry(const int *const word, const int length) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: removeUnigramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    const int ptNodePos = getTerminalPtNodePositionOfWord(word, length,
-            false /* forceLowerCaseSearch */);
-    if (ptNodePos == NOT_A_DICT_POS) {
-        return false;
-    }
-    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    if (!mNodeWriter.markPtNodeAsDeleted(&ptNodeParams)) {
-        AKLOGE("Cannot remove unigram. ptNodePos: %d", ptNodePos);
-        return false;
-    }
-    if (!ptNodeParams.representsNonWordInfo()) {
-        mUnigramCount--;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTriePolicy::addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const BigramProperty *const bigramProperty) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: addNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (!prevWordsInfo->isValid()) {
-        AKLOGE("prev words info is not valid for adding n-gram entry to the dictionary.");
-        return false;
-    }
-    if (bigramProperty->getTargetCodePoints()->size() > MAX_WORD_LENGTH) {
-        AKLOGE("The word is too long to insert the ngram to the dictionary. "
-                "length: %d", bigramProperty->getTargetCodePoints()->size());
-        return false;
-    }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-            false /* tryLowerCaseSearch */);
-    const auto prevWordsPtNodePosView = PtNodePosArrayView::fromFixedSizeArray(prevWordsPtNodePos);
-    // TODO: Support N-gram.
-    if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
-        if (prevWordsInfo->isNthPrevWordBeginningOfSentence(1 /* n */)) {
-            const std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-            const UnigramProperty beginningOfSentenceUnigramProperty(
-                    true /* representsBeginningOfSentence */, true /* isNotAWord */,
-                    false /* isBlacklisted */, MAX_PROBABILITY /* probability */,
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
-            if (!addUnigramEntry(prevWordsInfo->getNthPrevWordCodePoints(1 /* n */),
-                    prevWordsInfo->getNthPrevWordCodePointCount(1 /* n */),
-                    &beginningOfSentenceUnigramProperty)) {
-                AKLOGE("Cannot add unigram entry for the beginning-of-sentence.");
-                return false;
-            }
-            // Refresh Terminal PtNode positions.
-            prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-                    false /* tryLowerCaseSearch */);
-        } else {
-            return false;
-        }
-    }
-    const int word1Pos = getTerminalPtNodePositionOfWord(
-            bigramProperty->getTargetCodePoints()->data(),
-            bigramProperty->getTargetCodePoints()->size(), false /* forceLowerCaseSearch */);
-    if (word1Pos == NOT_A_DICT_POS) {
-        return false;
-    }
-    bool addedNewEntry = false;
-    if (mUpdatingHelper.addNgramEntry(prevWordsPtNodePosView, word1Pos, bigramProperty,
-            &addedNewEntry)) {
-        if (addedNewEntry) {
-            mBigramCount++;
-        }
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-        const int *const word, const int length) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: removeNgramEntry() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS) {
-        AKLOGE("The dictionary is too large to dynamically update. Dictionary size: %d",
-                mDictBuffer->getTailPosition());
-        return false;
-    }
-    if (!prevWordsInfo->isValid()) {
-        AKLOGE("prev words info is not valid for removing n-gram entry form the dictionary.");
-        return false;
-    }
-    if (length > MAX_WORD_LENGTH) {
-        AKLOGE("word is too long to remove n-gram entry form the dictionary. length: %d", length);
-    }
-    int prevWordsPtNodePos[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-    prevWordsInfo->getPrevWordsTerminalPtNodePos(this, prevWordsPtNodePos,
-            false /* tryLowerCaseSerch */);
-    const auto prevWordsPtNodePosView = PtNodePosArrayView::fromFixedSizeArray(prevWordsPtNodePos);
-    // TODO: Support N-gram.
-    if (prevWordsPtNodePos[0] == NOT_A_DICT_POS) {
-        return false;
-    }
-    const int wordPos = getTerminalPtNodePositionOfWord(word, length,
-            false /* forceLowerCaseSearch */);
-    if (wordPos == NOT_A_DICT_POS) {
-        return false;
-    }
-    if (mUpdatingHelper.removeNgramEntry(prevWordsPtNodePosView, wordPos)) {
-        mBigramCount--;
-        return true;
-    } else {
-        return false;
-    }
-}
-
-bool Ver4PatriciaTriePolicy::flush(const char *const filePath) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath);
-        return false;
-    }
-    if (!mWritingHelper.writeToDictFile(filePath, mUnigramCount, mBigramCount)) {
-        AKLOGE("Cannot flush the dictionary to file.");
-        mIsCorrupted = true;
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) {
-        AKLOGE("Cannot flush the dictionary to file with GC.");
-        mIsCorrupted = true;
-        return false;
-    }
-    return true;
-}
-
-bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const {
-    if (!mBuffers->isUpdatable()) {
-        AKLOGI("Warning: needsToRunGC() is called for non-updatable dictionary.");
-        return false;
-    }
-    if (mBuffers->isNearSizeLimit()) {
-        // Additional buffer size is near the limit.
-        return true;
-    } else if (mHeaderPolicy->getExtendedRegionSize() + mDictBuffer->getUsedAdditionalBufferSize()
-            > Ver4DictConstants::MAX_DICT_EXTENDED_REGION_SIZE) {
-        // Total extended region size of the trie exceeds the limit.
-        return true;
-    } else if (mDictBuffer->getTailPosition() >= MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS
-            && mDictBuffer->getUsedAdditionalBufferSize() > 0) {
-        // Needs to reduce dictionary size.
-        return true;
-    } else if (mHeaderPolicy->isDecayingDict()) {
-        return ForgettingCurveUtils::needsToDecay(mindsBlockByGC, mUnigramCount, mBigramCount,
-                mHeaderPolicy);
-    }
-    return false;
-}
-
-void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength,
-        char *const outResult, const int maxResultLength) {
-    const int compareLength = queryLength + 1 /* terminator */;
-    if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d", mUnigramCount);
-    } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d", mBigramCount);
-    } else if (strncmp(query, MAX_UNIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d",
-                mHeaderPolicy->isDecayingDict() ?
-                        ForgettingCurveUtils::getUnigramCountHardLimit(
-                                mHeaderPolicy->getMaxUnigramCount()) :
-                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    } else if (strncmp(query, MAX_BIGRAM_COUNT_QUERY, compareLength) == 0) {
-        snprintf(outResult, maxResultLength, "%d",
-                mHeaderPolicy->isDecayingDict() ?
-                        ForgettingCurveUtils::getBigramCountHardLimit(
-                                mHeaderPolicy->getMaxBigramCount()) :
-                        static_cast<int>(Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    }
-}
-
-const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const codePoints,
-        const int codePointCount) const {
-    const int ptNodePos = getTerminalPtNodePositionOfWord(codePoints, codePointCount,
-            false /* forceLowerCaseSearch */);
-    if (ptNodePos == NOT_A_DICT_POS) {
-        AKLOGE("getWordProperty is called for invalid word.");
-        return WordProperty();
-    }
-    const PtNodeParams ptNodeParams = mNodeReader.fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-    std::vector<int> codePointVector(ptNodeParams.getCodePoints(),
-            ptNodeParams.getCodePoints() + ptNodeParams.getCodePointCount());
-    const ProbabilityEntry probabilityEntry =
-            mBuffers->getLanguageModelDictContent()->getProbabilityEntry(
-                    ptNodeParams.getTerminalId());
-    const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
-    // Fetch bigram information.
-    std::vector<BigramProperty> bigrams;
-    const int bigramListPos = getBigramsPositionOfPtNode(ptNodePos);
-    if (bigramListPos != NOT_A_DICT_POS) {
-        int bigramWord1CodePoints[MAX_WORD_LENGTH];
-        const BigramDictContent *const bigramDictContent = mBuffers->getBigramDictContent();
-        const TerminalPositionLookupTable *const terminalPositionLookupTable =
-                mBuffers->getTerminalPositionLookupTable();
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            hasNext = bigramEntry.hasNext();
-            const int word1TerminalId = bigramEntry.getTargetTerminalId();
-            const int word1TerminalPtNodePos =
-                    terminalPositionLookupTable->getTerminalPtNodePosition(word1TerminalId);
-            if (word1TerminalPtNodePos == NOT_A_DICT_POS) {
-                continue;
-            }
-            // Word (unigram) probability
-            int word1Probability = NOT_A_PROBABILITY;
-            const int codePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-                    word1TerminalPtNodePos, MAX_WORD_LENGTH, bigramWord1CodePoints,
-                    &word1Probability);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + codePointCount);
-            const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
-                    bigramEntry.getProbability();
-            bigrams.emplace_back(&word1, probability,
-                    historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-                    historicalInfo->getCount());
-        }
-    }
-    // Fetch shortcut information.
-    std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-    int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
-    if (shortcutPos != NOT_A_DICT_POS) {
-        int shortcutTarget[MAX_WORD_LENGTH];
-        const ShortcutDictContent *const shortcutDictContent =
-                mBuffers->getShortcutDictContent();
-        bool hasNext = true;
-        while (hasNext) {
-            int shortcutTargetLength = 0;
-            int shortcutProbability = NOT_A_PROBABILITY;
-            shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
-                    &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
-            const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcuts.emplace_back(&target, shortcutProbability);
-        }
-    }
-    const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
-            ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
-            historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-            historicalInfo->getCount(), &shortcuts);
-    return WordProperty(&codePointVector, &unigramProperty, &bigrams);
-}
-
-int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
-        int *const outCodePointCount) {
-    *outCodePointCount = 0;
-    if (token == 0) {
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        DynamicPtReadingHelper::TraversePolicyToGetAllTerminalPtNodePositions traversePolicy(
-                &mTerminalPtNodePositionsForIteratingWords);
-        DynamicPtReadingHelper readingHelper(&mNodeReader, &mPtNodeArrayReader);
-        readingHelper.initWithPtNodeArrayPos(getRootPosition());
-        readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(&traversePolicy);
-    }
-    const int terminalPtNodePositionsVectorSize =
-            static_cast<int>(mTerminalPtNodePositionsForIteratingWords.size());
-    if (token < 0 || token >= terminalPtNodePositionsVectorSize) {
-        AKLOGE("Given token %d is invalid.", token);
-        return 0;
-    }
-    const int terminalPtNodePos = mTerminalPtNodePositionsForIteratingWords[token];
-    int unigramProbability = NOT_A_PROBABILITY;
-    *outCodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
-            terminalPtNodePos, MAX_WORD_LENGTH, outCodePoints, &unigramProbability);
-    const int nextToken = token + 1;
-    if (nextToken >= terminalPtNodePositionsVectorSize) {
-        // All words have been iterated.
-        mTerminalPtNodePositionsForIteratingWords.clear();
-        return 0;
-    }
-    return nextToken;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
deleted file mode 100644
index faad429..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ /dev/null
@@ -1,150 +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.
- */
-
-#ifndef LATINIME_VER4_PATRICIA_TRIE_POLICY_H
-#define LATINIME_VER4_PATRICIA_TRIE_POLICY_H
-
-#include <vector>
-
-#include "defines.h"
-#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_updating_helper.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-class DicNode;
-class DicNodeVector;
-
-class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy {
- public:
-    Ver4PatriciaTriePolicy(Ver4DictBuffers::Ver4DictBuffersPtr buffers)
-            : mBuffers(std::move(buffers)), mHeaderPolicy(mBuffers->getHeaderPolicy()),
-              mDictBuffer(mBuffers->getWritableTrieBuffer()),
-              mBigramPolicy(mBuffers->getMutableBigramDictContent(),
-                      mBuffers->getTerminalPositionLookupTable(), mHeaderPolicy),
-              mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
-                      mBuffers->getTerminalPositionLookupTable()),
-              mNodeReader(mDictBuffer, mBuffers->getLanguageModelDictContent(), mHeaderPolicy),
-              mPtNodeArrayReader(mDictBuffer),
-              mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
-                      &mPtNodeArrayReader, &mBigramPolicy, &mShortcutPolicy),
-              mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
-              mWritingHelper(mBuffers.get()),
-              mUnigramCount(mHeaderPolicy->getUnigramCount()),
-              mBigramCount(mHeaderPolicy->getBigramCount()),
-              mTerminalPtNodePositionsForIteratingWords(), mIsCorrupted(false) {};
-
-    AK_FORCE_INLINE int getRootPosition() const {
-        return 0;
-    }
-
-    void createAndGetAllChildDicNodes(const DicNode *const dicNode,
-            DicNodeVector *const childDicNodes) const;
-
-    int getCodePointsAndProbabilityAndReturnCodePointCount(
-            const int terminalPtNodePos, const int maxCodePointCount, int *const outCodePoints,
-            int *const outUnigramProbability) const;
-
-    int getTerminalPtNodePositionOfWord(const int *const inWord,
-            const int length, const bool forceLowerCaseSearch) const;
-
-    int getProbability(const int unigramProbability, const int bigramProbability) const;
-
-    int getProbabilityOfPtNode(const int *const prevWordsPtNodePos, const int ptNodePos) const;
-
-    void iterateNgramEntries(const int *const prevWordsPtNodePos,
-            NgramListener *const listener) const;
-
-    int getShortcutPositionOfPtNode(const int ptNodePos) const;
-
-    const DictionaryHeaderStructurePolicy *getHeaderStructurePolicy() const {
-        return mHeaderPolicy;
-    }
-
-    const DictionaryShortcutsStructurePolicy *getShortcutsStructurePolicy() const {
-        return &mShortcutPolicy;
-    }
-
-    bool addUnigramEntry(const int *const word, const int length,
-            const UnigramProperty *const unigramProperty);
-
-    bool removeUnigramEntry(const int *const word, const int length);
-
-    bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo,
-            const BigramProperty *const bigramProperty);
-
-    bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word1,
-            const int length1);
-
-    bool flush(const char *const filePath);
-
-    bool flushWithGC(const char *const filePath);
-
-    bool needsToRunGC(const bool mindsBlockByGC) const;
-
-    void getProperty(const char *const query, const int queryLength, char *const outResult,
-            const int maxResultLength);
-
-    const WordProperty getWordProperty(const int *const codePoints,
-            const int codePointCount) const;
-
-    int getNextWordAndNextToken(const int token, int *const outCodePoints,
-            int *const outCodePointCount);
-
-    bool isCorrupted() const {
-        return mIsCorrupted;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTriePolicy);
-
-    static const char *const UNIGRAM_COUNT_QUERY;
-    static const char *const BIGRAM_COUNT_QUERY;
-    static const char *const MAX_UNIGRAM_COUNT_QUERY;
-    static const char *const MAX_BIGRAM_COUNT_QUERY;
-    // When the dictionary size is near the maximum size, we have to refuse dynamic operations to
-    // prevent the dictionary from overflowing.
-    static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS;
-    static const int MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS;
-
-    const Ver4DictBuffers::Ver4DictBuffersPtr mBuffers;
-    const HeaderPolicy *const mHeaderPolicy;
-    BufferWithExtendableBuffer *const mDictBuffer;
-    Ver4BigramListPolicy mBigramPolicy;
-    Ver4ShortcutListPolicy mShortcutPolicy;
-    Ver4PatriciaTrieNodeReader mNodeReader;
-    Ver4PtNodeArrayReader mPtNodeArrayReader;
-    Ver4PatriciaTrieNodeWriter mNodeWriter;
-    DynamicPtUpdatingHelper mUpdatingHelper;
-    Ver4PatriciaTrieWritingHelper mWritingHelper;
-    int mUnigramCount;
-    int mBigramCount;
-    std::vector<int> mTerminalPtNodePositionsForIteratingWords;
-    mutable bool mIsCorrupted;
-
-    int getBigramsPositionOfPtNode(const int ptNodePos) const;
-};
-} // namespace latinime
-#endif // LATINIME_VER4_PATRICIA_TRIE_POLICY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
deleted file mode 100644
index 254022d..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.cpp
+++ /dev/null
@@ -1,28 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_reading_utils.h"
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-/* static */ int Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(
-        const uint8_t *const buffer, int *pos) {
-    return ByteArrayUtils::readUint32AndAdvancePosition(buffer, pos);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
deleted file mode 100644
index 4220312..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ /dev/null
@@ -1,294 +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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h"
-
-#include <cstring>
-#include <queue>
-
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/bigram/ver4_bigram_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/shortcut/ver4_shortcut_list_policy.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_constants.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-namespace latinime {
-
-bool Ver4PatriciaTrieWritingHelper::writeToDictFile(const char *const dictDirPath,
-        const int unigramCount, const int bigramCount) const {
-    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
-    BufferWithExtendableBuffer headerBuffer(
-            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
-    const int extendedRegionSize = headerPolicy->getExtendedRegionSize()
-            + mBuffers->getTrieBuffer()->getUsedAdditionalBufferSize();
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(false /* updatesLastDecayedTime */,
-            unigramCount, bigramCount, extendedRegionSize, &headerBuffer)) {
-        AKLOGE("Cannot write header structure to buffer. "
-                "updatesLastDecayedTime: %d, unigramCount: %d, bigramCount: %d, "
-                "extendedRegionSize: %d", false, unigramCount, bigramCount,
-                extendedRegionSize);
-        return false;
-    }
-    return mBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
-}
-
-bool Ver4PatriciaTrieWritingHelper::writeToDictFileWithGC(const int rootPtNodeArrayPos,
-        const char *const dictDirPath) {
-    const HeaderPolicy *const headerPolicy = mBuffers->getHeaderPolicy();
-    Ver4DictBuffers::Ver4DictBuffersPtr dictBuffers(
-            Ver4DictBuffers::createVer4DictBuffers(headerPolicy,
-                    Ver4DictConstants::MAX_DICTIONARY_SIZE));
-    int unigramCount = 0;
-    int bigramCount = 0;
-    if (!runGC(rootPtNodeArrayPos, headerPolicy, dictBuffers.get(), &unigramCount, &bigramCount)) {
-        return false;
-    }
-    BufferWithExtendableBuffer headerBuffer(
-            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
-    if (!headerPolicy->fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
-            unigramCount, bigramCount, 0 /* extendedRegionSize */, &headerBuffer)) {
-        return false;
-    }
-    return dictBuffers->flushHeaderAndDictBuffers(dictDirPath, &headerBuffer);
-}
-
-bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
-        const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
-        int *const outUnigramCount, int *const outBigramCount) {
-    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
-            mBuffers->getLanguageModelDictContent(), headerPolicy);
-    Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
-    Ver4BigramListPolicy bigramPolicy(mBuffers->getMutableBigramDictContent(),
-            mBuffers->getTerminalPositionLookupTable(), headerPolicy);
-    Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
-            mBuffers->getTerminalPositionLookupTable());
-    Ver4PatriciaTrieNodeWriter ptNodeWriter(mBuffers->getWritableTrieBuffer(),
-            mBuffers, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
-
-    DynamicPtReadingHelper readingHelper(&ptNodeReader, &ptNodeArrayReader);
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners
-            ::TraversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-                    traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted(
-                            &ptNodeWriter);
-    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted)) {
-        return false;
-    }
-    const int unigramCount = traversePolicyToUpdateUnigramProbabilityAndMarkUselessPtNodesAsDeleted
-            .getValidUnigramCount();
-    const int maxUnigramCount = headerPolicy->getMaxUnigramCount();
-    if (headerPolicy->isDecayingDict() && unigramCount > maxUnigramCount) {
-        if (!truncateUnigrams(&ptNodeReader, &ptNodeWriter, maxUnigramCount)) {
-            AKLOGE("Cannot remove unigrams. current: %d, max: %d", unigramCount,
-                    maxUnigramCount);
-            return false;
-        }
-    }
-
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners::TraversePolicyToUpdateBigramProbability
-            traversePolicyToUpdateBigramProbability(&ptNodeWriter);
-    if (!readingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateBigramProbability)) {
-        return false;
-    }
-    const int bigramCount = traversePolicyToUpdateBigramProbability.getValidBigramEntryCount();
-    const int maxBigramCount = headerPolicy->getMaxBigramCount();
-    if (headerPolicy->isDecayingDict() && bigramCount > maxBigramCount) {
-        if (!truncateBigrams(maxBigramCount)) {
-            AKLOGE("Cannot remove bigrams. current: %d, max: %d", bigramCount, maxBigramCount);
-            return false;
-        }
-    }
-
-    // Mapping from positions in mBuffer to positions in bufferToWrite.
-    PtNodeWriter::DictPositionRelocationMap dictPositionRelocationMap;
-    readingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    Ver4PatriciaTrieNodeWriter ptNodeWriterForNewBuffers(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &ptNodeReader, &ptNodeArrayReader, &bigramPolicy,
-            &shortcutPolicy);
-    DynamicPtGcEventListeners::TraversePolicyToPlaceAndWriteValidPtNodesToBuffer
-            traversePolicyToPlaceAndWriteValidPtNodesToBuffer(&ptNodeWriterForNewBuffers,
-                    buffersToWrite->getWritableTrieBuffer(), &dictPositionRelocationMap);
-    if (!readingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-            &traversePolicyToPlaceAndWriteValidPtNodesToBuffer)) {
-        return false;
-    }
-
-    // Create policy instances for the GCed dictionary.
-    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
-            buffersToWrite->getLanguageModelDictContent(), headerPolicy);
-    Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
-    Ver4BigramListPolicy newBigramPolicy(buffersToWrite->getMutableBigramDictContent(),
-            buffersToWrite->getTerminalPositionLookupTable(), headerPolicy);
-    Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
-            buffersToWrite->getTerminalPositionLookupTable());
-    Ver4PatriciaTrieNodeWriter newPtNodeWriter(buffersToWrite->getWritableTrieBuffer(),
-            buffersToWrite, headerPolicy, &newPtNodeReader, &newPtNodeArrayreader, &newBigramPolicy,
-            &newShortcutPolicy);
-    // Re-assign terminal IDs for valid terminal PtNodes.
-    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
-    if(!buffersToWrite->getMutableTerminalPositionLookupTable()->runGCTerminalIds(
-            &terminalIdMap)) {
-        return false;
-    }
-    // Run GC for probability dict content.
-    if (!buffersToWrite->getMutableLanguageModelDictContent()->runGC(&terminalIdMap,
-            mBuffers->getLanguageModelDictContent(), nullptr /* outNgramCount */)) {
-        return false;
-    }
-    // Run GC for bigram dict content.
-    if(!buffersToWrite->getMutableBigramDictContent()->runGC(&terminalIdMap,
-            mBuffers->getBigramDictContent(), outBigramCount)) {
-        return false;
-    }
-    // Run GC for shortcut dict content.
-    if(!buffersToWrite->getMutableShortcutDictContent()->runGC(&terminalIdMap,
-            mBuffers->getShortcutDictContent())) {
-        return false;
-    }
-    DynamicPtReadingHelper newDictReadingHelper(&newPtNodeReader, &newPtNodeArrayreader);
-    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    DynamicPtGcEventListeners::TraversePolicyToUpdateAllPositionFields
-            traversePolicyToUpdateAllPositionFields(&newPtNodeWriter, &dictPositionRelocationMap);
-    if (!newDictReadingHelper.traverseAllPtNodesInPtNodeArrayLevelPreorderDepthFirstManner(
-            &traversePolicyToUpdateAllPositionFields)) {
-        return false;
-    }
-    newDictReadingHelper.initWithPtNodeArrayPos(rootPtNodeArrayPos);
-    TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-            traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(&newPtNodeWriter, &terminalIdMap);
-    if (!newDictReadingHelper.traverseAllPtNodesInPostorderDepthFirstManner(
-            &traversePolicyToUpdateAllPtNodeFlagsAndTerminalIds)) {
-        return false;
-    }
-    *outUnigramCount = traversePolicyToUpdateAllPositionFields.getUnigramCount();
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::truncateUnigrams(
-        const Ver4PatriciaTrieNodeReader *const ptNodeReader,
-        Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int terminalPos = terminalPosLookupTable->getTerminalPtNodePosition(i);
-        if (terminalPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        const ProbabilityEntry probabilityEntry =
-                mBuffers->getLanguageModelDictContent()->getProbabilityEntry(i);
-        const int probability = probabilityEntry.hasHistoricalInfo() ?
-                ForgettingCurveUtils::decodeProbability(
-                        probabilityEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                probabilityEntry.getProbability();
-        priorityQueue.push(DictProbability(terminalPos, probability,
-                probabilityEntry.getHistoricalInfo()->getTimeStamp()));
-    }
-
-    // Delete unigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxUnigramCount) {
-        const int ptNodePos = priorityQueue.top().getDictPos();
-        priorityQueue.pop();
-        const PtNodeParams ptNodeParams =
-                ptNodeReader->fetchPtNodeParamsInBufferFromPtNodePos(ptNodePos);
-        if (ptNodeParams.representsNonWordInfo()) {
-            continue;
-        }
-        if (!ptNodeWriter->markPtNodeAsWillBecomeNonTerminal(&ptNodeParams)) {
-            AKLOGE("Cannot mark PtNode as willBecomeNonterminal. PtNode pos: %d", ptNodePos);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::truncateBigrams(const int maxBigramCount) {
-    const TerminalPositionLookupTable *const terminalPosLookupTable =
-            mBuffers->getTerminalPositionLookupTable();
-    const int nextTerminalId = terminalPosLookupTable->getNextTerminalId();
-    std::priority_queue<DictProbability, std::vector<DictProbability>, DictProbabilityComparator>
-            priorityQueue;
-    BigramDictContent *const bigramDictContent = mBuffers->getMutableBigramDictContent();
-    for (int i = 0; i < nextTerminalId; ++i) {
-        const int bigramListPos = bigramDictContent->getBigramListHeadPos(i);
-        if (bigramListPos == NOT_A_DICT_POS) {
-            continue;
-        }
-        bool hasNext = true;
-        int readingPos = bigramListPos;
-        while (hasNext) {
-            const BigramEntry bigramEntry =
-                    bigramDictContent->getBigramEntryAndAdvancePosition(&readingPos);
-            const int entryPos = readingPos - bigramDictContent->getBigramEntrySize();
-            hasNext = bigramEntry.hasNext();
-            if (!bigramEntry.isValid()) {
-                continue;
-            }
-            const int probability = bigramEntry.hasHistoricalInfo() ?
-                    ForgettingCurveUtils::decodeProbability(
-                            bigramEntry.getHistoricalInfo(), mBuffers->getHeaderPolicy()) :
-                    bigramEntry.getProbability();
-            priorityQueue.push(DictProbability(entryPos, probability,
-                    bigramEntry.getHistoricalInfo()->getTimeStamp()));
-        }
-    }
-
-    // Delete bigrams.
-    while (static_cast<int>(priorityQueue.size()) > maxBigramCount) {
-        const int entryPos = priorityQueue.top().getDictPos();
-        const BigramEntry bigramEntry = bigramDictContent->getBigramEntry(entryPos);
-        const BigramEntry invalidatedBigramEntry = bigramEntry.getInvalidatedEntry();
-        if (!bigramDictContent->writeBigramEntry(&invalidatedBigramEntry, entryPos)) {
-            AKLOGE("Cannot write bigram entry to remove. pos: %d", entryPos);
-            return false;
-        }
-        priorityQueue.pop();
-    }
-    return true;
-}
-
-bool Ver4PatriciaTrieWritingHelper::TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-        ::onVisitingPtNode(const PtNodeParams *const ptNodeParams) {
-    if (!ptNodeParams->isTerminal()) {
-        return true;
-    }
-    TerminalPositionLookupTable::TerminalIdMap::const_iterator it =
-            mTerminalIdMap->find(ptNodeParams->getTerminalId());
-    if (it == mTerminalIdMap->end()) {
-        AKLOGE("terminal Id %d is not in the terminal position map. map size: %zd",
-                ptNodeParams->getTerminalId(), mTerminalIdMap->size());
-        return false;
-    }
-    if (!mPtNodeWriter->updateTerminalId(ptNodeParams, it->second)) {
-        AKLOGE("Cannot update terminal id. %d -> %d", it->first, it->second);
-        return false;
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
deleted file mode 100644
index bb464ad..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.h
+++ /dev/null
@@ -1,125 +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.
- */
-
-#ifndef LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H
-#define LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_gc_event_listeners.h"
-#include "suggest/policyimpl/dictionary/structure/v4/content/terminal_position_lookup_table.h"
-
-namespace latinime {
-
-class HeaderPolicy;
-class Ver4DictBuffers;
-class Ver4PatriciaTrieNodeReader;
-class Ver4PatriciaTrieNodeWriter;
-
-class Ver4PatriciaTrieWritingHelper {
- public:
-    Ver4PatriciaTrieWritingHelper(Ver4DictBuffers *const buffers)
-            : mBuffers(buffers) {}
-
-    bool writeToDictFile(const char *const dictDirPath, const int unigramCount,
-            const int bigramCount) const;
-
-    // This method cannot be const because the original dictionary buffer will be updated to detect
-    // useless PtNodes during GC.
-    bool writeToDictFileWithGC(const int rootPtNodeArrayPos, const char *const dictDirPath);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(Ver4PatriciaTrieWritingHelper);
-
-    class TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds
-            : public DynamicPtReadingHelper::TraversingEventListener {
-     public:
-        TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds(
-                Ver4PatriciaTrieNodeWriter *const ptNodeWriter,
-                const TerminalPositionLookupTable::TerminalIdMap *const terminalIdMap)
-                : mPtNodeWriter(ptNodeWriter), mTerminalIdMap(terminalIdMap) {}
-
-        bool onAscend() { return true; }
-
-        bool onDescend(const int ptNodeArrayPos) { return true; }
-
-        bool onReadingPtNodeArrayTail() { return true; }
-
-        bool onVisitingPtNode(const PtNodeParams *const ptNodeParams);
-
-     private:
-        DISALLOW_IMPLICIT_CONSTRUCTORS(TraversePolicyToUpdateAllPtNodeFlagsAndTerminalIds);
-
-        Ver4PatriciaTrieNodeWriter *const mPtNodeWriter;
-        const TerminalPositionLookupTable::TerminalIdMap *const mTerminalIdMap;
-    };
-
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbability {
-     public:
-        DictProbability(const int dictPos, const int probability, const int timestamp)
-                : mDictPos(dictPos), mProbability(probability), mTimestamp(timestamp) {}
-
-        int getDictPos() const {
-            return mDictPos;
-        }
-
-        int getProbability() const {
-            return mProbability;
-        }
-
-        int getTimestamp() const {
-            return mTimestamp;
-        }
-
-     private:
-        DISALLOW_DEFAULT_CONSTRUCTOR(DictProbability);
-
-        int mDictPos;
-        int mProbability;
-        int mTimestamp;
-    };
-
-    // For truncateUnigrams() and truncateBigrams().
-    class DictProbabilityComparator {
-     public:
-        bool operator()(const DictProbability &left, const DictProbability &right) {
-            if (left.getProbability() != right.getProbability()) {
-                return left.getProbability() > right.getProbability();
-            }
-            if (left.getTimestamp() != right.getTimestamp()) {
-                return left.getTimestamp() < right.getTimestamp();
-            }
-            return left.getDictPos() > right.getDictPos();
-        }
-
-     private:
-        DISALLOW_ASSIGNMENT_OPERATOR(DictProbabilityComparator);
-    };
-
-    bool runGC(const int rootPtNodeArrayPos, const HeaderPolicy *const headerPolicy,
-            Ver4DictBuffers *const buffersToWrite, int *const outUnigramCount,
-            int *const outBigramCount);
-
-    bool truncateUnigrams(const Ver4PatriciaTrieNodeReader *const ptNodeReader,
-            Ver4PatriciaTrieNodeWriter *const ptNodeWriter, const int maxUnigramCount);
-
-    bool truncateBigrams(const int maxBigramCount);
-
-    Ver4DictBuffers *const mBuffers;
-};
-} // namespace latinime
-
-#endif /* LATINIME_VER4_PATRICIA_TRIE_WRITING_HELPER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
deleted file mode 100644
index b014c52..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h"
-
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_reading_utils.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/patricia_trie_reading_utils.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-bool Ver4PtNodeArrayReader::readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-        int *const outPtNodeCount, int *const outFirstPtNodePos) const {
-    if (ptNodeArrayPos < 0 || ptNodeArrayPos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of a bug or a broken dictionary.
-        AKLOGE("Reading PtNode array info from invalid dictionary position: %d, dict size: %d",
-                ptNodeArrayPos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return false;
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(ptNodeArrayPos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int readingPos = ptNodeArrayPos;
-    if (usesAdditionalBuffer) {
-        readingPos -= mBuffer->getOriginalBufferSize();
-    }
-    const int ptNodeCountInArray = PatriciaTrieReadingUtils::getPtNodeArraySizeAndAdvancePosition(
-            dictBuf, &readingPos);
-    if (usesAdditionalBuffer) {
-        readingPos += mBuffer->getOriginalBufferSize();
-    }
-    if (ptNodeCountInArray < 0) {
-        AKLOGE("Invalid PtNode count in an array: %d.", ptNodeCountInArray);
-        return false;
-    }
-    *outPtNodeCount = ptNodeCountInArray;
-    *outFirstPtNodePos = readingPos;
-    return true;
-}
-
-bool Ver4PtNodeArrayReader::readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-        int *const outNextPtNodeArrayPos) const {
-    if (forwordLinkPos < 0 || forwordLinkPos >= mBuffer->getTailPosition()) {
-        // Reading invalid position because of bug or broken dictionary.
-        AKLOGE("Reading forward link from invalid dictionary position: %d, dict size: %d",
-                forwordLinkPos, mBuffer->getTailPosition());
-        ASSERT(false);
-        return false;
-    }
-    const bool usesAdditionalBuffer = mBuffer->isInAdditionalBuffer(forwordLinkPos);
-    const uint8_t *const dictBuf = mBuffer->getBuffer(usesAdditionalBuffer);
-    int readingPos = forwordLinkPos;
-    if (usesAdditionalBuffer) {
-        readingPos -= mBuffer->getOriginalBufferSize();
-    }
-    const int nextPtNodeArrayOffset =
-            DynamicPtReadingUtils::getForwardLinkPosition(dictBuf, readingPos);
-    if (DynamicPtReadingUtils::isValidForwardLinkPosition(nextPtNodeArrayOffset)) {
-        *outNextPtNodeArrayPos = forwordLinkPos + nextPtNodeArrayOffset;
-    } else {
-        *outNextPtNodeArrayPos = NOT_A_DICT_POS;
-    }
-    return true;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h
deleted file mode 100644
index d81808e..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_pt_node_array_reader.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_VER4_PT_NODE_ARRAY_READER_H
-#define LATINIME_VER4_PT_NODE_ARRAY_READER_H
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/pt_node_array_reader.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-
-class Ver4PtNodeArrayReader : public PtNodeArrayReader {
- public:
-    Ver4PtNodeArrayReader(const BufferWithExtendableBuffer *const buffer) : mBuffer(buffer) {};
-
-    virtual bool readPtNodeArrayInfoAndReturnIfValid(const int ptNodeArrayPos,
-            int *const outPtNodeCount, int *const outFirstPtNodePos) const;
-    virtual bool readForwardLinkAndReturnIfValid(const int forwordLinkPos,
-            int *const outNextPtNodeArrayPos) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(Ver4PtNodeArrayReader);
-
-    const BufferWithExtendableBuffer *const mBuffer;
-};
-} // namespace latinime
-#endif /* LATINIME_VER4_PT_NODE_ARRAY_READER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp
deleted file mode 100644
index 833063c..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.cpp
+++ /dev/null
@@ -1,168 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-const size_t BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE = 1024 * 1024;
-const int BufferWithExtendableBuffer::NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE = 90;
-// TODO: Needs to allocate larger memory corresponding to the current vector size.
-const size_t BufferWithExtendableBuffer::EXTEND_ADDITIONAL_BUFFER_SIZE_STEP = 128 * 1024;
-
-uint32_t BufferWithExtendableBuffer::readUint(const int size, const int pos) const {
-    const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(pos);
-    const int posInBuffer = readingPosIsInAdditionalBuffer ? pos - mOriginalBuffer.size() : pos;
-    return ByteArrayUtils::readUint(getBuffer(readingPosIsInAdditionalBuffer), size, posInBuffer);
-}
-
-uint32_t BufferWithExtendableBuffer::readUintAndAdvancePosition(const int size,
-        int *const pos) const {
-    const int value = readUint(size, *pos);
-    *pos += size;
-    return value;
-}
-
-void BufferWithExtendableBuffer::readCodePointsAndAdvancePosition(const int maxCodePointCount,
-        int *const outCodePoints, int *outCodePointCount, int *const pos) const {
-    const bool readingPosIsInAdditionalBuffer = isInAdditionalBuffer(*pos);
-    if (readingPosIsInAdditionalBuffer) {
-        *pos -= mOriginalBuffer.size();
-    }
-    *outCodePointCount = ByteArrayUtils::readStringAndAdvancePosition(
-            getBuffer(readingPosIsInAdditionalBuffer), maxCodePointCount, outCodePoints, pos);
-    if (readingPosIsInAdditionalBuffer) {
-        *pos += mOriginalBuffer.size();
-    }
-}
-
-bool BufferWithExtendableBuffer::extend(const int size) {
-    return checkAndPrepareWriting(getTailPosition(), size);
-}
-
-bool BufferWithExtendableBuffer::writeUint(const uint32_t data, const int size, const int pos) {
-    int writingPos = pos;
-    return writeUintAndAdvancePosition(data, size, &writingPos);
-}
-
-bool BufferWithExtendableBuffer::writeUintAndAdvancePosition(const uint32_t data, const int size,
-        int *const pos) {
-    if (!(size >= 1 && size <= 4)) {
-        AKLOGI("writeUintAndAdvancePosition() is called with invalid size: %d", size);
-        ASSERT(false);
-        return false;
-    }
-    if (!checkAndPrepareWriting(*pos, size)) {
-        return false;
-    }
-    const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos);
-    uint8_t *const buffer =
-            usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data();
-    if (usesAdditionalBuffer) {
-        *pos -= mOriginalBuffer.size();
-    }
-    ByteArrayUtils::writeUintAndAdvancePosition(buffer, data, size, pos);
-    if (usesAdditionalBuffer) {
-        *pos += mOriginalBuffer.size();
-    }
-    return true;
-}
-
-bool BufferWithExtendableBuffer::writeCodePointsAndAdvancePosition(const int *const codePoints,
-        const int codePointCount, const bool writesTerminator, int *const pos) {
-    const size_t size = ByteArrayUtils::calculateRequiredByteCountToStoreCodePoints(
-            codePoints, codePointCount, writesTerminator);
-    if (!checkAndPrepareWriting(*pos, size)) {
-        return false;
-    }
-    const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos);
-    uint8_t *const buffer =
-            usesAdditionalBuffer ? mAdditionalBuffer.data() : mOriginalBuffer.data();
-    if (usesAdditionalBuffer) {
-        *pos -= mOriginalBuffer.size();
-    }
-    ByteArrayUtils::writeCodePointsAndAdvancePosition(buffer, codePoints, codePointCount,
-            writesTerminator, pos);
-    if (usesAdditionalBuffer) {
-        *pos += mOriginalBuffer.size();
-    }
-    return true;
-}
-
-bool BufferWithExtendableBuffer::extendBuffer(const size_t size) {
-    const size_t extendSize = std::max(EXTEND_ADDITIONAL_BUFFER_SIZE_STEP, size);
-    const size_t sizeAfterExtending =
-            std::min(mAdditionalBuffer.size() + extendSize, mMaxAdditionalBufferSize);
-    if (sizeAfterExtending < mAdditionalBuffer.size() + size) {
-        return false;
-    }
-    mAdditionalBuffer.resize(sizeAfterExtending);
-    return true;
-}
-
-bool BufferWithExtendableBuffer::checkAndPrepareWriting(const int pos, const int size) {
-    if (pos < 0 || size < 0) {
-        // Invalid position or size.
-        return false;
-    }
-    const size_t totalRequiredSize = static_cast<size_t>(pos + size);
-    if (!isInAdditionalBuffer(pos)) {
-        // Here don't need to care about the additional buffer.
-        if (mOriginalBuffer.size() < totalRequiredSize) {
-            // Violate the boundary.
-            return false;
-        }
-        // The buffer has sufficient capacity.
-        return true;
-    }
-    // Hereafter, pos is in the additional buffer.
-    const size_t tailPosition = static_cast<size_t>(getTailPosition());
-    if (totalRequiredSize <= tailPosition) {
-        // The buffer has sufficient capacity.
-        return true;
-    }
-    if (static_cast<size_t>(pos) != tailPosition) {
-        // The additional buffer must be extended from the tail position.
-        return false;
-    }
-    const size_t extendSize = totalRequiredSize -
-            std::min(mAdditionalBuffer.size() + mOriginalBuffer.size(), totalRequiredSize);
-    if (extendSize > 0 && !extendBuffer(extendSize)) {
-        // Failed to extend the buffer.
-        return false;
-    }
-    mUsedAdditionalBufferSize += size;
-    return true;
-}
-
-bool BufferWithExtendableBuffer::copy(const BufferWithExtendableBuffer *const sourceBuffer) {
-    int copyingPos = 0;
-    const int tailPos = sourceBuffer->getTailPosition();
-    const int maxDataChunkSize = sizeof(uint32_t);
-    while (copyingPos < tailPos) {
-        const int remainingSize = tailPos - copyingPos;
-        const int copyingSize = (remainingSize >= maxDataChunkSize) ?
-                maxDataChunkSize : remainingSize;
-        const uint32_t data = sourceBuffer->readUint(copyingSize, copyingPos);
-        if (!writeUint(data, copyingSize, copyingPos)) {
-            return false;
-        }
-        copyingPos += copyingSize;
-    }
-    return true;
-}
-
-}
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
deleted file mode 100644
index fad83aa..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
+++ /dev/null
@@ -1,125 +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.
- */
-
-#ifndef LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H
-#define LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H
-
-#include <cstddef>
-#include <cstdint>
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-// This is used as a buffer that can be extended for updatable dictionaries.
-// To optimize performance, raw pointer is directly used for reading buffer. The position has to be
-// adjusted to access additional buffer. On the other hand, this class does not provide writable
-// raw pointer but provides several methods that handle boundary checking for writing data.
-class BufferWithExtendableBuffer {
- public:
-    static const size_t DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE;
-
-    BufferWithExtendableBuffer(const ReadWriteByteArrayView originalBuffer,
-            const int maxAdditionalBufferSize)
-            : mOriginalBuffer(originalBuffer), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
-              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
-
-    // Without original buffer.
-    BufferWithExtendableBuffer(const int maxAdditionalBufferSize)
-            : mOriginalBuffer(), mAdditionalBuffer(), mUsedAdditionalBufferSize(0),
-              mMaxAdditionalBufferSize(maxAdditionalBufferSize) {}
-
-    AK_FORCE_INLINE int getTailPosition() const {
-        return mOriginalBuffer.size() + mUsedAdditionalBufferSize;
-    }
-
-    AK_FORCE_INLINE int getUsedAdditionalBufferSize() const {
-        return mUsedAdditionalBufferSize;
-    }
-
-    /**
-     * For reading.
-     */
-    AK_FORCE_INLINE bool isInAdditionalBuffer(const int position) const {
-        return position >= static_cast<int>(mOriginalBuffer.size());
-    }
-
-    // TODO: Resolve the issue that the address can be changed when the vector is resized.
-    // CAVEAT!: Be careful about array out of bound access with buffers
-    AK_FORCE_INLINE const uint8_t *getBuffer(const bool usesAdditionalBuffer) const {
-        if (usesAdditionalBuffer) {
-            return mAdditionalBuffer.data();
-        } else {
-            return mOriginalBuffer.data();
-        }
-    }
-
-    uint32_t readUint(const int size, const int pos) const;
-
-    uint32_t readUintAndAdvancePosition(const int size, int *const pos) const;
-
-    void readCodePointsAndAdvancePosition(const int maxCodePointCount,
-            int *const outCodePoints, int *outCodePointCount, int *const pos) const;
-
-    AK_FORCE_INLINE int getOriginalBufferSize() const {
-        return mOriginalBuffer.size();
-    }
-
-    AK_FORCE_INLINE bool isNearSizeLimit() const {
-        return mAdditionalBuffer.size() >= ((mMaxAdditionalBufferSize
-                * NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE) / 100);
-    }
-
-    bool extend(const int size);
-
-    /**
-     * For writing.
-     *
-     * Writing is allowed for original buffer, already written region of additional buffer and the
-     * tail of additional buffer.
-     */
-    bool writeUint(const uint32_t data, const int size, const int pos);
-
-    bool writeUintAndAdvancePosition(const uint32_t data, const int size, int *const pos);
-
-    bool writeCodePointsAndAdvancePosition(const int *const codePoints, const int codePointCount,
-            const bool writesTerminator, int *const pos);
-
-    bool copy(const BufferWithExtendableBuffer *const sourceBuffer);
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(BufferWithExtendableBuffer);
-
-    static const int NEAR_BUFFER_LIMIT_THRESHOLD_PERCENTILE;
-    static const size_t EXTEND_ADDITIONAL_BUFFER_SIZE_STEP;
-
-    const ReadWriteByteArrayView mOriginalBuffer;
-    std::vector<uint8_t> mAdditionalBuffer;
-    int mUsedAdditionalBufferSize;
-    const size_t mMaxAdditionalBufferSize;
-
-    // Return if the buffer is successfully extended or not.
-    bool extendBuffer(const size_t size);
-
-    // Returns if it is possible to write size-bytes from pos. When pos is at the tail position of
-    // the additional buffer, try extending the buffer.
-    bool checkAndPrepareWriting(const int pos, const int size);
-};
-}
-#endif /* LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.cpp
deleted file mode 100644
index 1833e88..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.cpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-const uint8_t ByteArrayUtils::MINIMUM_ONE_BYTE_CHARACTER_VALUE = 0x20;
-const uint8_t ByteArrayUtils::MAXIMUM_ONE_BYTE_CHARACTER_VALUE = 0xFF;
-const uint8_t ByteArrayUtils::CHARACTER_ARRAY_TERMINATOR = 0x1F;
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
deleted file mode 100644
index c0a9fcb..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
+++ /dev/null
@@ -1,279 +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.
- */
-
-#ifndef LATINIME_BYTE_ARRAY_UTILS_H
-#define LATINIME_BYTE_ARRAY_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-
-namespace latinime {
-
-/**
- * Utility methods for reading byte arrays.
- */
-class ByteArrayUtils {
- public:
-    /**
-     * Integer writing
-     *
-     * Each method write a corresponding size integer in a big endian manner.
-     */
-    static AK_FORCE_INLINE void writeUintAndAdvancePosition(uint8_t *const buffer,
-            const uint32_t data, const int size, int *const pos) {
-        // size must be in 1 to 4.
-        ASSERT(size >= 1 && size <= 4);
-        switch (size) {
-            case 1:
-                ByteArrayUtils::writeUint8AndAdvancePosition(buffer, data, pos);
-                return;
-            case 2:
-                ByteArrayUtils::writeUint16AndAdvancePosition(buffer, data, pos);
-                return;
-            case 3:
-                ByteArrayUtils::writeUint24AndAdvancePosition(buffer, data, pos);
-                return;
-            case 4:
-                ByteArrayUtils::writeUint32AndAdvancePosition(buffer, data, pos);
-                return;
-            default:
-                break;
-        }
-    }
-
-    /**
-     * Integer reading
-     *
-     * Each method read a corresponding size integer in a big endian manner.
-     */
-    static AK_FORCE_INLINE uint32_t readUint32(const uint8_t *const buffer, const int pos) {
-        return (buffer[pos] << 24) ^ (buffer[pos + 1] << 16)
-                ^ (buffer[pos + 2] << 8) ^ buffer[pos + 3];
-    }
-
-    static AK_FORCE_INLINE uint32_t readUint24(const uint8_t *const buffer, const int pos) {
-        return (buffer[pos] << 16) ^ (buffer[pos + 1] << 8) ^ buffer[pos + 2];
-    }
-
-    static AK_FORCE_INLINE uint16_t readUint16(const uint8_t *const buffer, const int pos) {
-        return (buffer[pos] << 8) ^ buffer[pos + 1];
-    }
-
-    static AK_FORCE_INLINE uint8_t readUint8(const uint8_t *const buffer, const int pos) {
-        return buffer[pos];
-    }
-
-    static AK_FORCE_INLINE uint32_t readUint32AndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        const uint32_t value = readUint32(buffer, *pos);
-        *pos += 4;
-        return value;
-    }
-
-    static AK_FORCE_INLINE int readSint24AndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        const uint8_t value = readUint8(buffer, *pos);
-        if (value < 0x80) {
-            return readUint24AndAdvancePosition(buffer, pos);
-        } else {
-            (*pos)++;
-            return -(((value & 0x7F) << 16) ^ readUint16AndAdvancePosition(buffer, pos));
-        }
-    }
-
-    static AK_FORCE_INLINE uint32_t readUint24AndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        const uint32_t value = readUint24(buffer, *pos);
-        *pos += 3;
-        return value;
-    }
-
-    static AK_FORCE_INLINE uint16_t readUint16AndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        const uint16_t value = readUint16(buffer, *pos);
-        *pos += 2;
-        return value;
-    }
-
-    static AK_FORCE_INLINE uint8_t readUint8AndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        return buffer[(*pos)++];
-    }
-
-    static AK_FORCE_INLINE int readUint(const uint8_t *const buffer,
-            const int size, const int pos) {
-        // size must be in 1 to 4.
-        ASSERT(size >= 1 && size <= 4);
-        switch (size) {
-            case 1:
-                return ByteArrayUtils::readUint8(buffer, pos);
-            case 2:
-                return ByteArrayUtils::readUint16(buffer, pos);
-            case 3:
-                return ByteArrayUtils::readUint24(buffer, pos);
-            case 4:
-                return ByteArrayUtils::readUint32(buffer, pos);
-            default:
-                return 0;
-        }
-    }
-
-    /**
-     * Code Point Reading
-     *
-     * 1 byte = bbbbbbbb match
-     * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
-     * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
-     *       unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
-     *       00011111 would be outside unicode.
-     * else: iso-latin-1 code
-     * This allows for the whole unicode range to be encoded, including chars outside of
-     * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
-     * characters which should never happen anyway (and still work, but take 3 bytes).
-     */
-    static AK_FORCE_INLINE int readCodePoint(const uint8_t *const buffer, const int pos) {
-        int p = pos;
-        return readCodePointAndAdvancePosition(buffer, &p);
-    }
-
-    static AK_FORCE_INLINE int readCodePointAndAdvancePosition(
-            const uint8_t *const buffer, int *const pos) {
-        const uint8_t firstByte = readUint8(buffer, *pos);
-        if (firstByte < MINIMUM_ONE_BYTE_CHARACTER_VALUE) {
-            if (firstByte == CHARACTER_ARRAY_TERMINATOR) {
-                *pos += 1;
-                return NOT_A_CODE_POINT;
-            } else {
-                return readUint24AndAdvancePosition(buffer, pos);
-            }
-        } else {
-            *pos += 1;
-            return firstByte;
-        }
-    }
-
-    /**
-     * String (array of code points) Reading
-     *
-     * Reads code points until the terminator is found.
-     */
-    // Returns the length of the string.
-    static int readStringAndAdvancePosition(const uint8_t *const buffer,
-            const int maxLength, int *const outBuffer, int *const pos) {
-        int length = 0;
-        int codePoint = readCodePointAndAdvancePosition(buffer, pos);
-        while (NOT_A_CODE_POINT != codePoint && length < maxLength) {
-            outBuffer[length++] = codePoint;
-            codePoint = readCodePointAndAdvancePosition(buffer, pos);
-        }
-        return length;
-    }
-
-    // Advances the position and returns the length of the string.
-    static int advancePositionToBehindString(
-            const uint8_t *const buffer, const int maxLength, int *const pos) {
-        int length = 0;
-        int codePoint = readCodePointAndAdvancePosition(buffer, pos);
-        while (NOT_A_CODE_POINT != codePoint && length < maxLength) {
-            codePoint = readCodePointAndAdvancePosition(buffer, pos);
-            length++;
-        }
-        return length;
-    }
-
-    /**
-     * String (array of code points) Writing
-     */
-    static void writeCodePointsAndAdvancePosition(uint8_t *const buffer,
-            const int *const codePoints, const int codePointCount, const bool writesTerminator,
-            int *const pos) {
-        for (int i = 0; i < codePointCount; ++i) {
-            const int codePoint = codePoints[i];
-            if (codePoint == NOT_A_CODE_POINT || codePoint == CHARACTER_ARRAY_TERMINATOR) {
-                break;
-            } else if (codePoint < MINIMUM_ONE_BYTE_CHARACTER_VALUE
-                    || codePoint > MAXIMUM_ONE_BYTE_CHARACTER_VALUE) {
-                // three bytes character.
-                writeUint24AndAdvancePosition(buffer, codePoint, pos);
-            } else {
-                // one byte character.
-                writeUint8AndAdvancePosition(buffer, codePoint, pos);
-            }
-        }
-        if (writesTerminator) {
-            writeUint8AndAdvancePosition(buffer, CHARACTER_ARRAY_TERMINATOR, pos);
-        }
-    }
-
-    static int calculateRequiredByteCountToStoreCodePoints(const int *const codePoints,
-            const int codePointCount, const bool writesTerminator) {
-        int byteCount = 0;
-        for (int i = 0; i < codePointCount; ++i) {
-            const int codePoint = codePoints[i];
-            if (codePoint == NOT_A_CODE_POINT || codePoint == CHARACTER_ARRAY_TERMINATOR) {
-                break;
-            } else if (codePoint < MINIMUM_ONE_BYTE_CHARACTER_VALUE
-                    || codePoint > MAXIMUM_ONE_BYTE_CHARACTER_VALUE) {
-                // three bytes character.
-                byteCount += 3;
-            } else {
-                // one byte character.
-                byteCount += 1;
-            }
-        }
-        if (writesTerminator) {
-            // The terminator is one byte.
-            byteCount += 1;
-        }
-        return byteCount;
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayUtils);
-
-    static const uint8_t MINIMUM_ONE_BYTE_CHARACTER_VALUE;
-    static const uint8_t MAXIMUM_ONE_BYTE_CHARACTER_VALUE;
-    static const uint8_t CHARACTER_ARRAY_TERMINATOR;
-
-    static AK_FORCE_INLINE void writeUint32AndAdvancePosition(uint8_t *const buffer,
-            const uint32_t data, int *const pos) {
-        buffer[(*pos)++] = (data >> 24) & 0xFF;
-        buffer[(*pos)++] = (data >> 16) & 0xFF;
-        buffer[(*pos)++] = (data >> 8) & 0xFF;
-        buffer[(*pos)++] = data & 0xFF;
-    }
-
-    static AK_FORCE_INLINE void writeUint24AndAdvancePosition(uint8_t *const buffer,
-            const uint32_t data, int *const pos) {
-        buffer[(*pos)++] = (data >> 16) & 0xFF;
-        buffer[(*pos)++] = (data >> 8) & 0xFF;
-        buffer[(*pos)++] = data & 0xFF;
-    }
-
-    static AK_FORCE_INLINE void writeUint16AndAdvancePosition(uint8_t *const buffer,
-            const uint16_t data, int *const pos) {
-        buffer[(*pos)++] = (data >> 8) & 0xFF;
-        buffer[(*pos)++] = data & 0xFF;
-    }
-
-    static AK_FORCE_INLINE void writeUint8AndAdvancePosition(uint8_t *const buffer,
-            const uint8_t data, int *const pos) {
-        buffer[(*pos)++] = data & 0xFF;
-    }
-};
-} // namespace latinime
-#endif /* LATINIME_BYTE_ARRAY_UTILS_H */
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
deleted file mode 100644
index b7e2a72..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.cpp
+++ /dev/null
@@ -1,144 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-
-#include <cstdio>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/structure/backward/v402/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/structure/pt_common/dynamic_pt_writing_utils.h"
-#include "suggest/policyimpl/dictionary/structure/v4/ver4_dict_buffers.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-#include "utils/time_keeper.h"
-
-namespace latinime {
-
-const char *const DictFileWritingUtils::TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE = ".tmp";
-// Enough size to describe buffer size.
-const int DictFileWritingUtils::SIZE_OF_BUFFER_SIZE_FIELD = 4;
-
-/* static */ bool DictFileWritingUtils::createEmptyDictFile(const char *const filePath,
-        const int dictVersion, const std::vector<int> localeAsCodePointVector,
-        const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap) {
-    TimeKeeper::setCurrentTime();
-    const FormatUtils::FORMAT_VERSION formatVersion = FormatUtils::getFormatVersion(dictVersion);
-    switch (formatVersion) {
-        case FormatUtils::VERSION_4:
-            return createEmptyV4DictFile<backward::v402::Ver4DictConstants,
-                    backward::v402::Ver4DictBuffers,
-                    backward::v402::Ver4DictBuffers::Ver4DictBuffersPtr>(
-                            filePath, localeAsCodePointVector, attributeMap, formatVersion);
-        case FormatUtils::VERSION_4_ONLY_FOR_TESTING:
-        case FormatUtils::VERSION_4_DEV:
-            return createEmptyV4DictFile<Ver4DictConstants, Ver4DictBuffers,
-                    Ver4DictBuffers::Ver4DictBuffersPtr>(
-                            filePath, localeAsCodePointVector, attributeMap, formatVersion);
-        default:
-            AKLOGE("Cannot create dictionary %s because format version %d is not supported.",
-                    filePath, dictVersion);
-            return false;
-    }
-}
-
-template<class DictConstants, class DictBuffers, class DictBuffersPtr>
-/* static */ bool DictFileWritingUtils::createEmptyV4DictFile(const char *const dirPath,
-        const std::vector<int> localeAsCodePointVector,
-        const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
-        const FormatUtils::FORMAT_VERSION formatVersion) {
-    HeaderPolicy headerPolicy(formatVersion, localeAsCodePointVector, attributeMap);
-    DictBuffersPtr dictBuffers = DictBuffers::createVer4DictBuffers(&headerPolicy,
-            DictConstants::MAX_DICT_EXTENDED_REGION_SIZE);
-    headerPolicy.fillInAndWriteHeaderToBuffer(true /* updatesLastDecayedTime */,
-            0 /* unigramCount */, 0 /* bigramCount */,
-            0 /* extendedRegionSize */, dictBuffers->getWritableHeaderBuffer());
-    if (!DynamicPtWritingUtils::writeEmptyDictionary(
-            dictBuffers->getWritableTrieBuffer(), 0 /* rootPos */)) {
-        AKLOGE("Empty ver4 dictionary structure cannot be created on memory.");
-        return false;
-    }
-    return dictBuffers->flush(dirPath);
-}
-
-/* static */ bool DictFileWritingUtils::flushBufferToFileWithSuffix(const char *const basePath,
-        const char *const suffix, const BufferWithExtendableBuffer *const buffer) {
-    const int filePathBufSize = FileUtils::getFilePathWithSuffixBufSize(basePath, suffix);
-    char filePath[filePathBufSize];
-    FileUtils::getFilePathWithSuffix(basePath, suffix, filePathBufSize, filePath);
-    return flushBufferToFile(filePath, buffer);
-}
-
-/* static */ bool DictFileWritingUtils::writeBufferToFileTail(FILE *const file,
-        const BufferWithExtendableBuffer *const buffer) {
-    uint8_t bufferSize[SIZE_OF_BUFFER_SIZE_FIELD];
-    int writingPos = 0;
-    ByteArrayUtils::writeUintAndAdvancePosition(bufferSize, buffer->getTailPosition(),
-            SIZE_OF_BUFFER_SIZE_FIELD, &writingPos);
-    if (fwrite(bufferSize, SIZE_OF_BUFFER_SIZE_FIELD, 1 /* count */, file) < 1) {
-        return false;
-    }
-    return writeBufferToFile(file, buffer);
-}
-
-/* static */ bool DictFileWritingUtils::flushBufferToFile(const char *const filePath,
-        const BufferWithExtendableBuffer *const buffer) {
-    const int fd = open(filePath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-    if (fd == -1) {
-        AKLOGE("File %s cannot be opened. errno: %d", filePath, errno);
-        ASSERT(false);
-        return false;
-    }
-    FILE *const file = fdopen(fd, "wb");
-    if (!file) {
-        AKLOGE("fdopen failed for the file %s. errno: %d", filePath, errno);
-        ASSERT(false);
-        return false;
-    }
-    if (!writeBufferToFile(file, buffer)) {
-        fclose(file);
-        remove(filePath);
-        AKLOGE("Buffer cannot be written to the file %s. size: %d", filePath,
-                buffer->getTailPosition());
-        ASSERT(false);
-        return false;
-    }
-    fclose(file);
-    return true;
-}
-
-// Returns whether the writing was succeeded or not.
-/* static */ bool DictFileWritingUtils::writeBufferToFile(FILE *const file,
-        const BufferWithExtendableBuffer *const buffer) {
-    const int originalBufSize = buffer->getOriginalBufferSize();
-    if (originalBufSize > 0 && fwrite(buffer->getBuffer(false /* usesAdditionalBuffer */),
-            originalBufSize, 1, file) < 1) {
-        return false;
-    }
-    const int additionalBufSize = buffer->getUsedAdditionalBufferSize();
-    if (additionalBufSize > 0 && fwrite(buffer->getBuffer(true /* usesAdditionalBuffer */),
-            additionalBufSize, 1, file) < 1) {
-        return false;
-    }
-    return true;
-}
-
-} // namespace latinime
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
deleted file mode 100644
index 4843b3b..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h
+++ /dev/null
@@ -1,67 +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.
- */
-
-#ifndef LATINIME_DICT_FILE_WRITING_UTILS_H
-#define LATINIME_DICT_FILE_WRITING_UTILS_H
-
-#include <cstdio>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-
-namespace latinime {
-
-class BufferWithExtendableBuffer;
-
-class DictFileWritingUtils {
- public:
-    static const char *const TEMP_FILE_SUFFIX_FOR_WRITING_DICT_FILE;
-
-    static bool createEmptyDictFile(const char *const filePath, const int dictVersion,
-            const std::vector<int> localeAsCodePointVector,
-            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap);
-
-    static bool flushBufferToFileWithSuffix(const char *const basePath, const char *const suffix,
-            const BufferWithExtendableBuffer *const buffer);
-
-    static bool writeBufferToFileTail(FILE *const file,
-            const BufferWithExtendableBuffer *const buffer);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(DictFileWritingUtils);
-
-    static const int SIZE_OF_BUFFER_SIZE_FIELD;
-
-    static bool createEmptyV401DictFile(const char *const filePath,
-            const std::vector<int> localeAsCodePointVector,
-            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
-            const FormatUtils::FORMAT_VERSION formatVersion);
-
-    template<class DictConstants, class DictBuffers, class DictBuffersPtr>
-    static bool createEmptyV4DictFile(const char *const filePath,
-            const std::vector<int> localeAsCodePointVector,
-            const DictionaryHeaderStructurePolicy::AttributeMap *const attributeMap,
-            const FormatUtils::FORMAT_VERSION formatVersion);
-
-    static bool flushBufferToFile(const char *const filePath,
-            const BufferWithExtendableBuffer *const buffer);
-
-    static bool writeBufferToFile(FILE *const file,
-            const BufferWithExtendableBuffer *const buffer);
-};
-} // namespace latinime
-#endif /* LATINIME_DICT_FILE_WRITING_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp
deleted file mode 100644
index fb80f38..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/file_utils.cpp
+++ /dev/null
@@ -1,171 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-
-#include <cstdio>
-#include <cstring>
-#include <dirent.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-namespace latinime {
-
-// Returns -1 on error.
-/* static */ int FileUtils::getFileSize(const char *const filePath) {
-    const int fd = open(filePath, O_RDONLY);
-    if (fd == -1) {
-        return -1;
-    }
-    struct stat statBuf;
-    if (fstat(fd, &statBuf) != 0) {
-        close(fd);
-        return -1;
-    }
-    close(fd);
-    return static_cast<int>(statBuf.st_size);
-}
-
-/* static */ bool FileUtils::existsDir(const char *const dirPath) {
-    DIR *const dir = opendir(dirPath);
-    if (dir == NULL) {
-        return false;
-    }
-    closedir(dir);
-    return true;
-}
-
-// Remove a directory and all files in the directory.
-/* static */ bool FileUtils::removeDirAndFiles(const char *const dirPath) {
-    return removeDirAndFiles(dirPath, 5 /* maxTries */);
-}
-
-// Remove a directory and all files in the directory, trying up to maxTimes.
-/* static */ bool FileUtils::removeDirAndFiles(const char *const dirPath, const int maxTries) {
-    DIR *const dir = opendir(dirPath);
-    if (dir == NULL) {
-        AKLOGE("Cannot open dir %s.", dirPath);
-        return true;
-    }
-    struct dirent *dirent;
-    while ((dirent = readdir(dir)) != NULL) {
-        if (dirent->d_type == DT_DIR) {
-            continue;
-        }
-        if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
-            continue;
-        }
-        const int filePathBufSize = getFilePathBufSize(dirPath, dirent->d_name);
-        char filePath[filePathBufSize];
-        getFilePath(dirPath, dirent->d_name, filePathBufSize, filePath);
-        if (remove(filePath) != 0) {
-            AKLOGE("Cannot remove file %s.", filePath);
-            closedir(dir);
-            return false;
-        }
-    }
-    closedir(dir);
-    if (remove(dirPath) != 0) {
-        if (maxTries > 0) {
-            // On NFS, deleting files sometimes creates new files. I'm not sure what the
-            // correct way of dealing with this is, but for the time being, this seems to work.
-            removeDirAndFiles(dirPath, maxTries - 1);
-        } else {
-            AKLOGE("Cannot remove directory %s.", dirPath);
-            return false;
-        }
-    }
-    return true;
-}
-
-/* static */ int FileUtils::getFilePathWithSuffixBufSize(const char *const filePath,
-        const char *const suffix) {
-    return strlen(filePath) + strlen(suffix) + 1 /* terminator */;
-}
-
-/* static */ void FileUtils::getFilePathWithSuffix(const char *const filePath,
-        const char *const suffix, const int filePathBufSize, char *const outFilePath) {
-    snprintf(outFilePath, filePathBufSize, "%s%s", filePath, suffix);
-}
-
-/* static */ int FileUtils::getFilePathBufSize(const char *const dirPath,
-        const char *const fileName) {
-    return strlen(dirPath) + 1 /* '/' */ + strlen(fileName) + 1 /* terminator */;
-}
-
-/* static */ void FileUtils::getFilePath(const char *const dirPath, const char *const fileName,
-        const int filePathBufSize, char *const outFilePath) {
-    snprintf(outFilePath, filePathBufSize, "%s/%s", dirPath, fileName);
-}
-
-/* static */ bool FileUtils::getFilePathWithoutSuffix(const char *const filePath,
-        const char *const suffix, const int outDirPathBufSize, char *const outDirPath) {
-    const int filePathLength = strlen(filePath);
-    const int suffixLength = strlen(suffix);
-    if (filePathLength <= suffixLength) {
-        AKLOGE("File path length (%s:%d) is shorter that suffix length (%s:%d).",
-                filePath, filePathLength, suffix, suffixLength);
-        return false;
-    }
-    const int resultFilePathLength = filePathLength - suffixLength;
-    if (outDirPathBufSize <= resultFilePathLength) {
-        AKLOGE("outDirPathBufSize is too small. filePath: %s, suffix: %s, outDirPathBufSize: %d",
-                filePath, suffix, outDirPathBufSize);
-        return false;
-    }
-    if (strncmp(filePath + resultFilePathLength, suffix, suffixLength) != 0) {
-        AKLOGE("File Path %s does not have %s as a suffix", filePath, suffix);
-        return false;
-    }
-    snprintf(outDirPath, resultFilePathLength + 1 /* terminator */, "%s", filePath);
-    return true;
-}
-
-/* static */ void FileUtils::getDirPath(const char *const filePath, const int outDirPathBufSize,
-        char *const outDirPath) {
-    for (int i = strlen(filePath) - 1; i >= 0; --i) {
-        if (filePath[i] == '/') {
-            if (i >= outDirPathBufSize) {
-                AKLOGE("outDirPathBufSize is too small. filePath: %s, outDirPathBufSize: %d",
-                        filePath, outDirPathBufSize);
-                ASSERT(false);
-                return;
-            }
-            snprintf(outDirPath, i + 1 /* terminator */, "%s", filePath);
-            return;
-        }
-    }
-}
-
-/* static */ void FileUtils::getBasename(const char *const filePath,
-        const int outNameBufSize, char *const outName) {
-    const int filePathBufSize = strlen(filePath) + 1 /* terminator */;
-    char filePathBuf[filePathBufSize];
-    snprintf(filePathBuf, filePathBufSize, "%s", filePath);
-    const char *const baseName = basename(filePathBuf);
-    const int baseNameLength = strlen(baseName);
-    if (baseNameLength >= outNameBufSize) {
-        AKLOGE("outNameBufSize is too small. filePath: %s, outNameBufSize: %d",
-                filePath, outNameBufSize);
-        return;
-    }
-    snprintf(outName, baseNameLength + 1 /* terminator */, "%s", baseName);
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
deleted file mode 100644
index fed0ae7..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.cpp
+++ /dev/null
@@ -1,239 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h"
-
-#include <algorithm>
-#include <cmath>
-#include <stdlib.h>
-
-#include "suggest/policyimpl/dictionary/header/header_policy.h"
-#include "suggest/policyimpl/dictionary/utils/probability_utils.h"
-#include "utils/time_keeper.h"
-
-namespace latinime {
-
-const int ForgettingCurveUtils::MULTIPLIER_TWO_IN_PROBABILITY_SCALE = 8;
-const int ForgettingCurveUtils::DECAY_INTERVAL_SECONDS = 2 * 60 * 60;
-
-const int ForgettingCurveUtils::MAX_LEVEL = 3;
-const int ForgettingCurveUtils::MIN_VISIBLE_LEVEL = 1;
-const int ForgettingCurveUtils::MAX_ELAPSED_TIME_STEP_COUNT = 15;
-const int ForgettingCurveUtils::DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD = 14;
-
-const float ForgettingCurveUtils::UNIGRAM_COUNT_HARD_LIMIT_WEIGHT = 1.2;
-const float ForgettingCurveUtils::BIGRAM_COUNT_HARD_LIMIT_WEIGHT = 1.2;
-
-const ForgettingCurveUtils::ProbabilityTable ForgettingCurveUtils::sProbabilityTable;
-
-// TODO: Revise the logic to decide the initial probability depending on the given probability.
-/* static */ const HistoricalInfo ForgettingCurveUtils::createUpdatedHistoricalInfo(
-        const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
-        const HistoricalInfo *const newHistoricalInfo, const HeaderPolicy *const headerPolicy) {
-    const int timestamp = newHistoricalInfo->getTimeStamp();
-    if (newProbability != NOT_A_PROBABILITY && originalHistoricalInfo->getLevel() == 0) {
-        // Add entry as a valid word.
-        const int level = clampToVisibleEntryLevelRange(newHistoricalInfo->getLevel());
-        const int count = clampToValidCountRange(newHistoricalInfo->getCount(), headerPolicy);
-        return HistoricalInfo(timestamp, level, count);
-    } else if (!originalHistoricalInfo->isValid()
-            || originalHistoricalInfo->getLevel() < newHistoricalInfo->getLevel()
-            || (originalHistoricalInfo->getLevel() == newHistoricalInfo->getLevel()
-                    && originalHistoricalInfo->getCount() < newHistoricalInfo->getCount())) {
-        // Initial information.
-        const int level = clampToValidLevelRange(newHistoricalInfo->getLevel());
-        const int count = clampToValidCountRange(newHistoricalInfo->getCount(), headerPolicy);
-        return HistoricalInfo(timestamp, level, count);
-    } else {
-        const int updatedCount = originalHistoricalInfo->getCount() + 1;
-        if (updatedCount >= headerPolicy->getForgettingCurveOccurrencesToLevelUp()) {
-            // The count exceeds the max value the level can be incremented.
-            if (originalHistoricalInfo->getLevel() >= MAX_LEVEL) {
-                // The level is already max.
-                return HistoricalInfo(timestamp,
-                        originalHistoricalInfo->getLevel(), originalHistoricalInfo->getCount());
-            } else {
-                // Level up.
-                return HistoricalInfo(timestamp,
-                        originalHistoricalInfo->getLevel() + 1, 0 /* count */);
-            }
-        } else {
-            return HistoricalInfo(timestamp, originalHistoricalInfo->getLevel(), updatedCount);
-        }
-    }
-}
-
-/* static */ int ForgettingCurveUtils::decodeProbability(
-        const HistoricalInfo *const historicalInfo, const HeaderPolicy *const headerPolicy) {
-    const int elapsedTimeStepCount = getElapsedTimeStepCount(historicalInfo->getTimeStamp(),
-            headerPolicy->getForgettingCurveDurationToLevelDown());
-    return sProbabilityTable.getProbability(
-            headerPolicy->getForgettingCurveProbabilityValuesTableId(),
-            clampToValidLevelRange(historicalInfo->getLevel()),
-            clampToValidTimeStepCountRange(elapsedTimeStepCount));
-}
-
-/* static */ int ForgettingCurveUtils::getProbability(const int unigramProbability,
-        const int bigramProbability) {
-    if (unigramProbability == NOT_A_PROBABILITY) {
-        return NOT_A_PROBABILITY;
-    } else if (bigramProbability == NOT_A_PROBABILITY) {
-        return std::min(backoff(unigramProbability), MAX_PROBABILITY);
-    } else {
-        // TODO: Investigate better way to handle bigram probability.
-        return std::min(std::max(unigramProbability,
-                bigramProbability + MULTIPLIER_TWO_IN_PROBABILITY_SCALE), MAX_PROBABILITY);
-    }
-}
-
-/* static */ bool ForgettingCurveUtils::needsToKeep(const HistoricalInfo *const historicalInfo,
-        const HeaderPolicy *const headerPolicy) {
-    return historicalInfo->getLevel() > 0
-            || getElapsedTimeStepCount(historicalInfo->getTimeStamp(),
-                    headerPolicy->getForgettingCurveDurationToLevelDown())
-                            < DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
-}
-
-/* static */ const HistoricalInfo ForgettingCurveUtils::createHistoricalInfoToSave(
-        const HistoricalInfo *const originalHistoricalInfo,
-        const HeaderPolicy *const headerPolicy) {
-    if (originalHistoricalInfo->getTimeStamp() == NOT_A_TIMESTAMP) {
-        return HistoricalInfo();
-    }
-    const int durationToLevelDownInSeconds = headerPolicy->getForgettingCurveDurationToLevelDown();
-    const int elapsedTimeStep = getElapsedTimeStepCount(
-            originalHistoricalInfo->getTimeStamp(), durationToLevelDownInSeconds);
-    if (elapsedTimeStep <= MAX_ELAPSED_TIME_STEP_COUNT) {
-        // No need to update historical info.
-        return *originalHistoricalInfo;
-    }
-    // Level down.
-    const int maxLevelDownAmonut = elapsedTimeStep / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
-    const int levelDownAmount = (maxLevelDownAmonut >= originalHistoricalInfo->getLevel()) ?
-            originalHistoricalInfo->getLevel() : maxLevelDownAmonut;
-    const int adjustedTimestampInSeconds = originalHistoricalInfo->getTimeStamp() +
-            levelDownAmount * durationToLevelDownInSeconds;
-    return HistoricalInfo(adjustedTimestampInSeconds,
-            originalHistoricalInfo->getLevel() - levelDownAmount, 0 /* count */);
-}
-
-/* static */ bool ForgettingCurveUtils::needsToDecay(const bool mindsBlockByDecay,
-        const int unigramCount, const int bigramCount, const HeaderPolicy *const headerPolicy) {
-    if (unigramCount >= getUnigramCountHardLimit(headerPolicy->getMaxUnigramCount())) {
-        // Unigram count exceeds the limit.
-        return true;
-    } else if (bigramCount >= getBigramCountHardLimit(headerPolicy->getMaxBigramCount())) {
-        // Bigram count exceeds the limit.
-        return true;
-    }
-    if (mindsBlockByDecay) {
-        return false;
-    }
-    if (headerPolicy->getLastDecayedTime() + DECAY_INTERVAL_SECONDS
-            < TimeKeeper::peekCurrentTime()) {
-        // Time to decay.
-        return true;
-    }
-    return false;
-}
-
-// See comments in ProbabilityUtils::backoff().
-/* static */ int ForgettingCurveUtils::backoff(const int unigramProbability) {
-    // See TODO comments in ForgettingCurveUtils::getProbability().
-    return unigramProbability;
-}
-
-/* static */ int ForgettingCurveUtils::getElapsedTimeStepCount(const int timestamp,
-        const int durationToLevelDownInSeconds) {
-    const int elapsedTimeInSeconds = TimeKeeper::peekCurrentTime() - timestamp;
-    const int timeStepDurationInSeconds =
-            durationToLevelDownInSeconds / (MAX_ELAPSED_TIME_STEP_COUNT + 1);
-    return elapsedTimeInSeconds / timeStepDurationInSeconds;
-}
-
-/* static */ int ForgettingCurveUtils::clampToVisibleEntryLevelRange(const int level) {
-    return std::min(std::max(level, MIN_VISIBLE_LEVEL), MAX_LEVEL);
-}
-
-/* static */ int ForgettingCurveUtils::clampToValidCountRange(const int count,
-        const HeaderPolicy *const headerPolicy) {
-    return std::min(std::max(count, 0), headerPolicy->getForgettingCurveOccurrencesToLevelUp() - 1);
-}
-
-/* static */ int ForgettingCurveUtils::clampToValidLevelRange(const int level) {
-    return std::min(std::max(level, 0), MAX_LEVEL);
-}
-
-/* static */ int ForgettingCurveUtils::clampToValidTimeStepCountRange(const int timeStepCount) {
-    return std::min(std::max(timeStepCount, 0), MAX_ELAPSED_TIME_STEP_COUNT);
-}
-
-const int ForgettingCurveUtils::ProbabilityTable::PROBABILITY_TABLE_COUNT = 4;
-const int ForgettingCurveUtils::ProbabilityTable::WEAK_PROBABILITY_TABLE_ID = 0;
-const int ForgettingCurveUtils::ProbabilityTable::MODEST_PROBABILITY_TABLE_ID = 1;
-const int ForgettingCurveUtils::ProbabilityTable::STRONG_PROBABILITY_TABLE_ID = 2;
-const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_PROBABILITY_TABLE_ID = 3;
-const int ForgettingCurveUtils::ProbabilityTable::WEAK_MAX_PROBABILITY = 127;
-const int ForgettingCurveUtils::ProbabilityTable::MODEST_BASE_PROBABILITY = 32;
-const int ForgettingCurveUtils::ProbabilityTable::STRONG_BASE_PROBABILITY = 35;
-const int ForgettingCurveUtils::ProbabilityTable::AGGRESSIVE_BASE_PROBABILITY = 40;
-
-
-ForgettingCurveUtils::ProbabilityTable::ProbabilityTable() : mTables() {
-    mTables.resize(PROBABILITY_TABLE_COUNT);
-    for (int tableId = 0; tableId < PROBABILITY_TABLE_COUNT; ++tableId) {
-        mTables[tableId].resize(MAX_LEVEL + 1);
-        for (int level = 0; level <= MAX_LEVEL; ++level) {
-            mTables[tableId][level].resize(MAX_ELAPSED_TIME_STEP_COUNT + 1);
-            const float initialProbability = getBaseProbabilityForLevel(tableId, level);
-            const float endProbability = getBaseProbabilityForLevel(tableId, level - 1);
-            for (int timeStepCount = 0; timeStepCount <= MAX_ELAPSED_TIME_STEP_COUNT;
-                    ++timeStepCount) {
-                if (level == 0) {
-                    mTables[tableId][level][timeStepCount] = NOT_A_PROBABILITY;
-                    continue;
-                }
-                const float probability = initialProbability
-                        * powf(initialProbability / endProbability,
-                                -1.0f * static_cast<float>(timeStepCount)
-                                        / static_cast<float>(MAX_ELAPSED_TIME_STEP_COUNT + 1));
-                mTables[tableId][level][timeStepCount] =
-                        std::min(std::max(static_cast<int>(probability), 1), MAX_PROBABILITY);
-            }
-        }
-    }
-}
-
-/* static */ int ForgettingCurveUtils::ProbabilityTable::getBaseProbabilityForLevel(
-        const int tableId, const int level) {
-    if (tableId == WEAK_PROBABILITY_TABLE_ID) {
-        // Max probability is 127.
-        return static_cast<float>(WEAK_MAX_PROBABILITY / (1 << (MAX_LEVEL - level)));
-    } else if (tableId == MODEST_PROBABILITY_TABLE_ID) {
-        // Max probability is 128.
-        return static_cast<float>(MODEST_BASE_PROBABILITY * (level + 1));
-    } else if (tableId == STRONG_PROBABILITY_TABLE_ID) {
-        // Max probability is 140.
-        return static_cast<float>(STRONG_BASE_PROBABILITY * (level + 1));
-    } else if (tableId == AGGRESSIVE_PROBABILITY_TABLE_ID) {
-        // Max probability is 160.
-        return static_cast<float>(AGGRESSIVE_BASE_PROBABILITY * (level + 1));
-    } else {
-        return NOT_A_PROBABILITY;
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
deleted file mode 100644
index 9910777..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/forgetting_curve_utils.h
+++ /dev/null
@@ -1,113 +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.
- */
-
-#ifndef LATINIME_FORGETTING_CURVE_UTILS_H
-#define LATINIME_FORGETTING_CURVE_UTILS_H
-
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/historical_info.h"
-
-namespace latinime {
-
-class HeaderPolicy;
-
-class ForgettingCurveUtils {
- public:
-    static const HistoricalInfo createUpdatedHistoricalInfo(
-            const HistoricalInfo *const originalHistoricalInfo, const int newProbability,
-            const HistoricalInfo *const newHistoricalInfo, const HeaderPolicy *const headerPolicy);
-
-    static const HistoricalInfo createHistoricalInfoToSave(
-            const HistoricalInfo *const originalHistoricalInfo,
-            const HeaderPolicy *const headerPolicy);
-
-    static int decodeProbability(const HistoricalInfo *const historicalInfo,
-            const HeaderPolicy *const headerPolicy);
-
-    static int getProbability(const int encodedUnigramProbability,
-            const int encodedBigramProbability);
-
-    static bool needsToKeep(const HistoricalInfo *const historicalInfo,
-            const HeaderPolicy *const headerPolicy);
-
-    static bool needsToDecay(const bool mindsBlockByDecay, const int unigramCount,
-            const int bigramCount, const HeaderPolicy *const headerPolicy);
-
-    AK_FORCE_INLINE static int getUnigramCountHardLimit(const int maxUnigramCount) {
-        return static_cast<int>(static_cast<float>(maxUnigramCount)
-                * UNIGRAM_COUNT_HARD_LIMIT_WEIGHT);
-    }
-
-    AK_FORCE_INLINE static int getBigramCountHardLimit(const int maxBigramCount) {
-        return static_cast<int>(static_cast<float>(maxBigramCount)
-                * BIGRAM_COUNT_HARD_LIMIT_WEIGHT);
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ForgettingCurveUtils);
-
-    class ProbabilityTable {
-     public:
-        ProbabilityTable();
-
-        int getProbability(const int tableId, const int level,
-                const int elapsedTimeStepCount) const {
-            return mTables[tableId][level][elapsedTimeStepCount];
-        }
-
-     private:
-        DISALLOW_COPY_AND_ASSIGN(ProbabilityTable);
-
-        static const int PROBABILITY_TABLE_COUNT;
-        static const int WEAK_PROBABILITY_TABLE_ID;
-        static const int MODEST_PROBABILITY_TABLE_ID;
-        static const int STRONG_PROBABILITY_TABLE_ID;
-        static const int AGGRESSIVE_PROBABILITY_TABLE_ID;
-
-        static const int WEAK_MAX_PROBABILITY;
-        static const int MODEST_BASE_PROBABILITY;
-        static const int STRONG_BASE_PROBABILITY;
-        static const int AGGRESSIVE_BASE_PROBABILITY;
-
-        std::vector<std::vector<std::vector<int>>> mTables;
-
-        static int getBaseProbabilityForLevel(const int tableId, const int level);
-    };
-
-    static const int MULTIPLIER_TWO_IN_PROBABILITY_SCALE;
-    static const int DECAY_INTERVAL_SECONDS;
-
-    static const int MAX_LEVEL;
-    static const int MIN_VISIBLE_LEVEL;
-    static const int MAX_ELAPSED_TIME_STEP_COUNT;
-    static const int DISCARD_LEVEL_ZERO_ENTRY_TIME_STEP_COUNT_THRESHOLD;
-
-    static const float UNIGRAM_COUNT_HARD_LIMIT_WEIGHT;
-    static const float BIGRAM_COUNT_HARD_LIMIT_WEIGHT;
-
-    static const ProbabilityTable sProbabilityTable;
-
-    static int backoff(const int unigramProbability);
-    static int getElapsedTimeStepCount(const int timestamp, const int durationToLevelDown);
-    static int clampToVisibleEntryLevelRange(const int level);
-    static int clampToValidLevelRange(const int level);
-    static int clampToValidCountRange(const int count, const HeaderPolicy *const headerPolicy);
-    static int clampToValidTimeStepCountRange(const int timeStepCount);
-};
-} // namespace latinime
-#endif /* LATINIME_FORGETTING_CURVE_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
deleted file mode 100644
index 1916ea5..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.cpp
+++ /dev/null
@@ -1,67 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/format_utils.h"
-
-#include "suggest/policyimpl/dictionary/utils/byte_array_utils.h"
-
-namespace latinime {
-
-const uint32_t FormatUtils::MAGIC_NUMBER = 0x9BC13AFE;
-
-// Magic number (4 bytes), version (2 bytes), flags (2 bytes), header size (4 bytes) = 12
-const int FormatUtils::DICTIONARY_MINIMUM_SIZE = 12;
-
-/* static */ FormatUtils::FORMAT_VERSION FormatUtils::getFormatVersion(const int formatVersion) {
-    switch (formatVersion) {
-        case VERSION_2:
-            return VERSION_2;
-        case VERSION_4_ONLY_FOR_TESTING:
-            return VERSION_4_ONLY_FOR_TESTING;
-        case VERSION_4:
-            return VERSION_4;
-        case VERSION_4_DEV:
-            return VERSION_4_DEV;
-        default:
-            return UNKNOWN_VERSION;
-    }
-}
-/* static */ FormatUtils::FORMAT_VERSION FormatUtils::detectFormatVersion(
-        const uint8_t *const dict, const int dictSize) {
-    // The magic number is stored big-endian.
-    // If the dictionary is less than 4 bytes, we can't even read the magic number, so we don't
-    // understand this format.
-    if (dictSize < DICTIONARY_MINIMUM_SIZE) {
-        return UNKNOWN_VERSION;
-    }
-    const uint32_t magicNumber = ByteArrayUtils::readUint32(dict, 0);
-    switch (magicNumber) {
-        case MAGIC_NUMBER:
-            // The layout of the header is as follows:
-            // Magic number (4 bytes) 0x9B 0xC1 0x3A 0xFE
-            // Dictionary format version number (2 bytes)
-            // Options (2 bytes)
-            // Header size (4 bytes) : integer, big endian
-            // Conceptually this converts the hardcoded value of the bytes in the file into
-            // the symbolic value we use in the code. But we want the constants to be the
-            // same so we use them for both here.
-            return getFormatVersion(ByteArrayUtils::readUint16(dict, 4));
-        default:
-            return UNKNOWN_VERSION;
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
deleted file mode 100644
index 55ad579..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/format_utils.h
+++ /dev/null
@@ -1,53 +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.
- */
-
-#ifndef LATINIME_FORMAT_UTILS_H
-#define LATINIME_FORMAT_UTILS_H
-
-#include <cstdint>
-
-#include "defines.h"
-
-namespace latinime {
-
-/**
- * Methods to handle binary dictionary format version.
- */
-class FormatUtils {
- public:
-    enum FORMAT_VERSION {
-        // These MUST have the same values as the relevant constants in FormatSpec.java.
-        VERSION_2 = 2,
-        VERSION_4_ONLY_FOR_TESTING = 399,
-        VERSION_4 = 402,
-        VERSION_4_DEV = 403,
-        UNKNOWN_VERSION = -1
-    };
-
-    // 32 bit magic number is stored at the beginning of the dictionary header to reject
-    // unsupported or obsolete dictionary formats.
-    static const uint32_t MAGIC_NUMBER;
-
-    static FORMAT_VERSION getFormatVersion(const int formatVersion);
-    static FORMAT_VERSION detectFormatVersion(const uint8_t *const dict, const int dictSize);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(FormatUtils);
-
-    static const int DICTIONARY_MINIMUM_SIZE;
-};
-} // namespace latinime
-#endif /* LATINIME_FORMAT_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h b/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
deleted file mode 100644
index 428ca86..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/historical_info.h
+++ /dev/null
@@ -1,58 +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.
- */
-
-#ifndef LATINIME_HISTORICAL_INFO_H
-#define LATINIME_HISTORICAL_INFO_H
-
-#include "defines.h"
-
-namespace latinime {
-
-class HistoricalInfo {
- public:
-    // Invalid historical info.
-    HistoricalInfo()
-            : mTimestamp(NOT_A_TIMESTAMP), mLevel(0), mCount(0) {}
-
-    HistoricalInfo(const int timestamp, const int level, const int count)
-            : mTimestamp(timestamp), mLevel(level), mCount(count) {}
-
-    bool isValid() const {
-        return mTimestamp != NOT_A_TIMESTAMP;
-    }
-
-    int getTimeStamp() const {
-        return mTimestamp;
-    }
-
-    int getLevel() const {
-        return mLevel;
-    }
-
-    int getCount() const {
-        return mCount;
-    }
-
- private:
-    // Copy constructor is public to use this class as a type of return value.
-    DISALLOW_ASSIGNMENT_OPERATOR(HistoricalInfo);
-
-    const int mTimestamp;
-    const int mLevel;
-    const int mCount;
-};
-} // namespace latinime
-#endif /* LATINIME_HISTORICAL_INFO_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
deleted file mode 100644
index 4a126ff..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/mmapped_buffer.cpp
+++ /dev/null
@@ -1,98 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
-
-#include <cerrno>
-#include <climits>
-#include <cstdio>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "suggest/policyimpl/dictionary/utils/file_utils.h"
-
-namespace latinime {
-
-/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
-        const char *const path, const int bufferOffset, const int bufferSize,
-        const bool isUpdatable) {
-    const int mmapFd = open(path, O_RDONLY);
-    if (mmapFd < 0) {
-        AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
-        return nullptr;
-    }
-    const int pagesize = sysconf(_SC_PAGESIZE);
-    const int offset = bufferOffset % pagesize;
-    int alignedOffset = bufferOffset - offset;
-    int alignedSize = bufferSize + offset;
-    const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
-    void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
-            alignedOffset);
-    if (mmappedBuffer == MAP_FAILED) {
-        AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
-        close(mmapFd);
-        return nullptr;
-    }
-    uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
-    if (!buffer) {
-        AKLOGE("DICT: buffer is null");
-        close(mmapFd);
-        return nullptr;
-    }
-    return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
-            mmapFd, isUpdatable));
-}
-
-/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
-        const char *const path, const bool isUpdatable) {
-    const int fileSize = FileUtils::getFileSize(path);
-    if (fileSize == -1) {
-        return nullptr;
-    } else if (fileSize == 0) {
-        return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
-    } else {
-        return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
-    }
-}
-
-/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
-        const char *const dirPath, const char *const fileName, const bool isUpdatable) {
-    const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
-    char filePath[filePathBufferSize];
-    const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
-            fileName);
-    if (filePathLength >= filePathBufferSize) {
-        return nullptr;
-    }
-    return openBuffer(filePath, isUpdatable);
-}
-
-MmappedBuffer::~MmappedBuffer() {
-    if (mAlignedSize == 0) {
-        return;
-    }
-    int ret = munmap(mMmappedBuffer, mAlignedSize);
-    if (ret != 0) {
-        AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
-    }
-    ret = close(mMmapFd);
-    if (ret != 0) {
-        AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
-    }
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h
deleted file mode 100644
index 3b339e6..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/probability_utils.h
+++ /dev/null
@@ -1,54 +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.
- */
-
-#ifndef LATINIME_PROBABILITY_UTILS_H
-#define LATINIME_PROBABILITY_UTILS_H
-
-#include "defines.h"
-
-namespace latinime {
-
-// TODO: Quit using bigram probability to indicate the delta.
-class ProbabilityUtils {
- public:
-    static AK_FORCE_INLINE int backoff(const int unigramProbability) {
-        return unigramProbability;
-        // For some reason, applying the backoff weight gives bad results in tests. To apply the
-        // backoff weight, we divide the probability by 2, which in our storing format means
-        // decreasing the score by 8.
-        // TODO: figure out what's wrong with this.
-        // return unigramProbability > 8 ?
-        //         unigramProbability - 8 : (0 == unigramProbability ? 0 : 8);
-    }
-
-    static AK_FORCE_INLINE int computeProbabilityForBigram(
-            const int unigramProbability, const int bigramProbability) {
-        // We divide the range [unigramProbability..255] in 16.5 steps - in other words, we want
-        // the unigram probability to be the median value of the 17th step from the top. A value of
-        // 0 for the bigram probability represents the middle of the 16th step from the top,
-        // while a value of 15 represents the middle of the top step.
-        // See makedict.BinaryDictEncoder#makeBigramFlags for details.
-        const float stepSize = static_cast<float>(MAX_PROBABILITY - unigramProbability)
-                / (1.5f + MAX_BIGRAM_ENCODED_PROBABILITY);
-        return unigramProbability
-                + static_cast<int>(static_cast<float>(bigramProbability + 1) * stepSize);
-    }
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(ProbabilityUtils);
-};
-}
-#endif /* LATINIME_PROBABILITY_UTILS_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.cpp
deleted file mode 100644
index d336306..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.cpp
+++ /dev/null
@@ -1,101 +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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/sparse_table.h"
-
-namespace latinime {
-
-const int SparseTable::NOT_EXIST = -1;
-const int SparseTable::INDEX_SIZE = 4;
-
-bool SparseTable::contains(const int id) const {
-    const int readingPos = getPosInIndexTable(id);
-    if (id < 0 || mIndexTableBuffer->getTailPosition() <= readingPos) {
-        return false;
-    }
-    const int index = mIndexTableBuffer->readUint(INDEX_SIZE, readingPos);
-    return index != NOT_EXIST;
-}
-
-uint32_t SparseTable::get(const int id) const {
-    const int indexTableReadingPos = getPosInIndexTable(id);
-    const int index = mIndexTableBuffer->readUint(INDEX_SIZE, indexTableReadingPos);
-    const int contentTableReadingPos = getPosInContentTable(id, index);
-    if (contentTableReadingPos < 0
-            || contentTableReadingPos >= mContentTableBuffer->getTailPosition()) {
-        AKLOGE("contentTableReadingPos(%d) is invalid. id: %d, index: %d",
-                contentTableReadingPos, id, index);
-        return NOT_A_DICT_POS;
-    }
-    const int contentValue = mContentTableBuffer->readUint(mDataSize, contentTableReadingPos);
-    return contentValue == NOT_EXIST ? NOT_A_DICT_POS : contentValue;
-}
-
-bool SparseTable::set(const int id, const uint32_t value) {
-    const int posInIndexTable = getPosInIndexTable(id);
-    // Extends the index table if needed.
-    int tailPos = mIndexTableBuffer->getTailPosition();
-    while (tailPos <= posInIndexTable) {
-        if (!mIndexTableBuffer->writeUintAndAdvancePosition(NOT_EXIST, INDEX_SIZE, &tailPos)) {
-            AKLOGE("cannot extend index table. tailPos: %d to: %d", tailPos, posInIndexTable);
-            return false;
-        }
-    }
-    if (contains(id)) {
-        // The entry is already in the content table.
-        const int index = mIndexTableBuffer->readUint(INDEX_SIZE, posInIndexTable);
-        if (!mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index))) {
-            AKLOGE("cannot update value %d. pos: %d, tailPos: %d, mDataSize: %d", value,
-                    getPosInContentTable(id, index), mContentTableBuffer->getTailPosition(),
-                    mDataSize);
-            return false;
-        }
-        return true;
-    }
-    // The entry is not in the content table.
-    // Create new entry in the content table.
-    const int index = getIndexFromContentTablePos(mContentTableBuffer->getTailPosition());
-    if (!mIndexTableBuffer->writeUint(index, INDEX_SIZE, posInIndexTable)) {
-        AKLOGE("cannot write index %d. pos %d", index, posInIndexTable);
-        return false;
-    }
-    // Write a new block that containing the entry to be set.
-    int writingPos = getPosInContentTable(0 /* id */, index);
-    for (int i = 0; i < mBlockSize; ++i) {
-        if (!mContentTableBuffer->writeUintAndAdvancePosition(NOT_EXIST, mDataSize,
-                &writingPos)) {
-            AKLOGE("cannot write content table to extend. writingPos: %d, tailPos: %d, "
-                    "mDataSize: %d", writingPos, mContentTableBuffer->getTailPosition(), mDataSize);
-            return false;
-        }
-    }
-    return mContentTableBuffer->writeUint(value, mDataSize, getPosInContentTable(id, index));
-}
-
-int SparseTable::getIndexFromContentTablePos(const int contentTablePos) const {
-    return contentTablePos / mDataSize / mBlockSize;
-}
-
-int SparseTable::getPosInIndexTable(const int id) const {
-    return (id / mBlockSize) * INDEX_SIZE;
-}
-
-int SparseTable::getPosInContentTable(const int id, const int index) const {
-    const int offset = id % mBlockSize;
-    return (index * mBlockSize + offset) * mDataSize;
-}
-
-} // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h b/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h
deleted file mode 100644
index fca8120..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/sparse_table.h
+++ /dev/null
@@ -1,61 +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.
- */
-
-#ifndef LATINIME_SPARSE_TABLE_H
-#define LATINIME_SPARSE_TABLE_H
-
-#include <cstdint>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-namespace latinime {
-
-// Note that there is a corresponding implementation in SparseTable.java.
-// TODO: Support multiple content buffers.
-class SparseTable {
- public:
-    SparseTable(BufferWithExtendableBuffer *const indexTableBuffer,
-            BufferWithExtendableBuffer *const contentTableBuffer, const int blockSize,
-            const int dataSize)
-            : mIndexTableBuffer(indexTableBuffer), mContentTableBuffer(contentTableBuffer),
-              mBlockSize(blockSize), mDataSize(dataSize) {}
-
-    bool contains(const int id) const;
-
-    uint32_t get(const int id) const;
-
-    bool set(const int id, const uint32_t value);
-
- private:
-    DISALLOW_IMPLICIT_CONSTRUCTORS(SparseTable);
-
-    int getIndexFromContentTablePos(const int contentTablePos) const;
-
-    int getPosInIndexTable(const int id) const;
-
-    int getPosInContentTable(const int id, const int index) const;
-
-    static const int NOT_EXIST;
-    static const int INDEX_SIZE;
-
-    BufferWithExtendableBuffer *const mIndexTableBuffer;
-    BufferWithExtendableBuffer *const mContentTableBuffer;
-    const int mBlockSize;
-    const int mDataSize;
-};
-} // namespace latinime
-#endif /* LATINIME_SPARSE_TABLE_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
deleted file mode 100644
index 407b8ef..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/trie_map.h"
-
-#include "suggest/policyimpl/dictionary/utils/dict_file_writing_utils.h"
-
-namespace latinime {
-
-const int TrieMap::INVALID_INDEX = -1;
-const int TrieMap::FIELD0_SIZE = 4;
-const int TrieMap::FIELD1_SIZE = 3;
-const int TrieMap::ENTRY_SIZE = FIELD0_SIZE + FIELD1_SIZE;
-const uint32_t TrieMap::VALUE_FLAG = 0x400000;
-const uint32_t TrieMap::VALUE_MASK = 0x3FFFFF;
-const uint32_t TrieMap::TERMINAL_LINK_FLAG = 0x800000;
-const uint32_t TrieMap::TERMINAL_LINK_MASK = 0x7FFFFF;
-const int TrieMap::NUM_OF_BITS_USED_FOR_ONE_LEVEL = 5;
-const uint32_t TrieMap::LABEL_MASK = 0x1F;
-const int TrieMap::MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL = 1 << NUM_OF_BITS_USED_FOR_ONE_LEVEL;
-const int TrieMap::ROOT_BITMAP_ENTRY_INDEX = 0;
-const int TrieMap::ROOT_BITMAP_ENTRY_POS = MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL * FIELD0_SIZE;
-const TrieMap::Entry TrieMap::EMPTY_BITMAP_ENTRY = TrieMap::Entry(0, 0);
-const uint64_t TrieMap::MAX_VALUE =
-        (static_cast<uint64_t>(1) << ((FIELD0_SIZE + FIELD1_SIZE) * CHAR_BIT)) - 1;
-const int TrieMap::MAX_BUFFER_SIZE = TERMINAL_LINK_MASK * ENTRY_SIZE;
-
-TrieMap::TrieMap() : mBuffer(MAX_BUFFER_SIZE) {
-    mBuffer.extend(ROOT_BITMAP_ENTRY_POS);
-    writeEntry(EMPTY_BITMAP_ENTRY, ROOT_BITMAP_ENTRY_INDEX);
-}
-
-TrieMap::TrieMap(const ReadWriteByteArrayView buffer)
-        : mBuffer(buffer, BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE) {}
-
-void TrieMap::dump(const int from, const int to) const {
-    AKLOGI("BufSize: %d", mBuffer.getTailPosition());
-    for (int i = from; i < to; ++i) {
-        AKLOGI("Entry[%d]: %x, %x", i, readField0(i), readField1(i));
-    }
-    int unusedRegionSize = 0;
-    for (int i = 1; i <= MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL; ++i) {
-        int index = readEmptyTableLink(i);
-        while (index != ROOT_BITMAP_ENTRY_INDEX) {
-            index = readField0(index);
-            unusedRegionSize += i;
-        }
-    }
-    AKLOGI("Unused Size: %d", unusedRegionSize);
-}
-
-int TrieMap::getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIndex) {
-    const Entry bitmapEntry = readEntry(bitmapEntryIndex);
-    const uint32_t unsignedKey = static_cast<uint32_t>(key);
-    const int terminalEntryIndex = getTerminalEntryIndex(
-            unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntry, 0 /* level */);
-    if (terminalEntryIndex == INVALID_INDEX) {
-        // Not found.
-        return INVALID_INDEX;
-    }
-    const Entry terminalEntry = readEntry(terminalEntryIndex);
-    if (terminalEntry.hasTerminalLink()) {
-        return terminalEntry.getValueEntryIndex() + 1;
-    }
-    // Create a value entry and a bitmap entry.
-    const int valueEntryIndex = allocateTable(2 /* entryCount */);
-    if (!writeEntry(Entry(0, terminalEntry.getValue()), valueEntryIndex)) {
-        return INVALID_INDEX;
-    }
-    if (!writeEntry(EMPTY_BITMAP_ENTRY, valueEntryIndex + 1)) {
-        return INVALID_INDEX;
-    }
-    if (!writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, valueEntryIndex)) {
-        return INVALID_INDEX;
-    }
-    return valueEntryIndex + 1;
-}
-
-const TrieMap::Result TrieMap::get(const int key, const int bitmapEntryIndex) const {
-    const uint32_t unsignedKey = static_cast<uint32_t>(key);
-    return getInternal(unsignedKey, getBitShuffledKey(unsignedKey), bitmapEntryIndex,
-            0 /* level */);
-}
-
-bool TrieMap::put(const int key, const uint64_t value, const int bitmapEntryIndex) {
-    if (value > MAX_VALUE) {
-        return false;
-    }
-    const uint32_t unsignedKey = static_cast<uint32_t>(key);
-    return putInternal(unsignedKey, value, getBitShuffledKey(unsignedKey), bitmapEntryIndex,
-            readEntry(bitmapEntryIndex), 0 /* level */);
-}
-
-bool TrieMap::save(FILE *const file) const {
-    return DictFileWritingUtils::writeBufferToFileTail(file, &mBuffer);
-}
-
-/**
- * Iterate next entry in a certain level.
- *
- * @param iterationState the iteration state that will be read and updated in this method.
- * @param outKey the output key
- * @return Result instance. mIsValid is false when all entries are iterated.
- */
-const TrieMap::Result TrieMap::iterateNext(std::vector<TableIterationState> *const iterationState,
-        int *const outKey) const {
-    while (!iterationState->empty()) {
-        TableIterationState &state = iterationState->back();
-        if (state.mTableSize <= state.mCurrentIndex) {
-            // Move to parent.
-            iterationState->pop_back();
-        } else {
-            const int entryIndex = state.mTableIndex + state.mCurrentIndex;
-            state.mCurrentIndex += 1;
-            const Entry entry = readEntry(entryIndex);
-            if (entry.isBitmapEntry()) {
-                // Move to child.
-                iterationState->emplace_back(popCount(entry.getBitmap()), entry.getTableIndex());
-            } else {
-                if (outKey) {
-                    *outKey = entry.getKey();
-                }
-                if (!entry.hasTerminalLink()) {
-                    return Result(entry.getValue(), true, INVALID_INDEX);
-                }
-                const int valueEntryIndex = entry.getValueEntryIndex();
-                const Entry valueEntry = readEntry(valueEntryIndex);
-                return Result(valueEntry.getValueOfValueEntry(), true, valueEntryIndex + 1);
-            }
-        }
-    }
-    // Visited all entries.
-    return Result(0, false, INVALID_INDEX);
-}
-
-/**
- * Shuffle bits of the key in the fixed order.
- *
- * This method is used as a hash function. This returns different values for different inputs.
- */
-uint32_t TrieMap::getBitShuffledKey(const uint32_t key) const {
-    uint32_t shuffledKey = 0;
-    for (int i = 0; i < 4; ++i) {
-        const uint32_t keyPiece = (key >> (i * 8)) & 0xFF;
-        shuffledKey ^= ((keyPiece ^ (keyPiece << 7) ^ (keyPiece << 14) ^ (keyPiece << 21))
-                & 0x11111111) << i;
-    }
-    return shuffledKey;
-}
-
-bool TrieMap::writeValue(const uint64_t value, const int terminalEntryIndex) {
-    if (value <= VALUE_MASK) {
-        // Write value into the terminal entry.
-        return writeField1(value | VALUE_FLAG, terminalEntryIndex);
-    }
-    // Create value entry and write value.
-    const int valueEntryIndex = allocateTable(2 /* entryCount */);
-    if (!writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex)) {
-        return false;
-    }
-    if (!writeEntry(EMPTY_BITMAP_ENTRY, valueEntryIndex + 1)) {
-        return false;
-    }
-    return writeField1(valueEntryIndex | TERMINAL_LINK_FLAG, terminalEntryIndex);
-}
-
-bool TrieMap::updateValue(const Entry &terminalEntry, const uint64_t value,
-        const int terminalEntryIndex) {
-    if (!terminalEntry.hasTerminalLink()) {
-        return writeValue(value, terminalEntryIndex);
-    }
-    const int valueEntryIndex = terminalEntry.getValueEntryIndex();
-    return writeEntry(Entry(value >> (FIELD1_SIZE * CHAR_BIT), value), valueEntryIndex);
-}
-
-bool TrieMap::freeTable(const int tableIndex, const int entryCount) {
-    if (!writeField0(readEmptyTableLink(entryCount), tableIndex)) {
-        return false;
-    }
-    return writeEmptyTableLink(tableIndex, entryCount);
-}
-
-/**
- * Allocate table with entryCount-entries. Reuse freed table if possible.
- */
-int TrieMap::allocateTable(const int entryCount) {
-    if (entryCount > 0 && entryCount <= MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL) {
-        const int tableIndex = readEmptyTableLink(entryCount);
-        if (tableIndex > 0) {
-            if (!writeEmptyTableLink(readField0(tableIndex), entryCount)) {
-                return INVALID_INDEX;
-            }
-            // Reuse the table.
-            return tableIndex;
-        }
-    }
-    // Allocate memory space at tail position of the buffer.
-    const int mapIndex = getTailEntryIndex();
-    if (!mBuffer.extend(entryCount * ENTRY_SIZE)) {
-        return INVALID_INDEX;
-    }
-    return mapIndex;
-}
-
-int TrieMap::getTerminalEntryIndex(const uint32_t key, const uint32_t hashedKey,
-        const Entry &bitmapEntry, const int level) const {
-    const int label = getLabel(hashedKey, level);
-    if (!exists(bitmapEntry.getBitmap(), label)) {
-        return INVALID_INDEX;
-    }
-    const int entryIndex = bitmapEntry.getTableIndex() + popCount(bitmapEntry.getBitmap(), label);
-    const Entry entry = readEntry(entryIndex);
-    if (entry.isBitmapEntry()) {
-        // Move to the next level.
-        return getTerminalEntryIndex(key, hashedKey, entry, level + 1);
-    }
-    if (entry.getKey() == key) {
-        // Terminal entry is found.
-        return entryIndex;
-    }
-    return INVALID_INDEX;
-}
-
-/**
- * Get Result corresponding to the key.
- *
- * @param key the key.
- * @param hashedKey the hashed key.
- * @param bitmapEntryIndex the index of bitmap entry
- * @param level current level
- * @return Result instance corresponding to the key. mIsValid indicates whether the key is in the
- * map.
- */
-const TrieMap::Result TrieMap::getInternal(const uint32_t key, const uint32_t hashedKey,
-        const int bitmapEntryIndex, const int level) const {
-    const int terminalEntryIndex = getTerminalEntryIndex(key, hashedKey,
-            readEntry(bitmapEntryIndex), level);
-    if (terminalEntryIndex == INVALID_INDEX) {
-        // Not found.
-        return Result(0, false, INVALID_INDEX);
-    }
-    const Entry terminalEntry = readEntry(terminalEntryIndex);
-    if (!terminalEntry.hasTerminalLink()) {
-        return Result(terminalEntry.getValue(), true, INVALID_INDEX);
-    }
-    const int valueEntryIndex = terminalEntry.getValueEntryIndex();
-    const Entry valueEntry = readEntry(valueEntryIndex);
-    return Result(valueEntry.getValueOfValueEntry(), true, valueEntryIndex + 1);
-}
-
-/**
- * Put key to value mapping to the map.
- *
- * @param key the key.
- * @param value the value
- * @param hashedKey the hashed key.
- * @param bitmapEntryIndex the index of bitmap entry
- * @param bitmapEntry the bitmap entry
- * @param level current level
- * @return whether the key-value has been correctly inserted to the map or not.
- */
-bool TrieMap::putInternal(const uint32_t key, const uint64_t value, const uint32_t hashedKey,
-        const int bitmapEntryIndex, const Entry &bitmapEntry, const int level) {
-    const int label = getLabel(hashedKey, level);
-    const uint32_t bitmap = bitmapEntry.getBitmap();
-    const int mapIndex = bitmapEntry.getTableIndex();
-    if (!exists(bitmap, label)) {
-        // Current map doesn't contain the label.
-        return addNewEntryByExpandingTable(key, value, mapIndex, bitmap, bitmapEntryIndex, label);
-    }
-    const int entryIndex = mapIndex + popCount(bitmap, label);
-    const Entry entry = readEntry(entryIndex);
-    if (entry.isBitmapEntry()) {
-        // Bitmap entry is found. Go to the next level.
-        return putInternal(key, value, hashedKey, entryIndex, entry, level + 1);
-    }
-    if (entry.getKey() == key) {
-        // Terminal entry for the key is found. Update the value.
-        return updateValue(entry, value, entryIndex);
-    }
-    // Conflict with the existing key.
-    return addNewEntryByResolvingConflict(key, value, hashedKey, entry, entryIndex, level);
-}
-
-/**
- * Resolve a conflict in the current level and add new entry.
- *
- * @param key the key
- * @param value the value
- * @param hashedKey the hashed key
- * @param conflictedEntry the existing conflicted entry
- * @param conflictedEntryIndex the index of existing conflicted entry
- * @param level current level
- * @return whether the key-value has been correctly inserted to the map or not.
- */
-bool TrieMap::addNewEntryByResolvingConflict(const uint32_t key, const uint64_t value,
-        const uint32_t hashedKey, const Entry &conflictedEntry, const int conflictedEntryIndex,
-        const int level) {
-    const int conflictedKeyNextLabel =
-            getLabel(getBitShuffledKey(conflictedEntry.getKey()), level + 1);
-    const int nextLabel = getLabel(hashedKey, level + 1);
-    if (conflictedKeyNextLabel == nextLabel) {
-        // Conflicted again in the next level.
-        const int newTableIndex = allocateTable(1 /* entryCount */);
-        if (newTableIndex == INVALID_INDEX) {
-            return false;
-        }
-        if (!writeEntry(conflictedEntry, newTableIndex)) {
-            return false;
-        }
-        const Entry newBitmapEntry(setExist(0 /* bitmap */, nextLabel), newTableIndex);
-        if (!writeEntry(newBitmapEntry, conflictedEntryIndex)) {
-            return false;
-        }
-        return putInternal(key, value, hashedKey, conflictedEntryIndex, newBitmapEntry, level + 1);
-    }
-    // The conflict has been resolved. Create a table that contains 2 entries.
-    const int newTableIndex = allocateTable(2 /* entryCount */);
-    if (newTableIndex == INVALID_INDEX) {
-        return false;
-    }
-    if (nextLabel < conflictedKeyNextLabel) {
-        if (!writeTerminalEntry(key, value, newTableIndex)) {
-            return false;
-        }
-        if (!writeEntry(conflictedEntry, newTableIndex + 1)) {
-            return false;
-        }
-    } else { // nextLabel > conflictedKeyNextLabel
-        if (!writeEntry(conflictedEntry, newTableIndex)) {
-            return false;
-        }
-        if (!writeTerminalEntry(key, value, newTableIndex + 1)) {
-            return false;
-        }
-    }
-    const uint32_t updatedBitmap =
-            setExist(setExist(0 /* bitmap */, nextLabel), conflictedKeyNextLabel);
-    return writeEntry(Entry(updatedBitmap, newTableIndex), conflictedEntryIndex);
-}
-
-/**
- * Add new entry to the existing table.
- */
-bool TrieMap::addNewEntryByExpandingTable(const uint32_t key, const uint64_t value,
-        const int tableIndex, const uint32_t bitmap, const int bitmapEntryIndex, const int label) {
-    // Current map doesn't contain the label.
-    const int entryCount = popCount(bitmap);
-    const int newTableIndex = allocateTable(entryCount + 1);
-    if (newTableIndex == INVALID_INDEX) {
-        return false;
-    }
-    const int newEntryIndexInTable = popCount(bitmap, label);
-    // Copy from existing table to the new table.
-    for (int i = 0; i < entryCount; ++i) {
-        if (!copyEntry(tableIndex + i, newTableIndex + i + (i >= newEntryIndexInTable ? 1 : 0))) {
-            return false;
-        }
-    }
-    // Write new terminal entry.
-    if (!writeTerminalEntry(key, value, newTableIndex + newEntryIndexInTable)) {
-        return false;
-    }
-    // Update bitmap.
-    if (!writeEntry(Entry(setExist(bitmap, label), newTableIndex), bitmapEntryIndex)) {
-        return false;
-    }
-    if (entryCount > 0) {
-        return freeTable(tableIndex, entryCount);
-    }
-    return true;
-}
-
-}  // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h b/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
deleted file mode 100644
index 3e5c401..0000000
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/trie_map.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 2014, 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.
- */
-
-#ifndef LATINIME_TRIE_MAP_H
-#define LATINIME_TRIE_MAP_H
-
-#include <climits>
-#include <cstdint>
-#include <cstdio>
-#include <vector>
-
-#include "defines.h"
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-#include "utils/byte_array_view.h"
-
-namespace latinime {
-
-/**
- * Trie map derived from Phil Bagwell's Hash Array Mapped Trie.
- * key is int and value is uint64_t.
- * This supports multiple level map. Terminal entries can have a bitmap for the next level map.
- * This doesn't support root map resizing.
- */
-class TrieMap {
- public:
-    struct Result {
-        const uint64_t mValue;
-        const bool mIsValid;
-        const int mNextLevelBitmapEntryIndex;
-
-        Result(const uint64_t value, const bool isValid, const int nextLevelBitmapEntryIndex)
-                : mValue(value), mIsValid(isValid),
-                  mNextLevelBitmapEntryIndex(nextLevelBitmapEntryIndex) {}
-    };
-
-    /**
-     * Struct to record iteration state in a table.
-     */
-    struct TableIterationState {
-        int mTableSize;
-        int mTableIndex;
-        int mCurrentIndex;
-
-        TableIterationState(const int tableSize, const int tableIndex)
-                : mTableSize(tableSize), mTableIndex(tableIndex), mCurrentIndex(0) {}
-    };
-
-    class TrieMapRange;
-    class TrieMapIterator {
-     public:
-        class IterationResult {
-         public:
-            IterationResult(const TrieMap *const trieMap, const int key, const uint64_t value,
-                    const int nextLeveBitmapEntryIndex)
-                    : mTrieMap(trieMap), mKey(key), mValue(value),
-                      mNextLevelBitmapEntryIndex(nextLeveBitmapEntryIndex) {}
-
-            const TrieMapRange getEntriesInNextLevel() const {
-                return TrieMapRange(mTrieMap, mNextLevelBitmapEntryIndex);
-            }
-
-            bool hasNextLevelMap() const {
-                return mNextLevelBitmapEntryIndex != INVALID_INDEX;
-            }
-
-            AK_FORCE_INLINE int key() const {
-                return mKey;
-            }
-
-            AK_FORCE_INLINE uint64_t value() const {
-                return mValue;
-            }
-
-         private:
-            const TrieMap *const mTrieMap;
-            const int mKey;
-            const uint64_t mValue;
-            const int mNextLevelBitmapEntryIndex;
-        };
-
-        TrieMapIterator(const TrieMap *const trieMap, const int bitmapEntryIndex)
-                : mTrieMap(trieMap), mStateStack(), mBaseBitmapEntryIndex(bitmapEntryIndex),
-                  mKey(0), mValue(0), mIsValid(false), mNextLevelBitmapEntryIndex(INVALID_INDEX) {
-            if (!trieMap) {
-                return;
-            }
-            const Entry bitmapEntry = mTrieMap->readEntry(mBaseBitmapEntryIndex);
-            mStateStack.emplace_back(
-                    mTrieMap->popCount(bitmapEntry.getBitmap()), bitmapEntry.getTableIndex());
-            this->operator++();
-        }
-
-        const IterationResult operator*() const {
-            return IterationResult(mTrieMap, mKey, mValue, mNextLevelBitmapEntryIndex);
-        }
-
-        bool operator!=(const TrieMapIterator &other) const {
-            // Caveat: This works only for for loops.
-            return mIsValid || other.mIsValid;
-        }
-
-        const TrieMapIterator &operator++() {
-            const Result result = mTrieMap->iterateNext(&mStateStack, &mKey);
-            mValue = result.mValue;
-            mIsValid = result.mIsValid;
-            mNextLevelBitmapEntryIndex = result.mNextLevelBitmapEntryIndex;
-            return *this;
-        }
-
-     private:
-        DISALLOW_DEFAULT_CONSTRUCTOR(TrieMapIterator);
-        DISALLOW_ASSIGNMENT_OPERATOR(TrieMapIterator);
-
-        const TrieMap *const mTrieMap;
-        std::vector<TrieMap::TableIterationState> mStateStack;
-        const int mBaseBitmapEntryIndex;
-        int mKey;
-        uint64_t mValue;
-        bool mIsValid;
-        int mNextLevelBitmapEntryIndex;
-    };
-
-    /**
-     * Class to support iterating entries in TrieMap by range base for loops.
-     */
-    class TrieMapRange {
-     public:
-        TrieMapRange(const TrieMap *const trieMap, const int bitmapEntryIndex)
-                : mTrieMap(trieMap), mBaseBitmapEntryIndex(bitmapEntryIndex) {};
-
-        TrieMapIterator begin() const {
-            return TrieMapIterator(mTrieMap, mBaseBitmapEntryIndex);
-        }
-
-        const TrieMapIterator end() const {
-            return TrieMapIterator(nullptr, INVALID_INDEX);
-        }
-
-     private:
-        DISALLOW_DEFAULT_CONSTRUCTOR(TrieMapRange);
-        DISALLOW_ASSIGNMENT_OPERATOR(TrieMapRange);
-
-        const TrieMap *const mTrieMap;
-        const int mBaseBitmapEntryIndex;
-    };
-
-    static const int INVALID_INDEX;
-    static const uint64_t MAX_VALUE;
-
-    TrieMap();
-    // Construct TrieMap using existing data in the memory region written by save().
-    TrieMap(const ReadWriteByteArrayView buffer);
-    void dump(const int from = 0, const int to = 0) const;
-
-    bool isNearSizeLimit() const {
-        return mBuffer.isNearSizeLimit();
-    }
-
-    int getRootBitmapEntryIndex() const {
-        return ROOT_BITMAP_ENTRY_INDEX;
-    }
-
-    // Returns bitmapEntryIndex. Create the next level map if it doesn't exist.
-    int getNextLevelBitmapEntryIndex(const int key) {
-        return getNextLevelBitmapEntryIndex(key, ROOT_BITMAP_ENTRY_INDEX);
-    }
-
-    int getNextLevelBitmapEntryIndex(const int key, const int bitmapEntryIndex);
-
-    const Result getRoot(const int key) const {
-        return get(key, ROOT_BITMAP_ENTRY_INDEX);
-    }
-
-    const Result get(const int key, const int bitmapEntryIndex) const;
-
-    bool putRoot(const int key, const uint64_t value) {
-        return put(key, value, ROOT_BITMAP_ENTRY_INDEX);
-    }
-
-    bool put(const int key, const uint64_t value, const int bitmapEntryIndex);
-
-    const TrieMapRange getEntriesInRootLevel() const {
-        return getEntriesInSpecifiedLevel(ROOT_BITMAP_ENTRY_INDEX);
-    }
-
-    const TrieMapRange getEntriesInSpecifiedLevel(const int bitmapEntryIndex) const {
-        return TrieMapRange(this, bitmapEntryIndex);
-    }
-
-    bool save(FILE *const file) const;
-
- private:
-    DISALLOW_COPY_AND_ASSIGN(TrieMap);
-
-    /**
-     * Struct represents an entry.
-     *
-     * Entry is one of these entry types. All entries are fixed size and have 2 fields FIELD_0 and
-     * FIELD_1.
-     * 1. bitmap entry. bitmap entry contains bitmap and the link to hash table.
-     *   FIELD_0(bitmap) FIELD_1(LINK_TO_HASH_TABLE)
-     * 2. terminal entry. terminal entry contains hashed key and value or terminal link. terminal
-     * entry have terminal link when the value is not fit to FIELD_1 or there is a next level map
-     * for the key.
-     *   FIELD_0(hashed key) (FIELD_1(VALUE_FLAG VALUE) | FIELD_1(TERMINAL_LINK_FLAG TERMINAL_LINK))
-     * 3. value entry. value entry represents a value. Upper order bytes are stored in FIELD_0 and
-     * lower order bytes are stored in FIELD_1.
-     *   FIELD_0(value (upper order bytes)) FIELD_1(value (lower order bytes))
-     */
-    struct Entry {
-        const uint32_t mData0;
-        const uint32_t mData1;
-
-        Entry(const uint32_t data0, const uint32_t data1) : mData0(data0), mData1(data1) {}
-
-        AK_FORCE_INLINE bool isBitmapEntry() const {
-            return (mData1 & VALUE_FLAG) == 0 && (mData1 & TERMINAL_LINK_FLAG) == 0;
-        }
-
-        AK_FORCE_INLINE bool hasTerminalLink() const {
-            return (mData1 & TERMINAL_LINK_FLAG) != 0;
-        }
-
-        // For terminal entry.
-        AK_FORCE_INLINE uint32_t getKey() const {
-            return mData0;
-        }
-
-        // For terminal entry.
-        AK_FORCE_INLINE uint32_t getValue() const {
-            return mData1 & VALUE_MASK;
-        }
-
-        // For terminal entry.
-        AK_FORCE_INLINE uint32_t getValueEntryIndex() const {
-            return mData1 & TERMINAL_LINK_MASK;
-        }
-
-        // For bitmap entry.
-        AK_FORCE_INLINE uint32_t getBitmap() const {
-            return mData0;
-        }
-
-        // For bitmap entry.
-        AK_FORCE_INLINE int getTableIndex() const {
-            return static_cast<int>(mData1);
-        }
-
-        // For value entry.
-        AK_FORCE_INLINE uint64_t getValueOfValueEntry() const {
-            return ((static_cast<uint64_t>(mData0) << (FIELD1_SIZE * CHAR_BIT)) ^ mData1);
-        }
-    };
-
-    BufferWithExtendableBuffer mBuffer;
-
-    static const int FIELD0_SIZE;
-    static const int FIELD1_SIZE;
-    static const int ENTRY_SIZE;
-    static const uint32_t VALUE_FLAG;
-    static const uint32_t VALUE_MASK;
-    static const uint32_t TERMINAL_LINK_FLAG;
-    static const uint32_t TERMINAL_LINK_MASK;
-    static const int NUM_OF_BITS_USED_FOR_ONE_LEVEL;
-    static const uint32_t LABEL_MASK;
-    static const int MAX_NUM_OF_ENTRIES_IN_ONE_LEVEL;
-    static const int ROOT_BITMAP_ENTRY_INDEX;
-    static const int ROOT_BITMAP_ENTRY_POS;
-    static const Entry EMPTY_BITMAP_ENTRY;
-    static const int MAX_BUFFER_SIZE;
-
-    uint32_t getBitShuffledKey(const uint32_t key) const;
-    bool writeValue(const uint64_t value, const int terminalEntryIndex);
-    bool updateValue(const Entry &terminalEntry, const uint64_t value,
-            const int terminalEntryIndex);
-    bool freeTable(const int tableIndex, const int entryCount);
-    int allocateTable(const int entryCount);
-    int getTerminalEntryIndex(const uint32_t key, const uint32_t hashedKey,
-            const Entry &bitmapEntry, const int level) const;
-    const Result getInternal(const uint32_t key, const uint32_t hashedKey,
-            const int bitmapEntryIndex, const int level) const;
-    bool putInternal(const uint32_t key, const uint64_t value, const uint32_t hashedKey,
-            const int bitmapEntryIndex, const Entry &bitmapEntry, const int level);
-    bool addNewEntryByResolvingConflict(const uint32_t key, const uint64_t value,
-            const uint32_t hashedKey, const Entry &conflictedEntry, const int conflictedEntryIndex,
-            const int level);
-    bool addNewEntryByExpandingTable(const uint32_t key, const uint64_t value,
-            const int tableIndex, const uint32_t bitmap, const int bitmapEntryIndex,
-            const int label);
-    const Result iterateNext(std::vector<TableIterationState> *const iterationState,
-            int *const outKey) const;
-
-    AK_FORCE_INLINE const Entry readEntry(const int entryIndex) const {
-        return Entry(readField0(entryIndex), readField1(entryIndex));
-    }
-
-    // Returns whether an entry for the index is existing by testing if the index-th bit in the
-    // bitmap is set or not.
-    AK_FORCE_INLINE bool exists(const uint32_t bitmap, const int index) const {
-        return (bitmap & (1 << index)) != 0;
-    }
-
-    // Set index-th bit in the bitmap.
-    AK_FORCE_INLINE uint32_t setExist(const uint32_t bitmap, const int index) const {
-        return bitmap | (1 << index);
-    }
-
-    // Count set bits before index in the bitmap.
-    AK_FORCE_INLINE int popCount(const uint32_t bitmap, const int index) const {
-        return popCount(bitmap & ((1 << index) - 1));
-    }
-
-    // Count set bits in the bitmap.
-    AK_FORCE_INLINE int popCount(const uint32_t bitmap) const {
-        return __builtin_popcount(bitmap);
-        // int v = bitmap - ((bitmap >> 1) & 0x55555555);
-        // v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
-        // return (((v + (v >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
-    }
-
-    AK_FORCE_INLINE int getLabel(const uint32_t hashedKey, const int level) const {
-        return (hashedKey >> (level * NUM_OF_BITS_USED_FOR_ONE_LEVEL)) & LABEL_MASK;
-    }
-
-    AK_FORCE_INLINE uint32_t readField0(const int entryIndex) const {
-        return mBuffer.readUint(FIELD0_SIZE, ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE);
-    }
-
-    AK_FORCE_INLINE uint32_t readField1(const int entryIndex) const {
-        return mBuffer.readUint(FIELD1_SIZE,
-                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE + FIELD0_SIZE);
-    }
-
-    AK_FORCE_INLINE int readEmptyTableLink(const int entryCount) const {
-        return mBuffer.readUint(FIELD1_SIZE, (entryCount - 1) * FIELD1_SIZE);
-    }
-
-    AK_FORCE_INLINE bool writeEmptyTableLink(const int tableIndex, const int entryCount) {
-        return mBuffer.writeUint(tableIndex, FIELD1_SIZE, (entryCount - 1) * FIELD1_SIZE);
-    }
-
-    AK_FORCE_INLINE bool writeField0(const uint32_t data, const int entryIndex) {
-        return mBuffer.writeUint(data, FIELD0_SIZE,
-                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE);
-    }
-
-    AK_FORCE_INLINE bool writeField1(const uint32_t data, const int entryIndex) {
-        return mBuffer.writeUint(data, FIELD1_SIZE,
-                ROOT_BITMAP_ENTRY_POS + entryIndex * ENTRY_SIZE + FIELD0_SIZE);
-    }
-
-    AK_FORCE_INLINE bool writeEntry(const Entry &entry, const int entryIndex) {
-        return writeField0(entry.mData0, entryIndex) && writeField1(entry.mData1, entryIndex);
-    }
-
-    AK_FORCE_INLINE bool writeTerminalEntry(const uint32_t key, const uint64_t value,
-            const int entryIndex) {
-        return writeField0(key, entryIndex) && writeValue(value, entryIndex);
-    }
-
-    AK_FORCE_INLINE bool copyEntry(const int originalEntryIndex, const int newEntryIndex) {
-        return writeEntry(readEntry(originalEntryIndex), newEntryIndex);
-    }
-
-    AK_FORCE_INLINE int getTailEntryIndex() const {
-        return (mBuffer.getTailPosition() - ROOT_BITMAP_ENTRY_POS) / ENTRY_SIZE;
-    }
-};
-
-} // namespace latinime
-#endif /* LATINIME_TRIE_MAP_H */
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
index 3fc566e..856808a 100644
--- a/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.cpp
@@ -24,6 +24,7 @@
 const float ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD = 1.0f;
 
 const float ScoringParams::EXACT_MATCH_PROMOTION = 1.1f;
+const float ScoringParams::PERFECT_MATCH_PROMOTION = 1.1f;
 const float ScoringParams::CASE_ERROR_PENALTY_FOR_EXACT_MATCH = 0.01f;
 const float ScoringParams::ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH = 0.02f;
 const float ScoringParams::DIGRAPH_PENALTY_FOR_EXACT_MATCH = 0.03f;
@@ -31,6 +32,7 @@
 // TODO: Unlimit max cache dic node size
 const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE = 170;
 const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT = 310;
+const int ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_LOW_PROBABILITY_LOCALE = 50;
 const int ScoringParams::THRESHOLD_SHORT_WORD_LENGTH = 4;
 
 const float ScoringParams::DISTANCE_WEIGHT_LENGTH = 0.1524f;
@@ -47,18 +49,21 @@
 const float ScoringParams::INSERTION_COST_PROXIMITY_CHAR = 0.674f;
 const float ScoringParams::INSERTION_COST_FIRST_CHAR = 0.639f;
 const float ScoringParams::TRANSPOSITION_COST = 0.5608f;
-const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.334f;
-const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.4576f;
+const float ScoringParams::SPACE_SUBSTITUTION_COST = 0.33f;
+const float ScoringParams::SPACE_OMISSION_COST = 0.1f;
+const float ScoringParams::ADDITIONAL_PROXIMITY_COST = 0.37972f;
 const float ScoringParams::SUBSTITUTION_COST = 0.3806f;
-const float ScoringParams::COST_NEW_WORD = 0.0314f;
 const float ScoringParams::COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE = 0.3224f;
 const float ScoringParams::DISTANCE_WEIGHT_LANGUAGE = 1.1214f;
 const float ScoringParams::COST_FIRST_COMPLETION = 0.4836f;
 const float ScoringParams::COST_COMPLETION = 0.00624f;
 const float ScoringParams::HAS_PROXIMITY_TERMINAL_COST = 0.0683f;
 const float ScoringParams::HAS_EDIT_CORRECTION_TERMINAL_COST = 0.0362f;
-const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.4182f;
+const float ScoringParams::HAS_MULTI_WORD_TERMINAL_COST = 0.3482f;
 const float ScoringParams::TYPING_BASE_OUTPUT_SCORE = 1.0f;
 const float ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT = 0.1f;
 const float ScoringParams::NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT = 0.095f;
+const float ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_SUBSTITUTION = 0.99f;
+const float ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_OMISSION = 0.99f;
+const float ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SMALL_CACHE_SIZE = 0.99f;
 } // namespace latinime
diff --git a/native/jni/src/suggest/policyimpl/typing/scoring_params.h b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
index b12de6d..6f327a3 100644
--- a/native/jni/src/suggest/policyimpl/typing/scoring_params.h
+++ b/native/jni/src/suggest/policyimpl/typing/scoring_params.h
@@ -30,9 +30,11 @@
     static const float AUTOCORRECT_OUTPUT_THRESHOLD;
     static const int MAX_CACHE_DIC_NODE_SIZE;
     static const int MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT;
+    static const int MAX_CACHE_DIC_NODE_SIZE_FOR_LOW_PROBABILITY_LOCALE;
     static const int THRESHOLD_SHORT_WORD_LENGTH;
 
     static const float EXACT_MATCH_PROMOTION;
+    static const float PERFECT_MATCH_PROMOTION;
     static const float CASE_ERROR_PENALTY_FOR_EXACT_MATCH;
     static const float ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH;
     static const float DIGRAPH_PENALTY_FOR_EXACT_MATCH;
@@ -55,9 +57,9 @@
     static const float INSERTION_COST_FIRST_CHAR;
     static const float TRANSPOSITION_COST;
     static const float SPACE_SUBSTITUTION_COST;
+    static const float SPACE_OMISSION_COST;
     static const float ADDITIONAL_PROXIMITY_COST;
     static const float SUBSTITUTION_COST;
-    static const float COST_NEW_WORD;
     static const float COST_SECOND_OR_LATER_WORD_FIRST_CHAR_UPPERCASE;
     static const float DISTANCE_WEIGHT_LANGUAGE;
     static const float COST_FIRST_COMPLETION;
@@ -68,6 +70,9 @@
     static const float TYPING_BASE_OUTPUT_SCORE;
     static const float TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
     static const float NORMALIZED_SPATIAL_DISTANCE_THRESHOLD_FOR_EDIT;
+    static const float LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_SUBSTITUTION;
+    static const float LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_OMISSION;
+    static const float LOCALE_WEIGHT_THRESHOLD_FOR_SMALL_CACHE_SIZE;
 
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(ScoringParams);
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
index 04cb660..6acd767 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -33,32 +33,61 @@
     static const TypingScoring *getInstance() { return &sInstance; }
 
     AK_FORCE_INLINE void getMostProbableString(const DicTraverseSession *const traverseSession,
-            const float languageWeight, SuggestionResults *const outSuggestionResults) const {}
+            const float weightOfLangModelVsSpatialModel,
+            SuggestionResults *const outSuggestionResults) const {}
 
-    AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
-            DicNode *const terminals, const int size) const {
+    AK_FORCE_INLINE float getAdjustedWeightOfLangModelVsSpatialModel(
+            DicTraverseSession *const traverseSession, DicNode *const terminals,
+            const int size) const {
         return 1.0f;
     }
 
     AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance, const int inputSize,
             const ErrorTypeUtils::ErrorType containedErrorTypes, const bool forceCommit,
-            const bool boostExactMatches) const {
+            const bool boostExactMatches, const bool hasProbabilityZero) const {
         const float maxDistance = ScoringParams::DISTANCE_WEIGHT_LANGUAGE
                 + static_cast<float>(inputSize) * ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
         float score = ScoringParams::TYPING_BASE_OUTPUT_SCORE - compoundDistance / maxDistance;
         if (forceCommit) {
             score += ScoringParams::AUTOCORRECT_OUTPUT_THRESHOLD;
         }
-        if (boostExactMatches && ErrorTypeUtils::isExactMatch(containedErrorTypes)) {
-            score += ScoringParams::EXACT_MATCH_PROMOTION;
-            if ((ErrorTypeUtils::MATCH_WITH_CASE_ERROR & containedErrorTypes) != 0) {
-                score -= ScoringParams::CASE_ERROR_PENALTY_FOR_EXACT_MATCH;
+        if (hasProbabilityZero) {
+            // Previously, when both legitimate 0-frequency words (such as distracters) and
+            // offensive words were encoded in the same way, distracters would never show up
+            // when the user blocked offensive words (the default setting, as well as the
+            // setting for regression tests).
+            //
+            // When b/11031090 was fixed and a separate encoding was used for offensive words,
+            // 0-frequency words would no longer be blocked when they were an "exact match"
+            // (where case mismatches and accent mismatches would be considered an "exact
+            // match"). The exact match boosting functionality meant that, for example, when
+            // the user typed "mt" they would be suggested the word "Mt", although they most
+            // probably meant to type "my".
+            //
+            // For this reason, we introduced this change, which does the following:
+            // * Defines the "perfect match" as a really exact match, with no room for case or
+            // accent mismatches
+            // * When the target word has probability zero (as "Mt" does, because it is a
+            // distracter), ONLY boost its score if it is a perfect match.
+            //
+            // By doing this, when the user types "mt", the word "Mt" will NOT be boosted, and
+            // they will get "my". However, if the user makes an explicit effort to type "Mt",
+            // we do boost the word "Mt" so that the user's input is not autocorrected to "My".
+            if (boostExactMatches && ErrorTypeUtils::isPerfectMatch(containedErrorTypes)) {
+                score += ScoringParams::PERFECT_MATCH_PROMOTION;
             }
-            if ((ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR & containedErrorTypes) != 0) {
-                score -= ScoringParams::ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH;
-            }
-            if ((ErrorTypeUtils::MATCH_WITH_DIGRAPH & containedErrorTypes) != 0) {
-                score -= ScoringParams::DIGRAPH_PENALTY_FOR_EXACT_MATCH;
+        } else {
+            if (boostExactMatches && ErrorTypeUtils::isExactMatch(containedErrorTypes)) {
+                score += ScoringParams::EXACT_MATCH_PROMOTION;
+                if ((ErrorTypeUtils::MATCH_WITH_WRONG_CASE & containedErrorTypes) != 0) {
+                    score -= ScoringParams::CASE_ERROR_PENALTY_FOR_EXACT_MATCH;
+                }
+                if ((ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT & containedErrorTypes) != 0) {
+                    score -= ScoringParams::ACCENT_ERROR_PENALTY_FOR_EXACT_MATCH;
+                }
+                if ((ErrorTypeUtils::MATCH_WITH_DIGRAPH & containedErrorTypes) != 0) {
+                    score -= ScoringParams::DIGRAPH_PENALTY_FOR_EXACT_MATCH;
+                }
             }
         }
         return static_cast<int>(score * SUGGEST_INTERFACE_OUTPUT_SCALE);
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
index cb3dfac..b9b6314 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_traversal.h
@@ -26,6 +26,7 @@
 #include "suggest/core/layout/proximity_info_utils.h"
 #include "suggest/core/policy/traversal.h"
 #include "suggest/core/session/dic_traverse_session.h"
+#include "suggest/core/suggest_options.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
 #include "utils/char_utils.h"
 
@@ -77,6 +78,13 @@
         if (!CORRECT_NEW_WORD_SPACE_SUBSTITUTION) {
             return false;
         }
+        if (traverseSession->getSuggestOptions()->weightForLocale()
+                < ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_SUBSTITUTION) {
+            // Space substitution is heavy, so we skip doing it if the weight for this language
+            // is low because we anticipate the suggestions out of this dictionary are not for
+            // the language the user intends to type in.
+            return false;
+        }
         if (!canDoLookAheadCorrection(traverseSession, dicNode)) {
             return false;
         }
@@ -91,6 +99,13 @@
         if (!CORRECT_NEW_WORD_SPACE_OMISSION) {
             return false;
         }
+        if (traverseSession->getSuggestOptions()->weightForLocale()
+                < ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SPACE_OMISSION) {
+            // Space omission is heavy, so we skip doing it if the weight for this language
+            // is low because we anticipate the suggestions out of this dictionary are not for
+            // the language the user intends to type in.
+            return false;
+        }
         const int inputSize = traverseSession->getInputSize();
         // TODO: Don't refer to isCompletion?
         if (dicNode->isCompletion(inputSize)) {
@@ -141,9 +156,14 @@
         return DicNodeVector::DEFAULT_NODES_SIZE_FOR_OPTIMIZATION;
     }
 
-    AK_FORCE_INLINE int getMaxCacheSize(const int inputSize) const {
-        return (inputSize <= 1) ? ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT
-                : ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
+    AK_FORCE_INLINE int getMaxCacheSize(const int inputSize, const float weightForLocale) const {
+        if (inputSize <= 1) {
+            return ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_SINGLE_POINT;
+        }
+        if (weightForLocale < ScoringParams::LOCALE_WEIGHT_THRESHOLD_FOR_SMALL_CACHE_SIZE) {
+            return ScoringParams::MAX_CACHE_DIC_NODE_SIZE_FOR_LOW_PROBABILITY_LOCALE;
+        }
+        return ScoringParams::MAX_CACHE_DIC_NODE_SIZE;
     }
 
     AK_FORCE_INLINE int getTerminalCacheSize() const {
@@ -161,8 +181,8 @@
         return true;
     }
 
-    AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode) const {
-        const int probability = dicNode->getProbability();
+    AK_FORCE_INLINE bool isGoodToTraverseNextWord(const DicNode *const dicNode,
+            const int probability) const {
         if (probability < ScoringParams::THRESHOLD_NEXT_WORD_PROBABILITY) {
             return false;
         }
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
index 54f65c7..a0e5411 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.cpp
@@ -17,6 +17,7 @@
 #include "suggest/policyimpl/typing/typing_weighting.h"
 
 #include "suggest/core/dicnode/dic_node.h"
+#include "suggest/core/layout/proximity_info.h"
 #include "suggest/policyimpl/typing/scoring_params.h"
 
 namespace latinime {
@@ -36,30 +37,49 @@
                 // Compare the node code point with original primary code point on the keyboard.
                 const ProximityInfoState *const pInfoState =
                         traverseSession->getProximityInfoState(0);
-                const int primaryOriginalCodePoint = pInfoState->getPrimaryOriginalCodePointAt(
+                const int primaryCodePoint = pInfoState->getPrimaryCodePointAt(
                         dicNode->getInputIndex(0));
                 const int nodeCodePoint = dicNode->getNodeCodePoint();
-                if (primaryOriginalCodePoint == nodeCodePoint) {
+                const int keyIndex = traverseSession->getProximityInfo()->getKeyIndexOf(
+                        primaryCodePoint);
+                // TODO: Check whether the input code point is on the keyboard.
+                if (primaryCodePoint == nodeCodePoint) {
                     // Node code point is same as original code point on the keyboard.
                     return ErrorTypeUtils::NOT_AN_ERROR;
-                } else if (CharUtils::toLowerCase(primaryOriginalCodePoint) ==
+                } else if (CharUtils::toLowerCase(primaryCodePoint) ==
                         CharUtils::toLowerCase(nodeCodePoint)) {
                     // Only cases of the code points are different.
-                    return ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
-                } else if (CharUtils::toBaseCodePoint(primaryOriginalCodePoint) ==
-                        CharUtils::toBaseCodePoint(nodeCodePoint)) {
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+                } else if (primaryCodePoint == CharUtils::toBaseCodePoint(nodeCodePoint)) {
                     // Node code point is a variant of original code point.
-                    return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR;
-                } else {
+                    return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT;
+                } else if (CharUtils::toBaseCodePoint(primaryCodePoint)
+                        == CharUtils::toBaseCodePoint(nodeCodePoint)) {
+                    // Base code points are the same but the code point is intentionally input.
+                    if (keyIndex == NOT_AN_INDEX) {
+                        return ErrorTypeUtils::MATCH_WITH_MISSING_EXPLICIT_ACCENT;
+                    }
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT;
+                } else if (CharUtils::toLowerCase(primaryCodePoint)
+                        == CharUtils::toBaseLowerCase(nodeCodePoint)) {
                     // Node code point is a variant of original code point and the cases are also
                     // different.
-                    return ErrorTypeUtils::MATCH_WITH_ACCENT_ERROR
-                            | ErrorTypeUtils::MATCH_WITH_CASE_ERROR;
+                    return ErrorTypeUtils::MATCH_WITH_MISSING_ACCENT
+                            | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+                } else {
+                    if (keyIndex == NOT_AN_INDEX) {
+                        return ErrorTypeUtils::MATCH_WITH_MISSING_EXPLICIT_ACCENT
+                                | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
+                    }
+                    // Base code points are the same and the cases are different.
+                    return ErrorTypeUtils::MATCH_WITH_WRONG_ACCENT
+                            | ErrorTypeUtils::MATCH_WITH_WRONG_CASE;
                 }
             }
             break;
         case CT_ADDITIONAL_PROXIMITY:
-            return  ErrorTypeUtils::PROXIMITY_CORRECTION;
+            // TODO: Change to EDIT_CORRECTION.
+            return ErrorTypeUtils::PROXIMITY_CORRECTION;
         case CT_OMISSION:
             if (parentDicNode->canBeIntentionalOmission()) {
                 return ErrorTypeUtils::INTENTIONAL_OMISSION;
@@ -68,6 +88,8 @@
             }
             break;
         case CT_SUBSTITUTION:
+            // TODO: Quit settng PROXIMITY_CORRECTION.
+            return ErrorTypeUtils::EDIT_CORRECTION | ErrorTypeUtils::PROXIMITY_CORRECTION;
         case CT_INSERTION:
         case CT_TERMINAL_INSERTION:
         case CT_TRANSPOSITION:
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 8407717..1338ac8 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -150,9 +150,10 @@
         return cost + weightedDistance;
     }
 
-    float getNewWordSpatialCost(const DicTraverseSession *const traverseSession,
+    float getSpaceOmissionCost(const DicTraverseSession *const traverseSession,
             const DicNode *const dicNode, DicNode_InputStateG *inputStateG) const {
-        return ScoringParams::COST_NEW_WORD * traverseSession->getMultiWordCostMultiplier();
+        const float cost = ScoringParams::SPACE_OMISSION_COST;
+        return cost * traverseSession->getMultiWordCostMultiplier();
     }
 
     float getNewWordBigramLanguageCost(const DicTraverseSession *const traverseSession,
@@ -202,7 +203,10 @@
 
     AK_FORCE_INLINE float getSpaceSubstitutionCost(const DicTraverseSession *const traverseSession,
             const DicNode *const dicNode) const {
-        const float cost = ScoringParams::SPACE_SUBSTITUTION_COST + ScoringParams::COST_NEW_WORD;
+        const int inputIndex = dicNode->getInputIndex(0);
+        const float distanceToSpaceKey = traverseSession->getProximityInfoState(0)
+                ->getPointToKeyLength(inputIndex, KEYCODE_SPACE);
+        const float cost = ScoringParams::SPACE_SUBSTITUTION_COST * distanceToSpaceKey;
         return cost * traverseSession->getMultiWordCostMultiplier();
     }
 
diff --git a/native/jni/src/utils/byte_array_view.h b/native/jni/src/utils/byte_array_view.h
index 2c97c6d..2b778af 100644
--- a/native/jni/src/utils/byte_array_view.h
+++ b/native/jni/src/utils/byte_array_view.h
@@ -42,6 +42,13 @@
         return mPtr;
     }
 
+    AK_FORCE_INLINE const ReadOnlyByteArrayView skip(const size_t n) const {
+        if (mSize <= n) {
+            return ReadOnlyByteArrayView();
+        }
+        return ReadOnlyByteArrayView(mPtr + n, mSize - n);
+    }
+
  private:
     DISALLOW_ASSIGNMENT_OPERATOR(ReadOnlyByteArrayView);
 
@@ -77,10 +84,12 @@
     }
 
  private:
-    DISALLOW_ASSIGNMENT_OPERATOR(ReadWriteByteArrayView);
+    // Default copy constructor and assignment operator are used for using this class with STL
+    // containers.
 
-    uint8_t *const mPtr;
-    const size_t mSize;
+    // These members cannot be const to have the assignment operator.
+    uint8_t *mPtr;
+    size_t mSize;
 };
 
 } // namespace latinime
diff --git a/native/jni/src/utils/char_utils.cpp b/native/jni/src/utils/char_utils.cpp
index b17e084..a43e6dd 100644
--- a/native/jni/src/utils/char_utils.cpp
+++ b/native/jni/src/utils/char_utils.cpp
@@ -1057,11 +1057,11 @@
             - static_cast<int>((static_cast<const struct LatinCapitalSmallPair *>(b))->capital);
 }
 
-/* static */ unsigned short CharUtils::latin_tolower(const unsigned short c) {
+/* static */ int CharUtils::latin_tolower(const int c) {
     struct LatinCapitalSmallPair *p =
             static_cast<struct LatinCapitalSmallPair *>(bsearch(&c, SORTED_CHAR_MAP,
                     NELEMS(SORTED_CHAR_MAP), sizeof(SORTED_CHAR_MAP[0]), compare_pair_capital));
-    return p ? p->small : c;
+    return p ? static_cast<int>(p->small) : c;
 }
 
 /*
@@ -1117,7 +1117,9 @@
           // TODO: Check if it's really acceptable to consider ø a diacritical variant of o
     /* U+0100 */ 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063,
     /* U+0108 */ 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064,
-    /* U+0110 */ 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065,
+    /* U+0110 */ 0x0046, 0x0064, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065,
+        // U+0110: Manually changed from 0110 to 0046
+        // U+0111: Manually changed from 0111 to 0064
     /* U+0118 */ 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067,
     /* U+0120 */ 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127,
     /* U+0128 */ 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069,
@@ -1135,6 +1137,9 @@
     /* U+0170 */ 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079,
     /* U+0178 */ 0x0059, 0x005A, 0x007A, 0x005A, 0x007A, 0x005A, 0x007A, 0x0073,
     /* U+0180 */ 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187,
+          // TODO: A lot of letters are their own base code points, but for
+          // some (e.g. U+0180) it doesn't seem right. Ideally each code point should
+          // be checked individually with all languages it's used in.
     /* U+0188 */ 0x0188, 0x0189, 0x018A, 0x018B, 0x018C, 0x018D, 0x018E, 0x018F,
     /* U+0190 */ 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,
     /* U+0198 */ 0x0198, 0x0199, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F,
diff --git a/native/jni/src/utils/char_utils.h b/native/jni/src/utils/char_utils.h
index 6378650..7871c26 100644
--- a/native/jni/src/utils/char_utils.h
+++ b/native/jni/src/utils/char_utils.h
@@ -27,20 +27,14 @@
 
 class CharUtils {
  public:
+    static const std::vector<int> EMPTY_STRING;
+
     static AK_FORCE_INLINE bool isAsciiUpper(int c) {
         // Note: isupper(...) reports false positives for some Cyrillic characters, causing them to
         // be incorrectly lower-cased using toAsciiLower(...) rather than latin_tolower(...).
         return (c >= 'A' && c <= 'Z');
     }
 
-    static AK_FORCE_INLINE int toAsciiLower(int c) {
-        return c - 'A' + 'a';
-    }
-
-    static AK_FORCE_INLINE bool isAscii(int c) {
-        return isascii(c) != 0;
-    }
-
     static AK_FORCE_INLINE int toLowerCase(const int c) {
         if (isAsciiUpper(c)) {
             return toAsciiLower(c);
@@ -48,7 +42,7 @@
         if (isAscii(c)) {
             return c;
         }
-        return static_cast<int>(latin_tolower(static_cast<unsigned short>(c)));
+        return latin_tolower(c);
     }
 
     static AK_FORCE_INLINE int toBaseLowerCase(const int c) {
@@ -59,7 +53,6 @@
         // TODO: Do not hardcode here
         return codePoint == KEYCODE_SINGLE_QUOTE || codePoint == KEYCODE_HYPHEN_MINUS;
     }
-
     static AK_FORCE_INLINE int getCodePointCount(const int arraySize, const int *const codePoints) {
         int size = 0;
         for (; size < arraySize; ++size) {
@@ -91,9 +84,6 @@
         return codePoint >= MIN_UNICODE_CODE_POINT && codePoint <= MAX_UNICODE_CODE_POINT;
     }
 
-    static unsigned short latin_tolower(const unsigned short c);
-    static const std::vector<int> EMPTY_STRING;
-
     // Returns updated code point count. Returns 0 when the code points cannot be marked as a
     // Beginning-of-Sentence.
     static AK_FORCE_INLINE int attachBeginningOfSentenceMarker(int *const codePoints,
@@ -111,6 +101,17 @@
         return codePointCount + 1;
     }
 
+    // Returns updated code point count.
+    static AK_FORCE_INLINE int removeBeginningOfSentenceMarker(int *const codePoints,
+            const int codePointCount) {
+        if (codePointCount <= 0 || codePoints[0] != CODE_POINT_BEGINNING_OF_SENTENCE) {
+            return codePointCount;
+        }
+        const int newCodePointCount = codePointCount - 1;
+        memmove(codePoints, codePoints + 1, sizeof(int) * newCodePointCount);
+        return newCodePointCount;
+    }
+
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(CharUtils);
 
@@ -125,6 +126,16 @@
      */
     static const int BASE_CHARS_SIZE = 0x0500;
     static const unsigned short BASE_CHARS[BASE_CHARS_SIZE];
+
+    static AK_FORCE_INLINE bool isAscii(int c) {
+        return isascii(c) != 0;
+    }
+
+    static AK_FORCE_INLINE int toAsciiLower(int c) {
+        return c - 'A' + 'a';
+    }
+
+    static int latin_tolower(const int c);
 };
 } // namespace latinime
 #endif // LATINIME_CHAR_UTILS_H
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index c1ddc98..e0f6710 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -17,8 +17,10 @@
 #ifndef LATINIME_INT_ARRAY_VIEW_H
 #define LATINIME_INT_ARRAY_VIEW_H
 
+#include <algorithm>
+#include <array>
 #include <cstdint>
-#include <cstdlib>
+#include <cstring>
 #include <vector>
 
 #include "defines.h"
@@ -56,14 +58,14 @@
     explicit IntArrayView(const std::vector<int> &vector)
             : mPtr(vector.data()), mSize(vector.size()) {}
 
-    template <int N>
-    AK_FORCE_INLINE static IntArrayView fromFixedSizeArray(const int (&array)[N]) {
-        return IntArrayView(array, N);
+    template <size_t N>
+    AK_FORCE_INLINE static IntArrayView fromArray(const std::array<int, N> &array) {
+        return IntArrayView(array.data(), array.size());
     }
 
-    // Returns a view that points one int object. Does not take ownership of the given object.
-    AK_FORCE_INLINE static IntArrayView fromObject(const int *const object) {
-        return IntArrayView(object, 1);
+    // Returns a view that points one int object.
+    AK_FORCE_INLINE static IntArrayView singleElementView(const int *const ptr) {
+        return IntArrayView(ptr, 1);
     }
 
     AK_FORCE_INLINE int operator[](const size_t index) const {
@@ -91,6 +93,69 @@
         return mPtr + mSize;
     }
 
+    AK_FORCE_INLINE bool contains(const int value) const {
+        return std::find(begin(), end(), value) != end();
+    }
+
+    // Returns the view whose size is smaller than or equal to the given count.
+    AK_FORCE_INLINE const IntArrayView limit(const size_t maxSize) const {
+        return IntArrayView(mPtr, std::min(maxSize, mSize));
+    }
+
+    AK_FORCE_INLINE const IntArrayView skip(const size_t n) const {
+        if (mSize <= n) {
+            return IntArrayView();
+        }
+        return IntArrayView(mPtr + n, mSize - n);
+    }
+
+    template <size_t N>
+    void copyToArray(std::array<int, N> *const buffer, const size_t offset) const {
+        ASSERT(mSize + offset <= N);
+        memmove(buffer->data() + offset, mPtr, sizeof(int) * mSize);
+    }
+
+    AK_FORCE_INLINE int firstOrDefault(const int defaultValue) const {
+        if (empty()) {
+            return defaultValue;
+        }
+        return mPtr[0];
+    }
+
+    AK_FORCE_INLINE int lastOrDefault(const int defaultValue) const {
+        if (empty()) {
+            return defaultValue;
+        }
+        return mPtr[mSize - 1];
+    }
+
+    AK_FORCE_INLINE std::vector<int> toVector() const {
+        return std::vector<int>(begin(), end());
+    }
+
+    std::vector<IntArrayView> split(const int separator, const int limit = S_INT_MAX) const {
+        if (limit <= 0) {
+            return std::vector<IntArrayView>();
+        }
+        std::vector<IntArrayView> result;
+        if (limit == 1) {
+            result.emplace_back(mPtr, mSize);
+            return result;
+        }
+        size_t startIndex = 0;
+        for (size_t i = 0; i < mSize; ++i) {
+            if (mPtr[i] == separator) {
+                result.emplace_back(mPtr + startIndex, i - startIndex);
+                startIndex = i + 1;
+                if (result.size() >= static_cast<size_t>(limit - 1)) {
+                    break;
+                }
+            }
+        }
+        result.emplace_back(mPtr + startIndex, mSize - startIndex);
+        return result;
+    }
+
  private:
     DISALLOW_ASSIGNMENT_OPERATOR(IntArrayView);
 
@@ -100,6 +165,9 @@
 
 using WordIdArrayView = IntArrayView;
 using PtNodePosArrayView = IntArrayView;
+using CodePointArrayView = IntArrayView;
+template <size_t size>
+using WordIdArray = std::array<int, size>;
 
 } // namespace latinime
 #endif // LATINIME_MEMORY_VIEW_H
diff --git a/native/jni/src/utils/jni_data_utils.cpp b/native/jni/src/utils/jni_data_utils.cpp
index 5555293..41f0623 100644
--- a/native/jni/src/utils/jni_data_utils.cpp
+++ b/native/jni/src/utils/jni_data_utils.cpp
@@ -16,9 +16,100 @@
 
 #include "utils/jni_data_utils.h"
 
+#include "utils/int_array_view.h"
+
 namespace latinime {
 
 const int JniDataUtils::CODE_POINT_REPLACEMENT_CHARACTER = 0xFFFD;
 const int JniDataUtils::CODE_POINT_NULL = 0;
 
+/* static */ void JniDataUtils::outputWordProperty(JNIEnv *const env,
+        const WordProperty &wordProperty, jintArray outCodePoints, jbooleanArray outFlags,
+        jintArray outProbabilityInfo, jobject outNgramPrevWordsArray,
+        jobject outNgramPrevWordIsBeginningOfSentenceArray, jobject outNgramTargets,
+        jobject outNgramProbabilities, jobject outShortcutTargets,
+        jobject outShortcutProbabilities) {
+    const CodePointArrayView codePoints = wordProperty.getCodePoints();
+    JniDataUtils::outputCodePoints(env, outCodePoints, 0 /* start */,
+            MAX_WORD_LENGTH /* maxLength */, codePoints.data(), codePoints.size(),
+            false /* needsNullTermination */);
+    const UnigramProperty &unigramProperty = wordProperty.getUnigramProperty();
+    const std::vector<NgramProperty> &ngrams = wordProperty.getNgramProperties();
+    jboolean flags[] = {unigramProperty.isNotAWord(), unigramProperty.isPossiblyOffensive(),
+            !ngrams.empty(), unigramProperty.hasShortcuts(),
+            unigramProperty.representsBeginningOfSentence()};
+    env->SetBooleanArrayRegion(outFlags, 0 /* start */, NELEMS(flags), flags);
+    const HistoricalInfo &historicalInfo = unigramProperty.getHistoricalInfo();
+    int probabilityInfo[] = {unigramProperty.getProbability(), historicalInfo.getTimestamp(),
+            historicalInfo.getLevel(), historicalInfo.getCount()};
+    env->SetIntArrayRegion(outProbabilityInfo, 0 /* start */, NELEMS(probabilityInfo),
+            probabilityInfo);
+
+    jclass integerClass = env->FindClass("java/lang/Integer");
+    jmethodID intToIntegerConstructorId = env->GetMethodID(integerClass, "<init>", "(I)V");
+    jclass arrayListClass = env->FindClass("java/util/ArrayList");
+    jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
+
+    // Output ngrams.
+    jclass intArrayClass = env->FindClass("[I");
+    for (const auto &ngramProperty : ngrams) {
+        const NgramContext *const ngramContext = ngramProperty.getNgramContext();
+        jobjectArray prevWordWordCodePointsArray = env->NewObjectArray(
+                ngramContext->getPrevWordCount(), intArrayClass, nullptr);
+        jbooleanArray prevWordIsBeginningOfSentenceArray =
+                env->NewBooleanArray(ngramContext->getPrevWordCount());
+        for (size_t i = 0; i < ngramContext->getPrevWordCount(); ++i) {
+            const CodePointArrayView codePoints = ngramContext->getNthPrevWordCodePoints(i + 1);
+            jintArray prevWordCodePoints = env->NewIntArray(codePoints.size());
+            JniDataUtils::outputCodePoints(env, prevWordCodePoints, 0 /* start */,
+                    codePoints.size(), codePoints.data(), codePoints.size(),
+                    false /* needsNullTermination */);
+            env->SetObjectArrayElement(prevWordWordCodePointsArray, i, prevWordCodePoints);
+            env->DeleteLocalRef(prevWordCodePoints);
+            JniDataUtils::putBooleanToArray(env, prevWordIsBeginningOfSentenceArray, i,
+                    ngramContext->isNthPrevWordBeginningOfSentence(i + 1));
+        }
+        env->CallBooleanMethod(outNgramPrevWordsArray, addMethodId, prevWordWordCodePointsArray);
+        env->CallBooleanMethod(outNgramPrevWordIsBeginningOfSentenceArray, addMethodId,
+                prevWordIsBeginningOfSentenceArray);
+        env->DeleteLocalRef(prevWordWordCodePointsArray);
+        env->DeleteLocalRef(prevWordIsBeginningOfSentenceArray);
+
+        const std::vector<int> *const targetWordCodePoints = ngramProperty.getTargetCodePoints();
+        jintArray targetWordCodePointArray = env->NewIntArray(targetWordCodePoints->size());
+        JniDataUtils::outputCodePoints(env, targetWordCodePointArray, 0 /* start */,
+                targetWordCodePoints->size(), targetWordCodePoints->data(),
+                targetWordCodePoints->size(), false /* needsNullTermination */);
+        env->CallBooleanMethod(outNgramTargets, addMethodId, targetWordCodePointArray);
+        env->DeleteLocalRef(targetWordCodePointArray);
+
+        const HistoricalInfo &ngramHistoricalInfo = ngramProperty.getHistoricalInfo();
+        int bigramProbabilityInfo[] = {ngramProperty.getProbability(),
+                ngramHistoricalInfo.getTimestamp(), ngramHistoricalInfo.getLevel(),
+                ngramHistoricalInfo.getCount()};
+        jintArray bigramProbabilityInfoArray = env->NewIntArray(NELEMS(bigramProbabilityInfo));
+        env->SetIntArrayRegion(bigramProbabilityInfoArray, 0 /* start */,
+                NELEMS(bigramProbabilityInfo), bigramProbabilityInfo);
+        env->CallBooleanMethod(outNgramProbabilities, addMethodId, bigramProbabilityInfoArray);
+        env->DeleteLocalRef(bigramProbabilityInfoArray);
+    }
+
+    // Output shortcuts.
+    for (const auto &shortcut : unigramProperty.getShortcuts()) {
+        const std::vector<int> *const targetCodePoints = shortcut.getTargetCodePoints();
+        jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
+        JniDataUtils::outputCodePoints(env, shortcutTargetCodePointArray, 0 /* start */,
+                targetCodePoints->size(), targetCodePoints->data(), targetCodePoints->size(),
+                false /* needsNullTermination */);
+        env->CallBooleanMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
+        env->DeleteLocalRef(shortcutTargetCodePointArray);
+        jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
+                shortcut.getProbability());
+        env->CallBooleanMethod(outShortcutProbabilities, addMethodId, integerProbability);
+        env->DeleteLocalRef(integerProbability);
+    }
+    env->DeleteLocalRef(integerClass);
+    env->DeleteLocalRef(arrayListClass);
+}
+
 } // namespace latinime
diff --git a/native/jni/src/utils/jni_data_utils.h b/native/jni/src/utils/jni_data_utils.h
index cb82d3c..8024e34 100644
--- a/native/jni/src/utils/jni_data_utils.h
+++ b/native/jni/src/utils/jni_data_utils.h
@@ -20,10 +20,11 @@
 #include <vector>
 
 #include "defines.h"
+#include "dictionary/header/header_read_write_utils.h"
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+#include "dictionary/property/ngram_context.h"
+#include "dictionary/property/word_property.h"
 #include "jni.h"
-#include "suggest/core/session/prev_words_info.h"
-#include "suggest/core/policy/dictionary_header_structure_policy.h"
-#include "suggest/policyimpl/dictionary/header/header_read_write_utils.h"
 #include "utils/char_utils.h"
 
 namespace latinime {
@@ -50,6 +51,7 @@
             const jsize keyUtf8Length = env->GetStringUTFLength(keyString);
             char keyChars[keyUtf8Length + 1];
             env->GetStringUTFRegion(keyString, 0, env->GetStringLength(keyString), keyChars);
+            env->DeleteLocalRef(keyString);
             keyChars[keyUtf8Length] = '\0';
             DictionaryHeaderStructurePolicy::AttributeMap::key_type key;
             HeaderReadWriteUtils::insertCharactersIntoVector(keyChars, &key);
@@ -59,6 +61,7 @@
             const jsize valueUtf8Length = env->GetStringUTFLength(valueString);
             char valueChars[valueUtf8Length + 1];
             env->GetStringUTFRegion(valueString, 0, env->GetStringLength(valueString), valueChars);
+            env->DeleteLocalRef(valueString);
             valueChars[valueUtf8Length] = '\0';
             DictionaryHeaderStructurePolicy::AttributeMap::mapped_type value;
             HeaderReadWriteUtils::insertCharactersIntoVector(valueChars, &value);
@@ -96,18 +99,14 @@
         }
     }
 
-    static PrevWordsInfo constructPrevWordsInfo(JNIEnv *env, jobjectArray prevWordCodePointArrays,
-            jbooleanArray isBeginningOfSentenceArray) {
+    static NgramContext constructNgramContext(JNIEnv *env, jobjectArray prevWordCodePointArrays,
+            jbooleanArray isBeginningOfSentenceArray, const size_t prevWordCount) {
         int prevWordCodePoints[MAX_PREV_WORD_COUNT_FOR_N_GRAM][MAX_WORD_LENGTH];
         int prevWordCodePointCount[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
         bool isBeginningOfSentence[MAX_PREV_WORD_COUNT_FOR_N_GRAM];
-        jsize prevWordsCount = env->GetArrayLength(prevWordCodePointArrays);
-        for (size_t i = 0; i < NELEMS(prevWordCodePoints); ++i) {
+        for (size_t i = 0; i < prevWordCount; ++i) {
             prevWordCodePointCount[i] = 0;
             isBeginningOfSentence[i] = false;
-            if (prevWordsCount <= static_cast<int>(i)) {
-                continue;
-            }
             jintArray prevWord = (jintArray)env->GetObjectArrayElement(prevWordCodePointArrays, i);
             if (!prevWord) {
                 continue;
@@ -117,14 +116,15 @@
                 continue;
             }
             env->GetIntArrayRegion(prevWord, 0, prevWordLength, prevWordCodePoints[i]);
+            env->DeleteLocalRef(prevWord);
             prevWordCodePointCount[i] = prevWordLength;
             jboolean isBeginningOfSentenceBoolean = JNI_FALSE;
             env->GetBooleanArrayRegion(isBeginningOfSentenceArray, i, 1 /* len */,
                     &isBeginningOfSentenceBoolean);
             isBeginningOfSentence[i] = isBeginningOfSentenceBoolean == JNI_TRUE;
         }
-        return PrevWordsInfo(prevWordCodePoints, prevWordCodePointCount, isBeginningOfSentence,
-                MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+        return NgramContext(prevWordCodePoints, prevWordCodePointCount, isBeginningOfSentence,
+                prevWordCount);
     }
 
     static void putBooleanToArray(JNIEnv *env, jbooleanArray array, const int index,
@@ -141,6 +141,12 @@
         env->SetFloatArrayRegion(array, index, 1 /* len */, &value);
     }
 
+    static void outputWordProperty(JNIEnv *const env, const WordProperty &wordProperty,
+            jintArray outCodePoints, jbooleanArray outFlags, jintArray outProbabilityInfo,
+            jobject outNgramPrevWordsArray, jobject outNgramPrevWordIsBeginningOfSentenceArray,
+            jobject outNgramTargets, jobject outNgramProbabilities, jobject outShortcutTargets,
+            jobject outShortcutProbabilities);
+
  private:
     DISALLOW_IMPLICIT_CONSTRUCTORS(JniDataUtils);
 
diff --git a/native/jni/src/utils/ngram_utils.h b/native/jni/src/utils/ngram_utils.h
new file mode 100644
index 0000000..fa85ba3
--- /dev/null
+++ b/native/jni/src/utils/ngram_utils.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_NGRAM_UTILS_H
+#define LATINIME_NGRAM_UTILS_H
+
+#include "defines.h"
+
+namespace latinime {
+
+enum class NgramType : int {
+    Unigram = 0,
+    Bigram = 1,
+    Trigram = 2,
+    Quadgram = 3,
+    NotANgramType = -1,
+};
+
+namespace AllNgramTypes {
+// Use anonymous namespace to avoid ODR (One Definition Rule) violation.
+namespace {
+
+const NgramType ASCENDING[] = {
+   NgramType::Unigram, NgramType::Bigram, NgramType::Trigram
+};
+
+const NgramType DESCENDING[] = {
+   NgramType::Trigram, NgramType::Bigram, NgramType::Unigram
+};
+
+}  // namespace
+}  // namespace AllNgramTypes
+
+class NgramUtils final {
+ public:
+    static AK_FORCE_INLINE NgramType getNgramTypeFromWordCount(const int wordCount) {
+        // Max supported ngram is (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram.
+        if (wordCount <= 0 || wordCount > MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1) {
+            return NgramType::NotANgramType;
+        }
+        // Convert word count to 0-origin enum value.
+        return static_cast<NgramType>(wordCount - 1);
+    }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(NgramUtils);
+
+};
+}
+#endif /* LATINIME_NGRAM_UTILS_H */
diff --git a/native/jni/src/utils/profiler.h b/native/jni/src/utils/profiler.h
new file mode 100644
index 0000000..5f107fe
--- /dev/null
+++ b/native/jni/src/utils/profiler.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014, 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.
+ */
+
+#ifndef LATINIME_PROFILER_H
+#define LATINIME_PROFILER_H
+
+#ifdef FLAG_DO_PROFILE
+
+#include "defines.h"
+
+#include <ctime>
+#include <unordered_map>
+
+namespace latinime {
+
+class Profiler final {
+ public:
+    Profiler(const clockid_t clockId)
+            : mClockId(clockId), mStartTime(getTimeInMicroSec()), mStartTimes(), mTimes(),
+              mCounters() {}
+
+    ~Profiler() {
+        const float totalTime =
+                static_cast<float>(getTimeInMicroSec() - mStartTime) / 1000.f;
+        AKLOGI("Total time is %6.3f ms.", totalTime);
+        for (const auto &time : mTimes) {
+            AKLOGI("(%d): Used %4.2f%%, %8.4f ms. Called %d times.", time.first,
+                    time.second / totalTime * 100.0f, time.second, mCounters[time.first]);
+        }
+    }
+
+    void startTimer(const int id) {
+        mStartTimes[id] = getTimeInMicroSec();
+    }
+
+    void endTimer(const int id) {
+        mTimes[id] += static_cast<float>(getTimeInMicroSec() - mStartTimes[id]) / 1000.0f;
+        mCounters[id]++;
+    }
+
+    operator bool() const { return false; }
+
+ private:
+    DISALLOW_IMPLICIT_CONSTRUCTORS(Profiler);
+
+    const clockid_t mClockId;
+    int64_t mStartTime;
+    std::unordered_map<int, int64_t> mStartTimes;
+    std::unordered_map<int, float> mTimes;
+    std::unordered_map<int, int> mCounters;
+
+    int64_t getTimeInMicroSec() {
+        timespec time;
+        clock_gettime(mClockId, &time);
+        return static_cast<int64_t>(time.tv_sec) * 1000000
+                + static_cast<int64_t>(time.tv_nsec) / 1000;
+    }
+};
+} // namespace latinime
+
+#define PROF_INIT Profiler __LATINIME__PROFILER__(CLOCK_THREAD_CPUTIME_ID)
+#define PROF_TIMER_START(timer_id) __LATINIME__PROFILER__.startTimer(timer_id)
+#define PROF_TIMER_END(timer_id) __LATINIME__PROFILER__.endTimer(timer_id)
+
+#else // FLAG_DO_PROFILE
+
+#define PROF_INIT
+#define PROF_TIMER_START(timer_id)
+#define PROF_TIMER_END(timer_id)
+
+#endif // FLAG_DO_PROFILE
+
+#endif /* LATINIME_PROFILER_H */
diff --git a/native/jni/tests/dictionary/header/header_read_write_utils_test.cpp b/native/jni/tests/dictionary/header/header_read_write_utils_test.cpp
new file mode 100644
index 0000000..eab5d65
--- /dev/null
+++ b/native/jni/tests/dictionary/header/header_read_write_utils_test.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/header/header_read_write_utils.h"
+
+#include <gtest/gtest.h>
+
+#include <cstring>
+#include <vector>
+
+#include "dictionary/interface/dictionary_header_structure_policy.h"
+
+namespace latinime {
+namespace {
+
+TEST(HeaderReadWriteUtilsTest, TestInsertCharactersIntoVector) {
+    DictionaryHeaderStructurePolicy::AttributeMap::key_type vector;
+
+    HeaderReadWriteUtils::insertCharactersIntoVector("", &vector);
+    EXPECT_TRUE(vector.empty());
+
+    static const char *str = "abc-xyz!?";
+    HeaderReadWriteUtils::insertCharactersIntoVector(str, &vector);
+    EXPECT_EQ(strlen(str) , vector.size());
+    for (size_t i = 0; i < vector.size(); ++i) {
+        EXPECT_EQ(str[i], vector[i]);
+    }
+}
+
+TEST(HeaderReadWriteUtilsTest, TestAttributeMapForInt) {
+    DictionaryHeaderStructurePolicy::AttributeMap attributeMap;
+
+    // Returns default value if not exists.
+    EXPECT_EQ(-1, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "", -1));
+    EXPECT_EQ(100, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "abc", 100));
+
+    HeaderReadWriteUtils::setIntAttribute(&attributeMap, "abc", 10);
+    EXPECT_EQ(10, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "abc", 100));
+    HeaderReadWriteUtils::setIntAttribute(&attributeMap, "abc", 20);
+    EXPECT_EQ(20, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "abc", 100));
+    HeaderReadWriteUtils::setIntAttribute(&attributeMap, "abcd", 30);
+    EXPECT_EQ(30, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "abcd", 100));
+    EXPECT_EQ(20, HeaderReadWriteUtils::readIntAttributeValue(&attributeMap, "abc", 100));
+}
+
+TEST(HeaderReadWriteUtilsTest, TestAttributeMapCodeForPoints) {
+    DictionaryHeaderStructurePolicy::AttributeMap attributeMap;
+
+    // Returns empty vector if not exists.
+    EXPECT_TRUE(HeaderReadWriteUtils::readCodePointVectorAttributeValue(&attributeMap, "").empty());
+    EXPECT_TRUE(HeaderReadWriteUtils::readCodePointVectorAttributeValue(
+            &attributeMap, "abc").empty());
+
+    HeaderReadWriteUtils::setCodePointVectorAttribute(&attributeMap, "abc", {});
+    EXPECT_TRUE(HeaderReadWriteUtils::readCodePointVectorAttributeValue(
+            &attributeMap, "abc").empty());
+
+    const std::vector<int> codePoints = { 0x0, 0x20, 0x1F, 0x100000 };
+    HeaderReadWriteUtils::setCodePointVectorAttribute(&attributeMap, "abc", codePoints);
+    EXPECT_EQ(codePoints, HeaderReadWriteUtils::readCodePointVectorAttributeValue(
+            &attributeMap, "abc"));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp b/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp
new file mode 100644
index 0000000..2e3047e
--- /dev/null
+++ b/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_global_counters_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/structure/v4/content/language_model_dict_content_global_counters.h"
+
+#include <gtest/gtest.h>
+
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+namespace {
+
+TEST(LanguageModelDictContentGlobalCountersTest, TestUpdateMaxValueOfCounters) {
+    LanguageModelDictContentGlobalCounters globalCounters;
+
+    EXPECT_FALSE(globalCounters.needsToHalveCounters());
+    globalCounters.updateMaxValueOfCounters(10);
+    EXPECT_FALSE(globalCounters.needsToHalveCounters());
+    const int count = (1 << (Ver4DictConstants::WORD_COUNT_FIELD_SIZE * CHAR_BIT)) - 1;
+    globalCounters.updateMaxValueOfCounters(count);
+    EXPECT_TRUE(globalCounters.needsToHalveCounters());
+    globalCounters.halveCounters();
+    EXPECT_FALSE(globalCounters.needsToHalveCounters());
+}
+
+TEST(LanguageModelDictContentGlobalCountersTest, TestIncrementTotalCount) {
+    LanguageModelDictContentGlobalCounters globalCounters;
+
+    EXPECT_EQ(0, globalCounters.getTotalCount());
+    globalCounters.incrementTotalCount();
+    EXPECT_EQ(1, globalCounters.getTotalCount());
+    for (int i = 1; i < 50; ++i) {
+        globalCounters.incrementTotalCount();
+    }
+    EXPECT_EQ(50, globalCounters.getTotalCount());
+    globalCounters.halveCounters();
+    EXPECT_EQ(25, globalCounters.getTotalCount());
+    globalCounters.halveCounters();
+    EXPECT_EQ(12, globalCounters.getTotalCount());
+    for (int i = 0; i < 4; ++i) {
+        globalCounters.halveCounters();
+    }
+    EXPECT_EQ(0, globalCounters.getTotalCount());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_test.cpp
new file mode 100644
index 0000000..ca8626e
--- /dev/null
+++ b/native/jni/tests/dictionary/structure/v4/content/language_model_dict_content_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/structure/v4/content/language_model_dict_content.h"
+
+#include <gtest/gtest.h>
+
+#include <array>
+#include <unordered_set>
+
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace {
+
+TEST(LanguageModelDictContentTest, TestUnigramProbability) {
+    LanguageModelDictContent languageModelDictContent(false /* useHistoricalInfo */);
+
+    const int flag = 0xF0;
+    const int probability = 10;
+    const int wordId = 100;
+    const ProbabilityEntry probabilityEntry(flag, probability);
+    languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
+    const ProbabilityEntry entry =
+            languageModelDictContent.getProbabilityEntry(wordId);
+    EXPECT_EQ(flag, entry.getFlags());
+    EXPECT_EQ(probability, entry.getProbability());
+
+    // Remove
+    EXPECT_TRUE(languageModelDictContent.removeProbabilityEntry(wordId));
+    EXPECT_FALSE(languageModelDictContent.getProbabilityEntry(wordId).isValid());
+    EXPECT_FALSE(languageModelDictContent.removeProbabilityEntry(wordId));
+    EXPECT_TRUE(languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry));
+    EXPECT_TRUE(languageModelDictContent.getProbabilityEntry(wordId).isValid());
+}
+
+TEST(LanguageModelDictContentTest, TestUnigramProbabilityWithHistoricalInfo) {
+    LanguageModelDictContent languageModelDictContent(true /* useHistoricalInfo */);
+
+    const int flag = 0xF0;
+    const int timestamp = 0x3FFFFFFF;
+    const int count = 10;
+    const int wordId = 100;
+    const HistoricalInfo historicalInfo(timestamp, 0 /* level */, count);
+    const ProbabilityEntry probabilityEntry(flag, &historicalInfo);
+    languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
+    const ProbabilityEntry entry = languageModelDictContent.getProbabilityEntry(wordId);
+    EXPECT_EQ(flag, entry.getFlags());
+    EXPECT_EQ(timestamp, entry.getHistoricalInfo()->getTimestamp());
+    EXPECT_EQ(count, entry.getHistoricalInfo()->getCount());
+
+    // Remove
+    EXPECT_TRUE(languageModelDictContent.removeProbabilityEntry(wordId));
+    EXPECT_FALSE(languageModelDictContent.getProbabilityEntry(wordId).isValid());
+    EXPECT_FALSE(languageModelDictContent.removeProbabilityEntry(wordId));
+    EXPECT_TRUE(languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry));
+    EXPECT_TRUE(languageModelDictContent.removeProbabilityEntry(wordId));
+}
+
+TEST(LanguageModelDictContentTest, TestIterateProbabilityEntry) {
+    LanguageModelDictContent languageModelDictContent(false /* useHistoricalInfo */);
+
+    const ProbabilityEntry originalEntry(0xFC, 100);
+
+    const int wordIds[] = { 1, 2, 3, 4, 5 };
+    for (const int wordId : wordIds) {
+        languageModelDictContent.setProbabilityEntry(wordId, &originalEntry);
+    }
+    std::unordered_set<int> wordIdSet(std::begin(wordIds), std::end(wordIds));
+    for (const auto entry : languageModelDictContent.getProbabilityEntries(WordIdArrayView())) {
+        EXPECT_EQ(originalEntry.getFlags(), entry.getProbabilityEntry().getFlags());
+        EXPECT_EQ(originalEntry.getProbability(), entry.getProbabilityEntry().getProbability());
+        wordIdSet.erase(entry.getWordId());
+    }
+    EXPECT_TRUE(wordIdSet.empty());
+}
+
+TEST(LanguageModelDictContentTest, TestGetWordProbability) {
+    LanguageModelDictContent languageModelDictContent(false /* useHistoricalInfo */);
+
+    const int flag = 0xFF;
+    const int probability = 10;
+    const int bigramProbability = 20;
+    const int trigramProbability = 30;
+    const int wordId = 100;
+    const std::array<int, 2> prevWordIdArray = {{ 1, 2 }};
+    const WordIdArrayView prevWordIds = WordIdArrayView::fromArray(prevWordIdArray);
+
+    const ProbabilityEntry probabilityEntry(flag, probability);
+    languageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
+    const ProbabilityEntry bigramProbabilityEntry(flag, bigramProbability);
+    languageModelDictContent.setProbabilityEntry(prevWordIds[0], &probabilityEntry);
+    languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(1), wordId,
+            &bigramProbabilityEntry);
+    EXPECT_EQ(bigramProbability, languageModelDictContent.getWordAttributes(prevWordIds, wordId,
+            false /* mustMatchAllPrevWords */, nullptr /* headerPolicy */).getProbability());
+    const ProbabilityEntry trigramProbabilityEntry(flag, trigramProbability);
+    languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(1),
+            prevWordIds[1], &probabilityEntry);
+    languageModelDictContent.setNgramProbabilityEntry(prevWordIds.limit(2), wordId,
+            &trigramProbabilityEntry);
+    EXPECT_EQ(trigramProbability, languageModelDictContent.getWordAttributes(prevWordIds, wordId,
+            false /* mustMatchAllPrevWords */, nullptr /* headerPolicy */).getProbability());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/structure/v4/content/probability_entry_test.cpp b/native/jni/tests/dictionary/structure/v4/content/probability_entry_test.cpp
new file mode 100644
index 0000000..ba81671
--- /dev/null
+++ b/native/jni/tests/dictionary/structure/v4/content/probability_entry_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/structure/v4/content/probability_entry.h"
+
+#include <gtest/gtest.h>
+
+#include "defines.h"
+
+namespace latinime {
+namespace {
+
+TEST(ProbabilityEntryTest, TestEncodeDecode) {
+    const int flag = 0xFF;
+    const int probability = 10;
+
+    const ProbabilityEntry entry(flag, probability);
+    const uint64_t encodedEntry = entry.encode(false /* hasHistoricalInfo */);
+    const ProbabilityEntry decodedEntry =
+            ProbabilityEntry::decode(encodedEntry, false /* hasHistoricalInfo */);
+    EXPECT_EQ(0xFF0Aull, encodedEntry);
+    EXPECT_EQ(flag, decodedEntry.getFlags());
+    EXPECT_EQ(probability, decodedEntry.getProbability());
+}
+
+TEST(ProbabilityEntryTest, TestEncodeDecodeWithHistoricalInfo) {
+    const int flag = 0xF0;
+    const int timestamp = 0x3FFFFFFF;
+    const int count = 0xABCD;
+
+    const HistoricalInfo historicalInfo(timestamp, 0 /* level */, count);
+    const ProbabilityEntry entry(flag, &historicalInfo);
+
+    const uint64_t encodedEntry = entry.encode(true /* hasHistoricalInfo */);
+    EXPECT_EQ(0xF03FFFFFFFABCDull, encodedEntry);
+    const ProbabilityEntry decodedEntry =
+            ProbabilityEntry::decode(encodedEntry, true /* hasHistoricalInfo */);
+
+    EXPECT_EQ(flag, decodedEntry.getFlags());
+    EXPECT_EQ(timestamp, decodedEntry.getHistoricalInfo()->getTimestamp());
+    EXPECT_EQ(count, decodedEntry.getHistoricalInfo()->getCount());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp b/native/jni/tests/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp
new file mode 100644
index 0000000..4f23889
--- /dev/null
+++ b/native/jni/tests/dictionary/structure/v4/content/terminal_position_lookup_table_test.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/structure/v4/content/terminal_position_lookup_table.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "defines.h"
+#include "dictionary/structure/v4/ver4_dict_constants.h"
+
+namespace latinime {
+namespace {
+
+TEST(TerminalPositionLookupTableTest, TestGetFromEmptyTable) {
+    TerminalPositionLookupTable lookupTable;
+
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(0));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(-1));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(
+            Ver4DictConstants::NOT_A_TERMINAL_ID));
+}
+
+TEST(TerminalPositionLookupTableTest, TestSetAndGet) {
+    TerminalPositionLookupTable lookupTable;
+
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(10, 100));
+    EXPECT_EQ(100, lookupTable.getTerminalPtNodePosition(10));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(9));
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(9, 200));
+    EXPECT_EQ(200, lookupTable.getTerminalPtNodePosition(9));
+    EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(10, 300));
+    EXPECT_EQ(300, lookupTable.getTerminalPtNodePosition(10));
+    EXPECT_FALSE(lookupTable.setTerminalPtNodePosition(-1, 400));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(-1));
+    EXPECT_FALSE(lookupTable.setTerminalPtNodePosition(Ver4DictConstants::NOT_A_TERMINAL_ID, 500));
+    EXPECT_EQ(NOT_A_DICT_POS, lookupTable.getTerminalPtNodePosition(
+            Ver4DictConstants::NOT_A_TERMINAL_ID));
+}
+
+TEST(TerminalPositionLookupTableTest, TestGC) {
+    TerminalPositionLookupTable lookupTable;
+
+    const std::vector<int> terminalIds = { 10, 20, 30 };
+    const std::vector<int> terminalPositions = { 100, 200, 300 };
+
+    for (size_t i = 0; i < terminalIds.size(); ++i) {
+        EXPECT_TRUE(lookupTable.setTerminalPtNodePosition(terminalIds[i], terminalPositions[i]));
+    }
+
+    TerminalPositionLookupTable::TerminalIdMap terminalIdMap;
+    EXPECT_TRUE(lookupTable.runGCTerminalIds(&terminalIdMap));
+
+    for (size_t i = 0; i < terminalIds.size(); ++i) {
+        EXPECT_EQ(static_cast<int>(i), terminalIdMap[terminalIds[i]])
+                << "Terminal id (" << terminalIds[i] << ") should be changed to " << i;
+        EXPECT_EQ(terminalPositions[i], lookupTable.getTerminalPtNodePosition(i));
+    }
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/bloom_filter_test.cpp b/native/jni/tests/dictionary/utils/bloom_filter_test.cpp
new file mode 100644
index 0000000..bcc8843
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/bloom_filter_test.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/bloom_filter.h"
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <random>
+#include <unordered_set>
+#include <vector>
+
+namespace latinime {
+namespace {
+
+TEST(BloomFilterTest, TestFilter) {
+    static const int TEST_RANDOM_DATA_MAX = 65536;
+    static const int ELEMENT_COUNT = 1000;
+    std::vector<int> elements;
+
+    // Initialize data set with random integers.
+    {
+        // Use the uniform integer distribution [0, TEST_RANDOM_DATA_MAX].
+        std::uniform_int_distribution<int> distribution(0, TEST_RANDOM_DATA_MAX);
+        auto randomNumberGenerator = std::bind(distribution, std::mt19937());
+        for (int i = 0; i < ELEMENT_COUNT; ++i) {
+            elements.push_back(randomNumberGenerator());
+        }
+    }
+
+    // Make sure BloomFilter contains nothing by default.
+    BloomFilter bloomFilter;
+    for (const int elem : elements) {
+        ASSERT_FALSE(bloomFilter.isInFilter(elem));
+    }
+
+    // Copy some of the test vector into bloom filter.
+    std::unordered_set<int> elementsThatHaveBeenSetInFilter;
+    {
+        // Use the uniform integer distribution [0, 1].
+        std::uniform_int_distribution<int> distribution(0, 1);
+        auto randomBitGenerator = std::bind(distribution, std::mt19937());
+        for (const int elem : elements) {
+            if (randomBitGenerator() == 0) {
+                bloomFilter.setInFilter(elem);
+                elementsThatHaveBeenSetInFilter.insert(elem);
+            }
+        }
+    }
+
+    for (const int elem : elements) {
+        const bool existsInFilter = bloomFilter.isInFilter(elem);
+        const bool hasBeenSetInFilter =
+                elementsThatHaveBeenSetInFilter.find(elem) != elementsThatHaveBeenSetInFilter.end();
+        if (hasBeenSetInFilter) {
+            EXPECT_TRUE(existsInFilter) << "elem: " << elem;
+        }
+        if (!existsInFilter) {
+            EXPECT_FALSE(hasBeenSetInFilter) << "elem: " << elem;
+        }
+    }
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/buffer_with_extendable_buffer_test.cpp b/native/jni/tests/dictionary/utils/buffer_with_extendable_buffer_test.cpp
new file mode 100644
index 0000000..2587891
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/buffer_with_extendable_buffer_test.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+const int DEFAULT_MAX_BUFFER_SIZE = 1024;
+
+TEST(BufferWithExtendablebufferTest, TestWriteAndRead) {
+    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
+    int pos = 0;
+    // 1 byte
+    const uint32_t data_1 = 0xFF;
+    EXPECT_TRUE(buffer.writeUint(data_1, 1 /* size */, pos));
+    EXPECT_EQ(data_1, buffer.readUint(1, pos));
+    pos += 1;
+    // 2 byte
+    const uint32_t data_2 = 0xFFFF;
+    EXPECT_TRUE(buffer.writeUint(data_2, 2 /* size */, pos));
+    EXPECT_EQ(data_2, buffer.readUint(2, pos));
+    pos += 2;
+    // 3 byte
+    const uint32_t data_3 = 0xFFFFFF;
+    EXPECT_TRUE(buffer.writeUint(data_3, 3 /* size */, pos));
+    EXPECT_EQ(data_3, buffer.readUint(3, pos));
+    pos += 3;
+    // 4 byte
+    const uint32_t data_4 = 0xFFFFFFFF;
+    EXPECT_TRUE(buffer.writeUint(data_4, 4 /* size */, pos));
+    EXPECT_EQ(data_4, buffer.readUint(4, pos));
+}
+
+TEST(BufferWithExtendablebufferTest, TestExtend) {
+    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
+    EXPECT_EQ(0, buffer.getTailPosition());
+    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
+    EXPECT_EQ(4, buffer.getTailPosition());
+    EXPECT_TRUE(buffer.extend(8 /* size */));
+    EXPECT_EQ(12, buffer.getTailPosition());
+    EXPECT_TRUE(buffer.writeUint(0xFFFF /* data */, 4 /* size */, 8 /* pos */));
+    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
+}
+
+TEST(BufferWithExtendablebufferTest, TestCopy) {
+    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
+    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
+    EXPECT_TRUE(buffer.writeUint(0xFFFF /* data */, 4 /* size */, 4 /* pos */));
+    BufferWithExtendableBuffer targetBuffer(DEFAULT_MAX_BUFFER_SIZE);
+    EXPECT_TRUE(targetBuffer.copy(&buffer));
+    EXPECT_EQ(0xFFu, targetBuffer.readUint(4 /* size */, 0 /* pos */));
+    EXPECT_EQ(0xFFFFu, targetBuffer.readUint(4 /* size */, 4 /* pos */));
+}
+
+TEST(BufferWithExtendablebufferTest, TestSizeLimit) {
+    BufferWithExtendableBuffer emptyBuffer(0 /* maxAdditionalBufferSize */);
+    EXPECT_FALSE(emptyBuffer.writeUint(0 /* data */, 1 /* size */, 0 /* pos */));
+    EXPECT_FALSE(emptyBuffer.extend(1 /* size */));
+
+    BufferWithExtendableBuffer smallBuffer(4 /* maxAdditionalBufferSize */);
+    EXPECT_TRUE(smallBuffer.writeUint(0 /* data */, 4 /* size */, 0 /* pos */));
+    EXPECT_FALSE(smallBuffer.writeUint(0 /* data */, 1 /* size */, 4 /* pos */));
+
+    EXPECT_TRUE(smallBuffer.copy(&emptyBuffer));
+    EXPECT_FALSE(emptyBuffer.copy(&smallBuffer));
+
+    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
+    EXPECT_FALSE(buffer.isNearSizeLimit());
+    int pos = 0;
+    while (!buffer.isNearSizeLimit()) {
+        EXPECT_TRUE(buffer.writeUintAndAdvancePosition(0 /* data */, 4 /* size */, &pos));
+    }
+    EXPECT_GT(pos, 0);
+    EXPECT_LE(pos, DEFAULT_MAX_BUFFER_SIZE);
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/byte_array_utils_test.cpp b/native/jni/tests/dictionary/utils/byte_array_utils_test.cpp
new file mode 100644
index 0000000..0725753
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/byte_array_utils_test.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/byte_array_utils.h"
+
+#include <gtest/gtest.h>
+
+#include <cstdint>
+
+namespace latinime {
+namespace {
+
+TEST(ByteArrayUtilsTest, TestReadCodePointTable) {
+    const int codePointTable[] = { 0x6f, 0x6b };
+    const uint8_t buffer[] = { 0x20u, 0x21u, 0x00u, 0x01u, 0x00u };
+    int pos = 0;
+    // Expect the first entry of codePointTable
+    EXPECT_EQ(0x6f, ByteArrayUtils::readCodePointAndAdvancePosition(buffer, codePointTable, &pos));
+    // Expect the second entry of codePointTable
+    EXPECT_EQ(0x6b, ByteArrayUtils::readCodePointAndAdvancePosition(buffer, codePointTable, &pos));
+    // Expect the original code point from buffer[2] to buffer[4], 0x100
+    // It isn't picked from the codePointTable, since it exceeds the range of the codePointTable.
+    EXPECT_EQ(0x100, ByteArrayUtils::readCodePointAndAdvancePosition(buffer, codePointTable, &pos));
+}
+
+TEST(ByteArrayUtilsTest, TestReadInt) {
+    const uint8_t buffer[] = { 0x1u, 0x8Au, 0x0u, 0xAAu };
+
+    EXPECT_EQ(0x01u, ByteArrayUtils::readUint8(buffer, 0));
+    EXPECT_EQ(0x8Au, ByteArrayUtils::readUint8(buffer, 1));
+    EXPECT_EQ(0x0u, ByteArrayUtils::readUint8(buffer, 2));
+    EXPECT_EQ(0xAAu, ByteArrayUtils::readUint8(buffer, 3));
+
+    EXPECT_EQ(0x018Au, ByteArrayUtils::readUint16(buffer, 0));
+    EXPECT_EQ(0x8A00u, ByteArrayUtils::readUint16(buffer, 1));
+    EXPECT_EQ(0xAAu, ByteArrayUtils::readUint16(buffer, 2));
+
+    EXPECT_EQ(0x18A00AAu, ByteArrayUtils::readUint32(buffer, 0));
+
+    int pos = 0;
+    EXPECT_EQ(0x18A00, ByteArrayUtils::readSint24AndAdvancePosition(buffer, &pos));
+    pos = 1;
+    EXPECT_EQ(-0xA00AA, ByteArrayUtils::readSint24AndAdvancePosition(buffer, &pos));
+}
+
+TEST(ByteArrayUtilsTest, TestWriteAndReadInt) {
+    uint8_t buffer[4];
+
+    int pos = 0;
+    const uint8_t data_1B = 0xC8;
+    ByteArrayUtils::writeUintAndAdvancePosition(buffer, data_1B, 1, &pos);
+    EXPECT_EQ(data_1B, ByteArrayUtils::readUint(buffer, 1, 0));
+
+    pos = 0;
+    const uint32_t data_4B = 0xABCD1234;
+    ByteArrayUtils::writeUintAndAdvancePosition(buffer, data_4B, 4, &pos);
+    EXPECT_EQ(data_4B, ByteArrayUtils::readUint(buffer, 4, 0));
+}
+
+TEST(ByteArrayUtilsTest, TestReadCodePoint) {
+    const uint8_t buffer[] = { 0x10, 0xFF, 0x00u, 0x20u, 0x41u, 0x1Fu, 0x60 };
+
+    EXPECT_EQ(0x10FF00, ByteArrayUtils::readCodePoint(buffer, 0));
+    EXPECT_EQ(0x20, ByteArrayUtils::readCodePoint(buffer, 3));
+    EXPECT_EQ(0x41, ByteArrayUtils::readCodePoint(buffer, 4));
+    EXPECT_EQ(NOT_A_CODE_POINT, ByteArrayUtils::readCodePoint(buffer, 5));
+
+    int pos = 0;
+    int codePointArray[3];
+    EXPECT_EQ(3, ByteArrayUtils::readStringAndAdvancePosition(buffer, MAX_WORD_LENGTH, nullptr,
+            codePointArray, &pos));
+    EXPECT_EQ(0x10FF00, codePointArray[0]);
+    EXPECT_EQ(0x20, codePointArray[1]);
+    EXPECT_EQ(0x41, codePointArray[2]);
+    EXPECT_EQ(0x60, ByteArrayUtils::readCodePoint(buffer, pos));
+}
+
+TEST(ByteArrayUtilsTest, TestWriteAndReadCodePoint) {
+    uint8_t buffer[10];
+
+    const int codePointArray[] = { 0x10FF00, 0x20, 0x41 };
+    int pos = 0;
+    ByteArrayUtils::writeCodePointsAndAdvancePosition(buffer, codePointArray, 3,
+            true /* writesTerminator */, &pos);
+    EXPECT_EQ(0x10FF00, ByteArrayUtils::readCodePoint(buffer, 0));
+    EXPECT_EQ(0x20, ByteArrayUtils::readCodePoint(buffer, 3));
+    EXPECT_EQ(0x41, ByteArrayUtils::readCodePoint(buffer, 4));
+    EXPECT_EQ(NOT_A_CODE_POINT, ByteArrayUtils::readCodePoint(buffer, 5));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/format_utils_test.cpp b/native/jni/tests/dictionary/utils/format_utils_test.cpp
new file mode 100644
index 0000000..3561bda
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/format_utils_test.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/format_utils.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "utils/byte_array_view.h"
+
+namespace latinime {
+namespace {
+
+TEST(FormatUtilsTest, TestMagicNumber) {
+    EXPECT_EQ(0x9BC13AFE, FormatUtils::MAGIC_NUMBER) << "Magic number must not be changed.";
+}
+
+const std::vector<uint8_t> getBuffer(const int magicNumber, const int version, const uint16_t flags,
+        const size_t headerSize) {
+    std::vector<uint8_t> buffer;
+    buffer.push_back(magicNumber >> 24);
+    buffer.push_back(magicNumber >> 16);
+    buffer.push_back(magicNumber >> 8);
+    buffer.push_back(magicNumber);
+
+    buffer.push_back(version >> 8);
+    buffer.push_back(version);
+
+    buffer.push_back(flags >> 8);
+    buffer.push_back(flags);
+
+    buffer.push_back(headerSize >> 24);
+    buffer.push_back(headerSize >> 16);
+    buffer.push_back(headerSize >> 8);
+    buffer.push_back(headerSize);
+    return buffer;
+}
+
+TEST(FormatUtilsTest, TestDetectFormatVersion) {
+    EXPECT_EQ(FormatUtils::UNKNOWN_VERSION,
+            FormatUtils::detectFormatVersion(ReadOnlyByteArrayView()));
+
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_2, 0, 0);
+        EXPECT_EQ(FormatUtils::VERSION_2, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size())));
+    }
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_402, 0, 0);
+        EXPECT_EQ(FormatUtils::VERSION_402, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size())));
+    }
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_403, 0, 0);
+        EXPECT_EQ(FormatUtils::VERSION_403, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size())));
+    }
+
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER - 1, FormatUtils::VERSION_2, 0, 0);
+        EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size())));
+    }
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER, 100, 0, 0);
+        EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size())));
+    }
+    {
+        const std::vector<uint8_t> buffer =
+                getBuffer(FormatUtils::MAGIC_NUMBER, FormatUtils::VERSION_2, 0, 0);
+        EXPECT_EQ(FormatUtils::UNKNOWN_VERSION, FormatUtils::detectFormatVersion(
+                ReadOnlyByteArrayView(buffer.data(), buffer.size() - 1)));
+    }
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/probability_utils_test.cpp b/native/jni/tests/dictionary/utils/probability_utils_test.cpp
new file mode 100644
index 0000000..4020ea4
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/probability_utils_test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/probability_utils.h"
+
+#include <gtest/gtest.h>
+
+#include "defines.h"
+
+namespace latinime {
+namespace {
+
+TEST(ProbabilityUtilsTest, TestEncodeRawProbability) {
+    EXPECT_EQ(MAX_PROBABILITY, ProbabilityUtils::encodeRawProbability(1.0f));
+    EXPECT_EQ(MAX_PROBABILITY - 9, ProbabilityUtils::encodeRawProbability(0.5f));
+    EXPECT_EQ(0, ProbabilityUtils::encodeRawProbability(0.0f));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/sparse_table_test.cpp b/native/jni/tests/dictionary/utils/sparse_table_test.cpp
new file mode 100644
index 0000000..237c963
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/sparse_table_test.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/sparse_table.h"
+
+#include <gtest/gtest.h>
+
+#include "dictionary/utils/buffer_with_extendable_buffer.h"
+
+namespace latinime {
+namespace {
+
+TEST(SparseTableTest, TestSetAndGet) {
+    static const int BLOCK_SIZE = 64;
+    static const int DATA_SIZE = 4;
+    BufferWithExtendableBuffer indexTableBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    BufferWithExtendableBuffer contentTableBuffer(
+            BufferWithExtendableBuffer::DEFAULT_MAX_ADDITIONAL_BUFFER_SIZE);
+    SparseTable sparseTable(&indexTableBuffer, &contentTableBuffer, BLOCK_SIZE, DATA_SIZE);
+
+    EXPECT_FALSE(sparseTable.contains(10));
+    EXPECT_TRUE(sparseTable.set(10, 100u));
+    EXPECT_EQ(100u, sparseTable.get(10));
+    EXPECT_TRUE(sparseTable.contains(10));
+    EXPECT_TRUE(sparseTable.contains(BLOCK_SIZE - 1));
+    EXPECT_FALSE(sparseTable.contains(BLOCK_SIZE));
+    EXPECT_TRUE(sparseTable.set(11, 101u));
+    EXPECT_EQ(100u, sparseTable.get(10));
+    EXPECT_EQ(101u, sparseTable.get(11));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/dictionary/utils/trie_map_test.cpp b/native/jni/tests/dictionary/utils/trie_map_test.cpp
new file mode 100644
index 0000000..745d398
--- /dev/null
+++ b/native/jni/tests/dictionary/utils/trie_map_test.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "dictionary/utils/trie_map.h"
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <cstdlib>
+#include <functional>
+#include <map>
+#include <random>
+#include <unordered_map>
+
+namespace latinime {
+namespace {
+
+TEST(TrieMapTest, TestSetAndGet) {
+    TrieMap trieMap;
+    trieMap.putRoot(10, 10);
+    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
+    trieMap.putRoot(0x10A, 10);
+    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
+    EXPECT_EQ(10ull, trieMap.getRoot(0x10A).mValue);
+    trieMap.putRoot(10, 1000);
+    EXPECT_EQ(1000ull, trieMap.getRoot(10).mValue);
+    trieMap.putRoot(11, 1000);
+    EXPECT_EQ(1000ull, trieMap.getRoot(11).mValue);
+    const int next = trieMap.getNextLevelBitmapEntryIndex(10);
+    EXPECT_EQ(1000ull, trieMap.getRoot(10).mValue);
+    trieMap.put(9, 9, next);
+    EXPECT_EQ(9ull, trieMap.get(9, next).mValue);
+    EXPECT_FALSE(trieMap.get(11, next).mIsValid);
+    trieMap.putRoot(0, 0xFFFFFFFFFull);
+    EXPECT_EQ(0xFFFFFFFFFull, trieMap.getRoot(0).mValue);
+}
+
+TEST(TrieMapTest, TestRemove) {
+    TrieMap trieMap;
+    trieMap.putRoot(10, 10);
+    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
+    EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+    EXPECT_FALSE(trieMap.getRoot(10).mIsValid);
+    for (const auto &element : trieMap.getEntriesInRootLevel()) {
+        EXPECT_TRUE(false);
+    }
+    EXPECT_TRUE(trieMap.putRoot(10, 0x3FFFFF));
+    EXPECT_FALSE(trieMap.remove(11, trieMap.getRootBitmapEntryIndex()))
+            << "Should fail if the key does not exist.";
+    EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+    trieMap.putRoot(12, 11);
+    const int nextLevel = trieMap.getNextLevelBitmapEntryIndex(10);
+    trieMap.put(10, 10, nextLevel);
+    EXPECT_EQ(0x3FFFFFull, trieMap.getRoot(10).mValue);
+    EXPECT_EQ(10ull, trieMap.get(10, nextLevel).mValue);
+    EXPECT_TRUE(trieMap.remove(10, trieMap.getRootBitmapEntryIndex()));
+    const TrieMap::Result result = trieMap.getRoot(10);
+    EXPECT_FALSE(result.mIsValid);
+    EXPECT_EQ(TrieMap::INVALID_INDEX, result.mNextLevelBitmapEntryIndex);
+    EXPECT_EQ(11ull, trieMap.getRoot(12).mValue);
+    EXPECT_TRUE(trieMap.putRoot(S_INT_MAX, 0xFFFFFFFFFull));
+    EXPECT_TRUE(trieMap.remove(S_INT_MAX, trieMap.getRootBitmapEntryIndex()));
+}
+
+TEST(TrieMapTest, TestSetAndGetLarge) {
+    static const int ELEMENT_COUNT = 200000;
+    TrieMap trieMap;
+    for (int i = 0; i < ELEMENT_COUNT; ++i) {
+        EXPECT_TRUE(trieMap.putRoot(i, i));
+    }
+    for (int i = 0; i < ELEMENT_COUNT; ++i) {
+        EXPECT_EQ(static_cast<uint64_t>(i), trieMap.getRoot(i).mValue);
+    }
+}
+
+TEST(TrieMapTest, TestRandSetAndGetLarge) {
+    static const int ELEMENT_COUNT = 100000;
+    TrieMap trieMap;
+    std::unordered_map<int, uint64_t> testKeyValuePairs;
+
+    // Use the uniform integer distribution [S_INT_MIN, S_INT_MAX].
+    std::uniform_int_distribution<int> keyDistribution(S_INT_MIN, S_INT_MAX);
+    auto keyRandomNumberGenerator = std::bind(keyDistribution, std::mt19937());
+
+    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
+    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
+    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
+
+    for (int i = 0; i < ELEMENT_COUNT; ++i) {
+        const int key = keyRandomNumberGenerator();
+        const uint64_t value = valueRandomNumberGenerator();
+        EXPECT_TRUE(trieMap.putRoot(key, value)) << key << " " << value;
+        testKeyValuePairs[key] = value;
+    }
+    for (const auto &v : testKeyValuePairs) {
+        EXPECT_EQ(v.second, trieMap.getRoot(v.first).mValue);
+    }
+}
+
+TEST(TrieMapTest, TestMultiLevel) {
+    static const int FIRST_LEVEL_ENTRY_COUNT = 10000;
+    static const int SECOND_LEVEL_ENTRY_COUNT = 20000;
+    static const int THIRD_LEVEL_ENTRY_COUNT = 40000;
+
+    TrieMap trieMap;
+    std::vector<int> firstLevelKeys;
+    std::map<int, uint64_t> firstLevelEntries;
+    std::vector<std::pair<int, int>> secondLevelKeys;
+    std::map<int, std::map<int, uint64_t>> twoLevelMap;
+    std::map<int, std::map<int, std::map<int, uint64_t>>> threeLevelMap;
+
+    // Use the uniform integer distribution [0, S_INT_MAX].
+    std::uniform_int_distribution<int> distribution(0, S_INT_MAX);
+    auto keyRandomNumberGenerator = std::bind(distribution, std::mt19937());
+    auto randomNumberGeneratorForKeySelection = std::bind(distribution, std::mt19937());
+
+    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
+    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
+    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
+
+    for (int i = 0; i < FIRST_LEVEL_ENTRY_COUNT; ++i) {
+        const int key = keyRandomNumberGenerator();
+        const uint64_t value = valueRandomNumberGenerator();
+        EXPECT_TRUE(trieMap.putRoot(key, value));
+        firstLevelKeys.push_back(key);
+        firstLevelEntries[key] = value;
+    }
+
+    for (int i = 0; i < SECOND_LEVEL_ENTRY_COUNT; ++i) {
+        const int key = keyRandomNumberGenerator();
+        const uint64_t value = valueRandomNumberGenerator();
+        const int firstLevelKey =
+                firstLevelKeys[randomNumberGeneratorForKeySelection() % FIRST_LEVEL_ENTRY_COUNT];
+        const int nextLevelBitmapEntryIndex = trieMap.getNextLevelBitmapEntryIndex(firstLevelKey);
+        EXPECT_NE(TrieMap::INVALID_INDEX, nextLevelBitmapEntryIndex);
+        EXPECT_TRUE(trieMap.put(key, value, nextLevelBitmapEntryIndex));
+        secondLevelKeys.push_back(std::make_pair(firstLevelKey, key));
+        twoLevelMap[firstLevelKey][key] = value;
+    }
+
+    for (int i = 0; i < THIRD_LEVEL_ENTRY_COUNT; ++i) {
+        const int key = keyRandomNumberGenerator();
+        const uint64_t value = valueRandomNumberGenerator();
+        const std::pair<int, int> secondLevelKey =
+                secondLevelKeys[randomNumberGeneratorForKeySelection() % SECOND_LEVEL_ENTRY_COUNT];
+        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(secondLevelKey.first);
+        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
+        const int thirdLevel = trieMap.getNextLevelBitmapEntryIndex(
+                secondLevelKey.second, secondLevel);
+        EXPECT_NE(TrieMap::INVALID_INDEX, thirdLevel);
+        EXPECT_TRUE(trieMap.put(key, value, thirdLevel));
+        threeLevelMap[secondLevelKey.first][secondLevelKey.second][key] = value;
+    }
+
+    for (const auto &firstLevelEntry : firstLevelEntries) {
+        EXPECT_EQ(firstLevelEntry.second, trieMap.getRoot(firstLevelEntry.first).mValue);
+    }
+
+    for (const auto &firstLevelEntry : twoLevelMap) {
+        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(firstLevelEntry.first);
+        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
+        for (const auto &secondLevelEntry : firstLevelEntry.second) {
+            EXPECT_EQ(secondLevelEntry.second,
+                    trieMap.get(secondLevelEntry.first, secondLevel).mValue);
+        }
+    }
+
+    for (const auto &firstLevelEntry : threeLevelMap) {
+        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(firstLevelEntry.first);
+        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
+        for (const auto &secondLevelEntry : firstLevelEntry.second) {
+            const int thirdLevel =
+                    trieMap.getNextLevelBitmapEntryIndex(secondLevelEntry.first, secondLevel);
+            EXPECT_NE(TrieMap::INVALID_INDEX, thirdLevel);
+            for (const auto &thirdLevelEntry : secondLevelEntry.second) {
+                EXPECT_EQ(thirdLevelEntry.second,
+                        trieMap.get(thirdLevelEntry.first, thirdLevel).mValue);
+            }
+        }
+    }
+
+    // Iteration
+    for (const auto &firstLevelEntry : trieMap.getEntriesInRootLevel()) {
+        EXPECT_EQ(trieMap.getRoot(firstLevelEntry.key()).mValue, firstLevelEntry.value());
+        EXPECT_EQ(firstLevelEntries[firstLevelEntry.key()], firstLevelEntry.value());
+        firstLevelEntries.erase(firstLevelEntry.key());
+        for (const auto &secondLevelEntry : firstLevelEntry.getEntriesInNextLevel()) {
+            EXPECT_EQ(twoLevelMap[firstLevelEntry.key()][secondLevelEntry.key()],
+                    secondLevelEntry.value());
+            twoLevelMap[firstLevelEntry.key()].erase(secondLevelEntry.key());
+            for (const auto &thirdLevelEntry : secondLevelEntry.getEntriesInNextLevel()) {
+                EXPECT_EQ(threeLevelMap[firstLevelEntry.key()][secondLevelEntry.key()]
+                        [thirdLevelEntry.key()], thirdLevelEntry.value());
+                threeLevelMap[firstLevelEntry.key()][secondLevelEntry.key()].erase(
+                        thirdLevelEntry.key());
+            }
+        }
+    }
+
+    // Ensure all entries have been traversed.
+    EXPECT_TRUE(firstLevelEntries.empty());
+    for (const auto &secondLevelEntry : twoLevelMap) {
+        EXPECT_TRUE(secondLevelEntry.second.empty());
+    }
+    for (const auto &secondLevelEntry : threeLevelMap) {
+        for (const auto &thirdLevelEntry : secondLevelEntry.second) {
+            EXPECT_TRUE(thirdLevelEntry.second.empty());
+        }
+    }
+}
+
+TEST(TrieMapTest, TestIteration) {
+    static const int ELEMENT_COUNT = 200000;
+    TrieMap trieMap;
+    std::unordered_map<int, uint64_t> testKeyValuePairs;
+
+    // Use the uniform integer distribution [S_INT_MIN, S_INT_MAX].
+    std::uniform_int_distribution<int> keyDistribution(S_INT_MIN, S_INT_MAX);
+    auto keyRandomNumberGenerator = std::bind(keyDistribution, std::mt19937());
+
+    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
+    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
+    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
+    for (int i = 0; i < ELEMENT_COUNT; ++i) {
+        const int key = keyRandomNumberGenerator();
+        const uint64_t value = valueRandomNumberGenerator();
+        EXPECT_TRUE(trieMap.putRoot(key, value));
+        testKeyValuePairs[key] = value;
+    }
+    for (const auto &entry : trieMap.getEntriesInRootLevel()) {
+        EXPECT_EQ(trieMap.getRoot(entry.key()).mValue, entry.value());
+        EXPECT_EQ(testKeyValuePairs[entry.key()], entry.value());
+        testKeyValuePairs.erase(entry.key());
+    }
+    EXPECT_TRUE(testKeyValuePairs.empty());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp b/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp
new file mode 100644
index 0000000..854efdf
--- /dev/null
+++ b/native/jni/tests/suggest/core/dicnode/dic_node_pool_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "suggest/core/dicnode/dic_node_pool.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+TEST(DicNodePoolTest, TestGet) {
+    static const int CAPACITY = 10;
+    DicNodePool dicNodePool(CAPACITY);
+
+    for (int i = 0; i < CAPACITY; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+}
+
+TEST(DicNodePoolTest, TestPlaceBack) {
+    static const int CAPACITY = 1;
+    DicNodePool dicNodePool(CAPACITY);
+
+    DicNode *const dicNode = dicNodePool.getInstance();
+    EXPECT_NE(nullptr, dicNode);
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+    dicNodePool.placeBackInstance(dicNode);
+    EXPECT_EQ(dicNode, dicNodePool.getInstance());
+}
+
+TEST(DicNodePoolTest, TestReset) {
+    static const int CAPACITY_SMALL = 2;
+    static const int CAPACITY_LARGE = 10;
+    DicNodePool dicNodePool(CAPACITY_SMALL);
+
+    for (int i = 0; i < CAPACITY_SMALL; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+
+    dicNodePool.reset(CAPACITY_LARGE);
+    for (int i = 0; i < CAPACITY_LARGE; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+
+    dicNodePool.reset(CAPACITY_SMALL);
+    for (int i = 0; i < CAPACITY_SMALL; ++i) {
+        EXPECT_NE(nullptr, dicNodePool.getInstance());
+    }
+    EXPECT_EQ(nullptr, dicNodePool.getInstance());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/suggest/core/dictionary/bloom_filter_test.cpp b/native/jni/tests/suggest/core/dictionary/bloom_filter_test.cpp
deleted file mode 100644
index b620217..0000000
--- a/native/jni/tests/suggest/core/dictionary/bloom_filter_test.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "suggest/core/dictionary/bloom_filter.h"
-
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <functional>
-#include <random>
-#include <unordered_set>
-#include <vector>
-
-namespace latinime {
-namespace {
-
-TEST(BloomFilterTest, TestFilter) {
-    static const int TEST_RANDOM_DATA_MAX = 65536;
-    static const int ELEMENT_COUNT = 1000;
-    std::vector<int> elements;
-
-    // Initialize data set with random integers.
-    {
-        // Use the uniform integer distribution [0, TEST_RANDOM_DATA_MAX].
-        std::uniform_int_distribution<int> distribution(0, TEST_RANDOM_DATA_MAX);
-        auto randomNumberGenerator = std::bind(distribution, std::mt19937());
-        for (int i = 0; i < ELEMENT_COUNT; ++i) {
-            elements.push_back(randomNumberGenerator());
-        }
-    }
-
-    // Make sure BloomFilter contains nothing by default.
-    BloomFilter bloomFilter;
-    for (const int elem : elements) {
-        ASSERT_FALSE(bloomFilter.isInFilter(elem));
-    }
-
-    // Copy some of the test vector into bloom filter.
-    std::unordered_set<int> elementsThatHaveBeenSetInFilter;
-    {
-        // Use the uniform integer distribution [0, 1].
-        std::uniform_int_distribution<int> distribution(0, 1);
-        auto randomBitGenerator = std::bind(distribution, std::mt19937());
-        for (const int elem : elements) {
-            if (randomBitGenerator() == 0) {
-                bloomFilter.setInFilter(elem);
-                elementsThatHaveBeenSetInFilter.insert(elem);
-            }
-        }
-    }
-
-    for (const int elem : elements) {
-        const bool existsInFilter = bloomFilter.isInFilter(elem);
-        const bool hasBeenSetInFilter =
-                elementsThatHaveBeenSetInFilter.find(elem) != elementsThatHaveBeenSetInFilter.end();
-        if (hasBeenSetInFilter) {
-            EXPECT_TRUE(existsInFilter) << "elem: " << elem;
-        }
-        if (!existsInFilter) {
-            EXPECT_FALSE(hasBeenSetInFilter) << "elem: " << elem;
-        }
-    }
-}
-
-}  // namespace
-}  // namespace latinime
diff --git a/native/jni/tests/suggest/core/layout/geometry_utils_test.cpp b/native/jni/tests/suggest/core/layout/geometry_utils_test.cpp
new file mode 100644
index 0000000..f5f89ed
--- /dev/null
+++ b/native/jni/tests/suggest/core/layout/geometry_utils_test.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "suggest/core/layout/geometry_utils.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+::testing::AssertionResult ExpectAngleDiffEq(const char* expectedExpression,
+      const char* actualExpression, float expected, float actual) {
+    if (actual < 0.0f || M_PI_F < actual) {
+        return ::testing::AssertionFailure()
+              << "Must be in the range of [0.0f, M_PI_F]."
+              << " expected: " << expected
+              << " actual: " << actual;
+    }
+    return ::testing::internal::CmpHelperFloatingPointEQ<float>(
+            expectedExpression, actualExpression, expected, actual);
+}
+
+#define EXPECT_ANGLE_DIFF_EQ(expected, actual) \
+        EXPECT_PRED_FORMAT2(ExpectAngleDiffEq, expected, actual);
+
+TEST(GeometryUtilsTest, testSquareFloat) {
+    const float test_data[] = { 0.0f, 1.0f, 123.456f, -1.0f, -9876.54321f };
+    for (const float value : test_data) {
+        EXPECT_FLOAT_EQ(value * value, GeometryUtils::SQUARE_FLOAT(value));
+    }
+}
+
+TEST(GeometryUtilsTest, testGetAngle) {
+    EXPECT_FLOAT_EQ(0.0f, GeometryUtils::getAngle(0, 0, 0, 0));
+    EXPECT_FLOAT_EQ(0.0f, GeometryUtils::getAngle(100, -10, 100, -10));
+
+    EXPECT_FLOAT_EQ(M_PI_F / 4.0f, GeometryUtils::getAngle(1, 1, 0, 0));
+    EXPECT_FLOAT_EQ(M_PI_F, GeometryUtils::getAngle(-1, 0, 0, 0));
+
+    EXPECT_FLOAT_EQ(GeometryUtils::getAngle(0, 0, -1, 0), GeometryUtils::getAngle(1, 0, 0, 0));
+    EXPECT_FLOAT_EQ(GeometryUtils::getAngle(1, 2, 3, 4),
+            GeometryUtils::getAngle(100, 200, 300, 400));
+}
+
+TEST(GeometryUtilsTest, testGetAngleDiff) {
+    EXPECT_ANGLE_DIFF_EQ(0.0f, GeometryUtils::getAngleDiff(0.0f, 0.0f));
+    EXPECT_ANGLE_DIFF_EQ(0.0f, GeometryUtils::getAngleDiff(10000.0f, 10000.0f));
+    EXPECT_ANGLE_DIFF_EQ(ROUND_FLOAT_10000(M_PI_F),
+            GeometryUtils::getAngleDiff(0.0f, M_PI_F));
+    EXPECT_ANGLE_DIFF_EQ(ROUND_FLOAT_10000(M_PI_F / 6.0f),
+            GeometryUtils::getAngleDiff(M_PI_F / 3.0f, M_PI_F / 2.0f));
+    EXPECT_ANGLE_DIFF_EQ(ROUND_FLOAT_10000(M_PI_F / 2.0f),
+            GeometryUtils::getAngleDiff(0.0f, M_PI_F * 1.5f));
+    EXPECT_ANGLE_DIFF_EQ(0.0f, GeometryUtils::getAngleDiff(0.0f, M_PI_F * 1024.0f));
+    EXPECT_ANGLE_DIFF_EQ(0.0f, GeometryUtils::getAngleDiff(-M_PI_F, M_PI_F));
+}
+
+TEST(GeometryUtilsTest, testGetDistanceInt) {
+    EXPECT_EQ(0, GeometryUtils::getDistanceInt(0, 0, 0, 0));
+    EXPECT_EQ(0, GeometryUtils::getAngle(100, -10, 100, -10));
+
+    EXPECT_EQ(5, GeometryUtils::getDistanceInt(0, 0, 5, 0));
+    EXPECT_EQ(5, GeometryUtils::getDistanceInt(0, 0, 3, 4));
+    EXPECT_EQ(5, GeometryUtils::getDistanceInt(0, -4, 3, 0));
+    EXPECT_EQ(5, GeometryUtils::getDistanceInt(0, 0, -3, -4));
+    EXPECT_EQ(500, GeometryUtils::getDistanceInt(0, 0, 300, -400));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
deleted file mode 100644
index 6eef204..0000000
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content_test.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.h"
-
-#include <gtest/gtest.h>
-
-#include "utils/int_array_view.h"
-
-namespace latinime {
-namespace {
-
-TEST(LanguageModelDictContentTest, TestUnigramProbability) {
-    LanguageModelDictContent LanguageModelDictContent(false /* useHistoricalInfo */);
-
-    const int flag = 0xFF;
-    const int probability = 10;
-    const int wordId = 100;
-    const ProbabilityEntry probabilityEntry(flag, probability);
-    LanguageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
-    const ProbabilityEntry entry =
-            LanguageModelDictContent.getProbabilityEntry(wordId);
-    EXPECT_EQ(flag, entry.getFlags());
-    EXPECT_EQ(probability, entry.getProbability());
-}
-
-TEST(LanguageModelDictContentTest, TestUnigramProbabilityWithHistoricalInfo) {
-    LanguageModelDictContent LanguageModelDictContent(true /* useHistoricalInfo */);
-
-    const int flag = 0xF0;
-    const int timestamp = 0x3FFFFFFF;
-    const int level = 3;
-    const int count = 10;
-    const int wordId = 100;
-    const HistoricalInfo historicalInfo(timestamp, level, count);
-    const ProbabilityEntry probabilityEntry(flag, NOT_A_PROBABILITY, &historicalInfo);
-    LanguageModelDictContent.setProbabilityEntry(wordId, &probabilityEntry);
-    const ProbabilityEntry entry = LanguageModelDictContent.getProbabilityEntry(wordId);
-    EXPECT_EQ(flag, entry.getFlags());
-    EXPECT_EQ(timestamp, entry.getHistoricalInfo()->getTimeStamp());
-    EXPECT_EQ(level, entry.getHistoricalInfo()->getLevel());
-    EXPECT_EQ(count, entry.getHistoricalInfo()->getCount());
-}
-
-}  // namespace
-}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp
deleted file mode 100644
index db94550..0000000
--- a/native/jni/tests/suggest/policyimpl/dictionary/structure/v4/content/probability_entry_test.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "suggest/policyimpl/dictionary/structure/v4/content/probability_entry.h"
-
-#include <gtest/gtest.h>
-
-#include "defines.h"
-
-namespace latinime {
-namespace {
-
-TEST(ProbabilityEntryTest, TestEncodeDecode) {
-    const int flag = 0xFF;
-    const int probability = 10;
-
-    const ProbabilityEntry entry(flag, probability);
-    const uint64_t encodedEntry = entry.encode(false /* hasHistoricalInfo */);
-    const ProbabilityEntry decodedEntry =
-            ProbabilityEntry::decode(encodedEntry, false /* hasHistoricalInfo */);
-    EXPECT_EQ(0xFF0Aull, encodedEntry);
-    EXPECT_EQ(flag, decodedEntry.getFlags());
-    EXPECT_EQ(probability, decodedEntry.getProbability());
-}
-
-TEST(ProbabilityEntryTest, TestEncodeDecodeWithHistoricalInfo) {
-    const int flag = 0xF0;
-    const int timestamp = 0x3FFFFFFF;
-    const int level = 3;
-    const int count = 10;
-
-    const HistoricalInfo historicalInfo(timestamp, level, count);
-    const ProbabilityEntry entry(flag, NOT_A_PROBABILITY, &historicalInfo);
-
-    const uint64_t encodedEntry = entry.encode(true /* hasHistoricalInfo */);
-    EXPECT_EQ(0xF03FFFFFFF030Aull, encodedEntry);
-    const ProbabilityEntry decodedEntry =
-            ProbabilityEntry::decode(encodedEntry, true /* hasHistoricalInfo */);
-
-    EXPECT_EQ(flag, decodedEntry.getFlags());
-    EXPECT_EQ(timestamp, decodedEntry.getHistoricalInfo()->getTimeStamp());
-    EXPECT_EQ(level, decodedEntry.getHistoricalInfo()->getLevel());
-    EXPECT_EQ(count, decodedEntry.getHistoricalInfo()->getCount());
-}
-
-}  // namespace
-}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp
deleted file mode 100644
index fa6c6d7..0000000
--- a/native/jni/tests/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer_test.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h"
-
-#include <gtest/gtest.h>
-
-namespace latinime {
-namespace {
-
-const int DEFAULT_MAX_BUFFER_SIZE = 1024;
-
-TEST(BufferWithExtendablebufferTest, TestWriteAndRead) {
-    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
-    int pos = 0;
-    // 1 byte
-    const uint32_t data_1 = 0xFF;
-    EXPECT_TRUE(buffer.writeUint(data_1, 1 /* size */, pos));
-    EXPECT_EQ(data_1, buffer.readUint(1, pos));
-    pos += 1;
-    // 2 byte
-    const uint32_t data_2 = 0xFFFF;
-    EXPECT_TRUE(buffer.writeUint(data_2, 2 /* size */, pos));
-    EXPECT_EQ(data_2, buffer.readUint(2, pos));
-    pos += 2;
-    // 3 byte
-    const uint32_t data_3 = 0xFFFFFF;
-    EXPECT_TRUE(buffer.writeUint(data_3, 3 /* size */, pos));
-    EXPECT_EQ(data_3, buffer.readUint(3, pos));
-    pos += 3;
-    // 4 byte
-    const uint32_t data_4 = 0xFFFFFFFF;
-    EXPECT_TRUE(buffer.writeUint(data_4, 4 /* size */, pos));
-    EXPECT_EQ(data_4, buffer.readUint(4, pos));
-}
-
-TEST(BufferWithExtendablebufferTest, TestExtend) {
-    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
-    EXPECT_EQ(0, buffer.getTailPosition());
-    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
-    EXPECT_EQ(4, buffer.getTailPosition());
-    EXPECT_TRUE(buffer.extend(8 /* size */));
-    EXPECT_EQ(12, buffer.getTailPosition());
-    EXPECT_TRUE(buffer.writeUint(0xFFFF /* data */, 4 /* size */, 8 /* pos */));
-    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
-}
-
-TEST(BufferWithExtendablebufferTest, TestCopy) {
-    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
-    EXPECT_TRUE(buffer.writeUint(0xFF /* data */, 4 /* size */, 0 /* pos */));
-    EXPECT_TRUE(buffer.writeUint(0xFFFF /* data */, 4 /* size */, 4 /* pos */));
-    BufferWithExtendableBuffer targetBuffer(DEFAULT_MAX_BUFFER_SIZE);
-    EXPECT_TRUE(targetBuffer.copy(&buffer));
-    EXPECT_EQ(0xFFu, targetBuffer.readUint(4 /* size */, 0 /* pos */));
-    EXPECT_EQ(0xFFFFu, targetBuffer.readUint(4 /* size */, 4 /* pos */));
-}
-
-TEST(BufferWithExtendablebufferTest, TestSizeLimit) {
-    BufferWithExtendableBuffer emptyBuffer(0 /* maxAdditionalBufferSize */);
-    EXPECT_FALSE(emptyBuffer.writeUint(0 /* data */, 1 /* size */, 0 /* pos */));
-    EXPECT_FALSE(emptyBuffer.extend(1 /* size */));
-
-    BufferWithExtendableBuffer smallBuffer(4 /* maxAdditionalBufferSize */);
-    EXPECT_TRUE(smallBuffer.writeUint(0 /* data */, 4 /* size */, 0 /* pos */));
-    EXPECT_FALSE(smallBuffer.writeUint(0 /* data */, 1 /* size */, 4 /* pos */));
-
-    EXPECT_TRUE(smallBuffer.copy(&emptyBuffer));
-    EXPECT_FALSE(emptyBuffer.copy(&smallBuffer));
-
-    BufferWithExtendableBuffer buffer(DEFAULT_MAX_BUFFER_SIZE);
-    EXPECT_FALSE(buffer.isNearSizeLimit());
-    int pos = 0;
-    while (!buffer.isNearSizeLimit()) {
-        EXPECT_TRUE(buffer.writeUintAndAdvancePosition(0 /* data */, 4 /* size */, &pos));
-    }
-    EXPECT_GT(pos, 0);
-    EXPECT_LE(pos, DEFAULT_MAX_BUFFER_SIZE);
-}
-
-}  // namespace
-}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp b/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp
deleted file mode 100644
index df778b6..0000000
--- a/native/jni/tests/suggest/policyimpl/dictionary/utils/trie_map_test.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "suggest/policyimpl/dictionary/utils/trie_map.h"
-
-#include <gtest/gtest.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <functional>
-#include <map>
-#include <random>
-#include <unordered_map>
-
-namespace latinime {
-namespace {
-
-TEST(TrieMapTest, TestSetAndGet) {
-    TrieMap trieMap;
-    trieMap.putRoot(10, 10);
-    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
-    trieMap.putRoot(0x10A, 10);
-    EXPECT_EQ(10ull, trieMap.getRoot(10).mValue);
-    EXPECT_EQ(10ull, trieMap.getRoot(0x10A).mValue);
-    trieMap.putRoot(10, 1000);
-    EXPECT_EQ(1000ull, trieMap.getRoot(10).mValue);
-    trieMap.putRoot(11, 1000);
-    EXPECT_EQ(1000ull, trieMap.getRoot(11).mValue);
-    const int next = trieMap.getNextLevelBitmapEntryIndex(10);
-    trieMap.put(9, 9, next);
-    EXPECT_EQ(9ull, trieMap.get(9, next).mValue);
-    EXPECT_FALSE(trieMap.get(11, next).mIsValid);
-    trieMap.putRoot(0, 0xFFFFFFFFFull);
-    EXPECT_EQ(0xFFFFFFFFFull, trieMap.getRoot(0).mValue);
-}
-
-TEST(TrieMapTest, TestSetAndGetLarge) {
-    static const int ELEMENT_COUNT = 200000;
-    TrieMap trieMap;
-    for (int i = 0; i < ELEMENT_COUNT; ++i) {
-        EXPECT_TRUE(trieMap.putRoot(i, i));
-    }
-    for (int i = 0; i < ELEMENT_COUNT; ++i) {
-        EXPECT_EQ(static_cast<uint64_t>(i), trieMap.getRoot(i).mValue);
-    }
-}
-
-TEST(TrieMapTest, TestRandSetAndGetLarge) {
-    static const int ELEMENT_COUNT = 100000;
-    TrieMap trieMap;
-    std::unordered_map<int, uint64_t> testKeyValuePairs;
-
-    // Use the uniform integer distribution [S_INT_MIN, S_INT_MAX].
-    std::uniform_int_distribution<int> keyDistribution(S_INT_MIN, S_INT_MAX);
-    auto keyRandomNumberGenerator = std::bind(keyDistribution, std::mt19937());
-
-    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
-    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
-    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
-
-    for (int i = 0; i < ELEMENT_COUNT; ++i) {
-        const int key = keyRandomNumberGenerator();
-        const uint64_t value = valueRandomNumberGenerator();
-        EXPECT_TRUE(trieMap.putRoot(key, value)) << key << " " << value;
-        testKeyValuePairs[key] = value;
-    }
-    for (const auto &v : testKeyValuePairs) {
-        EXPECT_EQ(v.second, trieMap.getRoot(v.first).mValue);
-    }
-}
-
-TEST(TrieMapTest, TestMultiLevel) {
-    static const int FIRST_LEVEL_ENTRY_COUNT = 10000;
-    static const int SECOND_LEVEL_ENTRY_COUNT = 20000;
-    static const int THIRD_LEVEL_ENTRY_COUNT = 40000;
-
-    TrieMap trieMap;
-    std::vector<int> firstLevelKeys;
-    std::map<int, uint64_t> firstLevelEntries;
-    std::vector<std::pair<int, int>> secondLevelKeys;
-    std::map<int, std::map<int, uint64_t>> twoLevelMap;
-    std::map<int, std::map<int, std::map<int, uint64_t>>> threeLevelMap;
-
-    // Use the uniform integer distribution [0, S_INT_MAX].
-    std::uniform_int_distribution<int> distribution(0, S_INT_MAX);
-    auto keyRandomNumberGenerator = std::bind(distribution, std::mt19937());
-    auto randomNumberGeneratorForKeySelection = std::bind(distribution, std::mt19937());
-
-    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
-    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
-    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
-
-    for (int i = 0; i < FIRST_LEVEL_ENTRY_COUNT; ++i) {
-        const int key = keyRandomNumberGenerator();
-        const uint64_t value = valueRandomNumberGenerator();
-        EXPECT_TRUE(trieMap.putRoot(key, value));
-        firstLevelKeys.push_back(key);
-        firstLevelEntries[key] = value;
-    }
-
-    for (int i = 0; i < SECOND_LEVEL_ENTRY_COUNT; ++i) {
-        const int key = keyRandomNumberGenerator();
-        const uint64_t value = valueRandomNumberGenerator();
-        const int firstLevelKey =
-                firstLevelKeys[randomNumberGeneratorForKeySelection() % FIRST_LEVEL_ENTRY_COUNT];
-        const int nextLevelBitmapEntryIndex = trieMap.getNextLevelBitmapEntryIndex(firstLevelKey);
-        EXPECT_NE(TrieMap::INVALID_INDEX, nextLevelBitmapEntryIndex);
-        EXPECT_TRUE(trieMap.put(key, value, nextLevelBitmapEntryIndex));
-        secondLevelKeys.push_back(std::make_pair(firstLevelKey, key));
-        twoLevelMap[firstLevelKey][key] = value;
-    }
-
-    for (int i = 0; i < THIRD_LEVEL_ENTRY_COUNT; ++i) {
-        const int key = keyRandomNumberGenerator();
-        const uint64_t value = valueRandomNumberGenerator();
-        const std::pair<int, int> secondLevelKey =
-                secondLevelKeys[randomNumberGeneratorForKeySelection() % SECOND_LEVEL_ENTRY_COUNT];
-        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(secondLevelKey.first);
-        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
-        const int thirdLevel = trieMap.getNextLevelBitmapEntryIndex(
-                secondLevelKey.second, secondLevel);
-        EXPECT_NE(TrieMap::INVALID_INDEX, thirdLevel);
-        EXPECT_TRUE(trieMap.put(key, value, thirdLevel));
-        threeLevelMap[secondLevelKey.first][secondLevelKey.second][key] = value;
-    }
-
-    for (const auto &firstLevelEntry : firstLevelEntries) {
-        EXPECT_EQ(firstLevelEntry.second, trieMap.getRoot(firstLevelEntry.first).mValue);
-    }
-
-    for (const auto &firstLevelEntry : twoLevelMap) {
-        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(firstLevelEntry.first);
-        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
-        for (const auto &secondLevelEntry : firstLevelEntry.second) {
-            EXPECT_EQ(secondLevelEntry.second,
-                    trieMap.get(secondLevelEntry.first, secondLevel).mValue);
-        }
-    }
-
-    for (const auto &firstLevelEntry : threeLevelMap) {
-        const int secondLevel = trieMap.getNextLevelBitmapEntryIndex(firstLevelEntry.first);
-        EXPECT_NE(TrieMap::INVALID_INDEX, secondLevel);
-        for (const auto &secondLevelEntry : firstLevelEntry.second) {
-            const int thirdLevel =
-                    trieMap.getNextLevelBitmapEntryIndex(secondLevelEntry.first, secondLevel);
-            EXPECT_NE(TrieMap::INVALID_INDEX, thirdLevel);
-            for (const auto &thirdLevelEntry : secondLevelEntry.second) {
-                EXPECT_EQ(thirdLevelEntry.second,
-                        trieMap.get(thirdLevelEntry.first, thirdLevel).mValue);
-            }
-        }
-    }
-
-    // Iteration
-    for (const auto &firstLevelEntry : trieMap.getEntriesInRootLevel()) {
-        EXPECT_EQ(trieMap.getRoot(firstLevelEntry.key()).mValue, firstLevelEntry.value());
-        EXPECT_EQ(firstLevelEntries[firstLevelEntry.key()], firstLevelEntry.value());
-        firstLevelEntries.erase(firstLevelEntry.key());
-        for (const auto &secondLevelEntry : firstLevelEntry.getEntriesInNextLevel()) {
-            EXPECT_EQ(twoLevelMap[firstLevelEntry.key()][secondLevelEntry.key()],
-                    secondLevelEntry.value());
-            twoLevelMap[firstLevelEntry.key()].erase(secondLevelEntry.key());
-            for (const auto &thirdLevelEntry : secondLevelEntry.getEntriesInNextLevel()) {
-                EXPECT_EQ(threeLevelMap[firstLevelEntry.key()][secondLevelEntry.key()]
-                        [thirdLevelEntry.key()], thirdLevelEntry.value());
-                threeLevelMap[firstLevelEntry.key()][secondLevelEntry.key()].erase(
-                        thirdLevelEntry.key());
-            }
-        }
-    }
-
-    // Ensure all entries have been traversed.
-    EXPECT_TRUE(firstLevelEntries.empty());
-    for (const auto &secondLevelEntry : twoLevelMap) {
-        EXPECT_TRUE(secondLevelEntry.second.empty());
-    }
-    for (const auto &secondLevelEntry : threeLevelMap) {
-        for (const auto &thirdLevelEntry : secondLevelEntry.second) {
-            EXPECT_TRUE(thirdLevelEntry.second.empty());
-        }
-    }
-}
-
-TEST(TrieMapTest, TestIteration) {
-    static const int ELEMENT_COUNT = 200000;
-    TrieMap trieMap;
-    std::unordered_map<int, uint64_t> testKeyValuePairs;
-
-    // Use the uniform integer distribution [S_INT_MIN, S_INT_MAX].
-    std::uniform_int_distribution<int> keyDistribution(S_INT_MIN, S_INT_MAX);
-    auto keyRandomNumberGenerator = std::bind(keyDistribution, std::mt19937());
-
-    // Use the uniform distribution [0, TrieMap::MAX_VALUE].
-    std::uniform_int_distribution<uint64_t> valueDistribution(0, TrieMap::MAX_VALUE);
-    auto valueRandomNumberGenerator = std::bind(valueDistribution, std::mt19937());
-    for (int i = 0; i < ELEMENT_COUNT; ++i) {
-        const int key = keyRandomNumberGenerator();
-        const uint64_t value = valueRandomNumberGenerator();
-        EXPECT_TRUE(trieMap.putRoot(key, value));
-        testKeyValuePairs[key] = value;
-    }
-    for (const auto &entry : trieMap.getEntriesInRootLevel()) {
-        EXPECT_EQ(trieMap.getRoot(entry.key()).mValue, entry.value());
-        EXPECT_EQ(testKeyValuePairs[entry.key()], entry.value());
-        testKeyValuePairs.erase(entry.key());
-    }
-    EXPECT_TRUE(testKeyValuePairs.empty());
-}
-
-}  // namespace
-}  // namespace latinime
diff --git a/native/jni/tests/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy_test.cpp b/native/jni/tests/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy_test.cpp
new file mode 100644
index 0000000..d134179
--- /dev/null
+++ b/native/jni/tests/suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy_test.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "suggest/policyimpl/utils/damerau_levenshtein_edit_distance_policy.h"
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include "suggest/policyimpl/utils/edit_distance.h"
+#include "utils/int_array_view.h"
+
+namespace latinime {
+namespace {
+
+TEST(DamerauLevenshteinEditDistancePolicyTest, TestConstructPolicy) {
+    const std::vector<int> codePoints0 = { 0x20, 0x40, 0x60 };
+    const std::vector<int> codePoints1 = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 };
+    DamerauLevenshteinEditDistancePolicy policy(codePoints0.data(), codePoints0.size(),
+            codePoints1.data(), codePoints1.size());
+
+    EXPECT_EQ(static_cast<int>(codePoints0.size()), policy.getString0Length());
+    EXPECT_EQ(static_cast<int>(codePoints1.size()), policy.getString1Length());
+}
+
+float getEditDistance(const std::vector<int> &codePoints0, const std::vector<int> &codePoints1) {
+    DamerauLevenshteinEditDistancePolicy policy(codePoints0.data(), codePoints0.size(),
+            codePoints1.data(), codePoints1.size());
+    return EditDistance::getEditDistance(&policy);
+}
+
+TEST(DamerauLevenshteinEditDistancePolicyTest, TestEditDistance) {
+    EXPECT_FLOAT_EQ(0.0f, getEditDistance({}, {}));
+    EXPECT_FLOAT_EQ(0.0f, getEditDistance({ 1 }, { 1 }));
+    EXPECT_FLOAT_EQ(0.0f, getEditDistance({ 1, 2, 3 }, { 1, 2, 3 }));
+
+    EXPECT_FLOAT_EQ(1.0f, getEditDistance({ 1 }, { }));
+    EXPECT_FLOAT_EQ(1.0f, getEditDistance({}, { 100 }));
+    EXPECT_FLOAT_EQ(5.0f, getEditDistance({}, { 1, 2, 3, 4, 5 }));
+
+    EXPECT_FLOAT_EQ(1.0f, getEditDistance({ 0 }, { 100 }));
+    EXPECT_FLOAT_EQ(5.0f, getEditDistance({ 1, 2, 3, 4, 5 }, { 11, 12, 13, 14, 15 }));
+
+    EXPECT_FLOAT_EQ(1.0f, getEditDistance({ 1 }, { 1, 2 }));
+    EXPECT_FLOAT_EQ(2.0f, getEditDistance({ 1, 2 }, { 0, 1, 2, 3 }));
+    EXPECT_FLOAT_EQ(2.0f, getEditDistance({ 0, 1, 2, 3 }, { 1, 2 }));
+
+    EXPECT_FLOAT_EQ(1.0f, getEditDistance({ 1, 2 }, { 2, 1 }));
+    EXPECT_FLOAT_EQ(2.0f, getEditDistance({ 1, 2, 3, 4 }, { 2, 1, 4, 3 }));
+}
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/utils/char_utils_test.cpp b/native/jni/tests/utils/char_utils_test.cpp
new file mode 100644
index 0000000..01d5340
--- /dev/null
+++ b/native/jni/tests/utils/char_utils_test.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/char_utils.h"
+
+#include <gtest/gtest.h>
+
+#include "defines.h"
+
+namespace latinime {
+namespace {
+
+TEST(CharUtilsTest, TestIsAsciiUpper) {
+    EXPECT_TRUE(CharUtils::isAsciiUpper('A'));
+    EXPECT_TRUE(CharUtils::isAsciiUpper('Z'));
+    EXPECT_FALSE(CharUtils::isAsciiUpper('a'));
+    EXPECT_FALSE(CharUtils::isAsciiUpper('z'));
+    EXPECT_FALSE(CharUtils::isAsciiUpper('@'));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(' '));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x00C0 /* LATIN CAPITAL LETTER A WITH GRAVE */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x0410 /* CYRILLIC CAPITAL LETTER A */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x0430 /* CYRILLIC SMALL LETTER A */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x3042 /* HIRAGANA LETTER A */));
+    EXPECT_FALSE(CharUtils::isAsciiUpper(0x1F36A /* COOKIE */));
+}
+
+TEST(CharUtilsTest, TestToLowerCase) {
+    EXPECT_EQ('a', CharUtils::toLowerCase('A'));
+    EXPECT_EQ('z', CharUtils::toLowerCase('Z'));
+    EXPECT_EQ('a', CharUtils::toLowerCase('a'));
+    EXPECT_EQ('z', CharUtils::toLowerCase('z'));
+    EXPECT_EQ('@', CharUtils::toLowerCase('@'));
+    EXPECT_EQ(' ', CharUtils::toLowerCase(' '));
+    EXPECT_EQ(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
+            CharUtils::toLowerCase(0x00C0 /* LATIN CAPITAL LETTER A WITH GRAVE */));
+    EXPECT_EQ(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
+            CharUtils::toLowerCase(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */));
+    EXPECT_EQ(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */,
+            CharUtils::toLowerCase(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */));
+    EXPECT_EQ(0x0430 /* CYRILLIC SMALL LETTER A */,
+            CharUtils::toLowerCase(0x0410 /* CYRILLIC CAPITAL LETTER A */));
+    EXPECT_EQ(0x0430 /* CYRILLIC SMALL LETTER A */,
+            CharUtils::toLowerCase(0x0430 /* CYRILLIC SMALL LETTER A */));
+    EXPECT_EQ(0x3042 /* HIRAGANA LETTER A */,
+            CharUtils::toLowerCase(0x3042 /* HIRAGANA LETTER A */));
+    EXPECT_EQ(0x1F36A /* COOKIE */, CharUtils::toLowerCase(0x1F36A /* COOKIE */));
+}
+
+TEST(CharUtilsTest, TestToBaseLowerCase) {
+    EXPECT_EQ('a', CharUtils::toBaseLowerCase('A'));
+    EXPECT_EQ('z', CharUtils::toBaseLowerCase('Z'));
+    EXPECT_EQ('a', CharUtils::toBaseLowerCase('a'));
+    EXPECT_EQ('z', CharUtils::toBaseLowerCase('z'));
+    EXPECT_EQ('@', CharUtils::toBaseLowerCase('@'));
+    EXPECT_EQ(' ', CharUtils::toBaseLowerCase(' '));
+    EXPECT_EQ('a', CharUtils::toBaseLowerCase(0x00C0 /* LATIN CAPITAL LETTER A WITH GRAVE */));
+    EXPECT_EQ('a', CharUtils::toBaseLowerCase(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */));
+    EXPECT_EQ(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */,
+            CharUtils::toBaseLowerCase(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */));
+    EXPECT_EQ(0x0430 /* CYRILLIC SMALL LETTER A */,
+            CharUtils::toBaseLowerCase(0x0410 /* CYRILLIC CAPITAL LETTER A */));
+    EXPECT_EQ(0x0430 /* CYRILLIC SMALL LETTER A */,
+            CharUtils::toBaseLowerCase(0x0430 /* CYRILLIC SMALL LETTER A */));
+    EXPECT_EQ(0x3042 /* HIRAGANA LETTER A */,
+            CharUtils::toBaseLowerCase(0x3042 /* HIRAGANA LETTER A */));
+    EXPECT_EQ(0x1F36A /* COOKIE */, CharUtils::toBaseLowerCase(0x1F36A /* COOKIE */));
+}
+
+TEST(CharUtilsTest, TestToBaseCodePoint) {
+    EXPECT_EQ('A', CharUtils::toBaseCodePoint('A'));
+    EXPECT_EQ('Z', CharUtils::toBaseCodePoint('Z'));
+    EXPECT_EQ('a', CharUtils::toBaseCodePoint('a'));
+    EXPECT_EQ('z', CharUtils::toBaseCodePoint('z'));
+    EXPECT_EQ('@', CharUtils::toBaseCodePoint('@'));
+    EXPECT_EQ(' ', CharUtils::toBaseCodePoint(' '));
+    EXPECT_EQ('A', CharUtils::toBaseCodePoint(0x00C0 /* LATIN CAPITAL LETTER A WITH GRAVE */));
+    EXPECT_EQ('a', CharUtils::toBaseCodePoint(0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */));
+    EXPECT_EQ(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */,
+            CharUtils::toBaseLowerCase(0x03C2 /* GREEK SMALL LETTER FINAL SIGMA */));
+    EXPECT_EQ(0x0410 /* CYRILLIC CAPITAL LETTER A */,
+            CharUtils::toBaseCodePoint(0x0410 /* CYRILLIC CAPITAL LETTER A */));
+    EXPECT_EQ(0x0430 /* CYRILLIC SMALL LETTER A */,
+            CharUtils::toBaseCodePoint(0x0430 /* CYRILLIC SMALL LETTER A */));
+    EXPECT_EQ(0x3042 /* HIRAGANA LETTER A */,
+            CharUtils::toBaseCodePoint(0x3042 /* HIRAGANA LETTER A */));
+    EXPECT_EQ(0x1F36A /* COOKIE */, CharUtils::toBaseCodePoint(0x1F36A /* COOKIE */));
+}
+
+TEST(CharUtilsTest, TestIsIntentionalOmissionCodePoint) {
+    EXPECT_TRUE(CharUtils::isIntentionalOmissionCodePoint('\''));
+    EXPECT_TRUE(CharUtils::isIntentionalOmissionCodePoint('-'));
+    EXPECT_FALSE(CharUtils::isIntentionalOmissionCodePoint('a'));
+    EXPECT_FALSE(CharUtils::isIntentionalOmissionCodePoint('?'));
+    EXPECT_FALSE(CharUtils::isIntentionalOmissionCodePoint('/'));
+}
+
+TEST(CharUtilsTest, TestIsInUnicodeSpace) {
+    EXPECT_FALSE(CharUtils::isInUnicodeSpace(NOT_A_CODE_POINT));
+    EXPECT_FALSE(CharUtils::isInUnicodeSpace(CODE_POINT_BEGINNING_OF_SENTENCE));
+    EXPECT_TRUE(CharUtils::isInUnicodeSpace('a'));
+    EXPECT_TRUE(CharUtils::isInUnicodeSpace(0x0410 /* CYRILLIC CAPITAL LETTER A */));
+    EXPECT_TRUE(CharUtils::isInUnicodeSpace(0x3042 /* HIRAGANA LETTER A */));
+    EXPECT_TRUE(CharUtils::isInUnicodeSpace(0x1F36A /* COOKIE */));
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/native/jni/tests/utils/int_array_view_test.cpp b/native/jni/tests/utils/int_array_view_test.cpp
index bd843ab..2fce633 100644
--- a/native/jni/tests/utils/int_array_view_test.cpp
+++ b/native/jni/tests/utils/int_array_view_test.cpp
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 
+#include <array>
 #include <vector>
 
 namespace latinime {
@@ -45,17 +46,157 @@
 
 TEST(IntArrayViewTest, TestConstructFromArray) {
     const size_t ARRAY_SIZE = 100;
-    int intArray[ARRAY_SIZE];
-    const auto intArrayView = IntArrayView::fromFixedSizeArray(intArray);
+    std::array<int, ARRAY_SIZE> intArray;
+    const auto intArrayView = IntArrayView::fromArray(intArray);
     EXPECT_EQ(ARRAY_SIZE, intArrayView.size());
 }
 
 TEST(IntArrayViewTest, TestConstructFromObject) {
     const int object = 10;
-    const auto intArrayView = IntArrayView::fromObject(&object);
-    EXPECT_EQ(1, intArrayView.size());
+    const auto intArrayView = IntArrayView::singleElementView(&object);
+    EXPECT_EQ(1u, intArrayView.size());
     EXPECT_EQ(object, intArrayView[0]);
 }
 
+TEST(IntArrayViewTest, TestContains) {
+    EXPECT_FALSE(IntArrayView().contains(0));
+    EXPECT_FALSE(IntArrayView().contains(1));
+
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+    EXPECT_TRUE(intArrayView.contains(0));
+    EXPECT_TRUE(intArrayView.contains(3));
+    EXPECT_TRUE(intArrayView.contains(-2));
+    EXPECT_FALSE(intArrayView.contains(-3));
+    EXPECT_FALSE(intArrayView.limit(0).contains(3));
+}
+
+TEST(IntArrayViewTest, TestLimit) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+
+    EXPECT_TRUE(intArrayView.limit(0).empty());
+    EXPECT_EQ(intArrayView.size(), intArrayView.limit(intArrayView.size()).size());
+    EXPECT_EQ(intArrayView.size(), intArrayView.limit(1000).size());
+
+    IntArrayView subView = intArrayView.limit(4);
+    EXPECT_EQ(4u, subView.size());
+    for (size_t i = 0; i < subView.size(); ++i) {
+        EXPECT_EQ(intVector[i], subView[i]);
+    }
+}
+
+TEST(IntArrayViewTest, TestSkip) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+
+    EXPECT_TRUE(intArrayView.skip(intVector.size()).empty());
+    EXPECT_TRUE(intArrayView.skip(intVector.size() + 1).empty());
+    EXPECT_EQ(intArrayView.size(), intArrayView.skip(0).size());
+    EXPECT_EQ(intArrayView.size(), intArrayView.limit(1000).size());
+
+    static const size_t SKIP_COUNT = 2;
+    IntArrayView subView = intArrayView.skip(SKIP_COUNT);
+    EXPECT_EQ(intVector.size() - SKIP_COUNT, subView.size());
+    for (size_t i = 0; i < subView.size(); ++i) {
+        EXPECT_EQ(intVector[i + SKIP_COUNT], subView[i]);
+    }
+}
+
+TEST(IntArrayViewTest, TestCopyToArray) {
+    // "{{" to suppress warning.
+    std::array<int, 7> buffer = {{10, 20, 30, 40, 50, 60, 70}};
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+    intArrayView.limit(0).copyToArray(&buffer, 0);
+    EXPECT_EQ(10, buffer[0]);
+    EXPECT_EQ(20, buffer[1]);
+    intArrayView.limit(1).copyToArray(&buffer, 0);
+    EXPECT_EQ(intVector[0], buffer[0]);
+    EXPECT_EQ(20, buffer[1]);
+    intArrayView.limit(1).copyToArray(&buffer, 1);
+    EXPECT_EQ(intVector[0], buffer[0]);
+    EXPECT_EQ(intVector[0], buffer[1]);
+    intArrayView.copyToArray(&buffer, 0);
+    for (size_t i = 0; i < intArrayView.size(); ++i) {
+        EXPECT_EQ(intVector[i], buffer[i]);
+    }
+    EXPECT_EQ(70, buffer[6]);
+}
+
+TEST(IntArrayViewTest, TestFirstOrDefault) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+
+    EXPECT_EQ(3, intArrayView.firstOrDefault(10));
+    EXPECT_EQ(10, intArrayView.limit(0).firstOrDefault(10));
+    EXPECT_EQ(-10, intArrayView.limit(0).firstOrDefault(-10));
+    EXPECT_EQ(10, intArrayView.skip(6).firstOrDefault(10));
+}
+
+TEST(IntArrayViewTest, TestLastOrDefault) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+
+    EXPECT_EQ(-2, intArrayView.lastOrDefault(10));
+    EXPECT_EQ(10, intArrayView.limit(0).lastOrDefault(10));
+    EXPECT_EQ(-10, intArrayView.limit(0).lastOrDefault(-10));
+    EXPECT_EQ(10, intArrayView.skip(6).lastOrDefault(10));
+}
+
+TEST(IntArrayViewTest, TestToVector) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+    EXPECT_EQ(intVector, intArrayView.toVector());
+    EXPECT_EQ(std::vector<int>(), CodePointArrayView().toVector());
+}
+
+TEST(IntArrayViewTest, TestSplit) {
+    EXPECT_TRUE(IntArrayView().split(0, 0).empty());
+    {
+        const auto intArrayViews = IntArrayView().split(0, 1);
+        EXPECT_EQ(1u, intArrayViews.size());
+        EXPECT_TRUE(intArrayViews[0].empty());
+    }
+    {
+        const auto intArrayViews = IntArrayView().split(0, 100);
+        EXPECT_EQ(1u, intArrayViews.size());
+        EXPECT_TRUE(intArrayViews[0].empty());
+    }
+
+    const std::vector<int> intVector = {1, 2, 3, 3, 2, 3};
+    const IntArrayView intArrayView(intVector);
+    {
+        const auto intArrayViews = intArrayView.split(2);
+        EXPECT_EQ(3u, intArrayViews.size());
+        EXPECT_EQ(std::vector<int>({1}), intArrayViews[0].toVector());
+        EXPECT_EQ(std::vector<int>({3, 3}), intArrayViews[1].toVector());
+        EXPECT_EQ(std::vector<int>({3}), intArrayViews[2].toVector());
+    }
+    {
+        const auto intArrayViews = intArrayView.split(2, 2);
+        EXPECT_EQ(2u, intArrayViews.size());
+        EXPECT_EQ(std::vector<int>({1}), intArrayViews[0].toVector());
+        EXPECT_EQ(std::vector<int>({3, 3, 2, 3}), intArrayViews[1].toVector());
+    }
+    {
+        const auto intArrayViews = intArrayView.split(2, 1);
+        EXPECT_EQ(1u, intArrayViews.size());
+        EXPECT_EQ(intVector, intArrayViews[0].toVector());
+    }
+    {
+        const auto intArrayViews = intArrayView.split(2, 0);
+        EXPECT_EQ(0u, intArrayViews.size());
+    }
+    {
+        const auto intArrayViews = intArrayView.split(3);
+        EXPECT_EQ(4u, intArrayViews.size());
+        EXPECT_EQ(std::vector<int>({1, 2}), intArrayViews[0].toVector());
+        EXPECT_EQ(std::vector<int>(), intArrayViews[1].toVector());
+        EXPECT_EQ(std::vector<int>({2}), intArrayViews[2].toVector());
+        EXPECT_EQ(std::vector<int>(), intArrayViews[3].toVector());
+    }
+}
+
 }  // namespace
 }  // namespace latinime
diff --git a/native/jni/tests/utils/time_keeper_test.cpp b/native/jni/tests/utils/time_keeper_test.cpp
new file mode 100644
index 0000000..3f54b91
--- /dev/null
+++ b/native/jni/tests/utils/time_keeper_test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "utils/time_keeper.h"
+
+#include <gtest/gtest.h>
+
+namespace latinime {
+namespace {
+
+TEST(TimeKeeperTest, TestTestMode) {
+    TimeKeeper::setCurrentTime();
+    const int startTime = TimeKeeper::peekCurrentTime();
+    static const int TEST_CURRENT_TIME = 100;
+    TimeKeeper::startTestModeWithForceCurrentTime(TEST_CURRENT_TIME);
+    EXPECT_EQ(TEST_CURRENT_TIME, TimeKeeper::peekCurrentTime());
+    TimeKeeper::setCurrentTime();
+    EXPECT_EQ(TEST_CURRENT_TIME, TimeKeeper::peekCurrentTime());
+    TimeKeeper::stopTestMode();
+    TimeKeeper::setCurrentTime();
+    EXPECT_LE(startTime, TimeKeeper::peekCurrentTime());
+}
+
+}  // namespace
+}  // namespace latinime
diff --git a/tests/Android.mk b/tests/Android.mk
index 5baebbd..0b54491 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 # We only want this apk build for tests.
@@ -24,6 +24,8 @@
 # Do not compress test data file
 LOCAL_AAPT_FLAGS += -0 .txt
 
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target
+
 # Include all test java files.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 4ca846b..c7a9e13 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -17,16 +17,17 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.inputmethod.latin.tests">
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
+    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
 
     <uses-permission android:name="android.permission.READ_CONTACTS" />
 
-    <application>
+    <application android:label="@string/app_name"
+        android:icon="@drawable/ic_app">
         <uses-library android:name="android.test.runner" />
         <!-- meta-data android:name="com.android.contacts.iconset" android:resource="@xml/iconset" /-->
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.inputmethod.latin"
         android:label="LatinIME tests">
     </instrumentation>
diff --git a/tests/res/drawable-hdpi/ic_app.png b/tests/res/drawable-hdpi/ic_app.png
new file mode 100644
index 0000000..345c23d
--- /dev/null
+++ b/tests/res/drawable-hdpi/ic_app.png
Binary files differ
diff --git a/tests/res/values/donottranslate.xml b/tests/res/values/donottranslate.xml
index 263d0af..f269476 100644
--- a/tests/res/values/donottranslate.xml
+++ b/tests/res/values/donottranslate.xml
@@ -50,13 +50,15 @@
     <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string>
     <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string>
     <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string>
-    <string name="indirect_string">!text/multiple_chars</string>
-    <string name="indirect_string_with_literal">x,!text/multiple_chars,y</string>
-    <string name="indirect2_string">!text/indirect_string</string>
-    <string name="infinite_indirection">infinite,!text/infinite_indirection,loop</string>
-    <string name="upper_indirect_string">!TEXT/MULTIPLE_CHARS</string>
-    <string name="upper_indirect_string_with_literal">x,!TEXT/MULTIPLE_CHARS,y</string>
-    <string name="upper_indirect2_string">!TEXT/UPPER_INDIRECT_STRING</string>
-    <string name="upper_infinite_indirection">infinite,!TEXT/INFINITE_INDIRECTION,loop</string>
+    <string name="indirect_string">!string/multiple_chars</string>
+    <string name="indirect_string_with_literal">x,!string/multiple_chars,y</string>
+    <string name="indirect2_string">!string/indirect_string</string>
+    <string name="infinite_indirection">infinite,!string/infinite_indirection,loop</string>
+    <string name="upper_indirect_string">!STRING/MULTIPLE_CHARS</string>
+    <string name="upper_indirect_string_with_literal">x,!STRING/MULTIPLE_CHARS,y</string>
+    <string name="upper_indirect2_string">!STRING/UPPER_INDIRECT_STRING</string>
+    <string name="upper_infinite_indirection">infinite,!STRING/INFINITE_INDIRECTION,loop</string>
     <string name="keyspec_indirect_navigate_actions">!fixedColumnOrder!2,!text/keyspec_action_previous,!text/keyspec_action_next</string>
+    <string name="label_next_key">ActionNext</string>
+    <string name="label_previous_key">ActionPrevious</string>
 </resources>
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
new file mode 100644
index 0000000..5cc48b6
--- /dev/null
+++ b/tests/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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>
+     <string name="app_name" translatable="false">LatinIMETests</string>
+</resources>
diff --git a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
index 319302c..67e7646 100644
--- a/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
+++ b/tests/src/com/android/inputmethod/compat/LocaleSpanCompatUtilsTests.java
@@ -20,7 +20,6 @@
 import android.os.Build;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.StyleSpan;
@@ -72,141 +71,141 @@
             final SpannableString text = new SpannableString("0123456789");
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if only LocaleSpans are updated.
         {
             final SpannableString text = new SpannableString("0123456789");
             final StyleSpan styleSpan = new StyleSpan(Typeface.BOLD);
-            text.setSpan(styleSpan, 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(styleSpan, 0, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(2, text);
             assertSpanEquals(styleSpan, text, 0);
-            assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if two jointed spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if two overlapped spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if three overlapped spans are merged into one span.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 4,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 8, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if disjoint spans remain disjoint.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 3,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 5, 6,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 8, 9, Locale.JAPANESE);
             assertSpanCount(3, text);
-            assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 3, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 2, 8, 9, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing span flags are preserved during merge.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 4, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 5, Locale.JAPANESE,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing span flags are preserved even when partially overlapped (leading edge).
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 1, 5,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 3, 7, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
-                    Spannable.SPAN_INCLUSIVE_EXCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_EXCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing span flags are preserved even when partially overlapped (trailing edge).
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.JAPANESE), 3, 7,
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_INCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 5, Locale.JAPANESE);
             assertSpanCount(1, text);
             assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE,
-                    Spannable.SPAN_EXCLUSIVE_INCLUSIVE | Spannable.SPAN_INTERMEDIATE);
+                    Spanned.SPAN_EXCLUSIVE_INCLUSIVE | Spanned.SPAN_INTERMEDIATE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match.
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 5,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 1, 7, Locale.JAPANESE);
             assertSpanCount(1, text);
-            assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 1, 7, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 2)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 6, Locale.JAPANESE);
             assertSpanCount(3, text);
-            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 6, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 2, 5, 6, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 3)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 2, 5, Locale.JAPANESE);
             assertSpanCount(2, text);
-            assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 5, 7, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 2, 5, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
 
         // Test if existing locale span will be removed when the locale doesn't match. (case 3)
         {
             final SpannableString text = new SpannableString("0123456789");
             text.setSpan(LocaleSpanCompatUtils.newLocaleSpan(Locale.ENGLISH), 3, 7,
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             LocaleSpanCompatUtils.updateLocaleSpan(text, 5, 8, Locale.JAPANESE);
             assertSpanCount(2, text);
-            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-            assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 0, 3, 5, Locale.ENGLISH, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            assertLocaleSpan(text, 1, 5, 8, Locale.JAPANESE, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java b/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java
new file mode 100644
index 0000000..daf412c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2014 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.compat;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.SuggestionSpan;
+
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Locale;
+
+@SmallTest
+public class SuggestionSpanUtilsTest extends AndroidTestCase {
+
+    /**
+     * Helper method to create a dummy {@link SuggestedWordInfo}.
+     *
+     * @param kindAndFlags the kind and flags to be used to create {@link SuggestedWordInfo}.
+     * @param word the word to be used to create {@link SuggestedWordInfo}.
+     * @return a new instance of {@link SuggestedWordInfo}.
+     */
+    private static SuggestedWordInfo createWordInfo(final String word, final int kindAndFlags) {
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 1 /* score */, kindAndFlags,
+                null /* sourceDict */,
+                SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
+                SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
+    }
+
+    private static void assertNotSuggestionSpan(final String expectedText,
+            final CharSequence actualText) {
+        assertTrue(TextUtils.equals(expectedText, actualText));
+        if (!(actualText instanceof Spanned)) {
+            return;
+        }
+        final Spanned spanned = (Spanned)actualText;
+        final SuggestionSpan[] suggestionSpans = spanned.getSpans(0, spanned.length(),
+                SuggestionSpan.class);
+        assertEquals(0, suggestionSpans.length);
+    }
+
+    private static void assertSuggestionSpan(final String expectedText,
+            final int reuiredSuggestionSpanFlags, final int requiredSpanFlags,
+            final String[] expectedSuggestions,
+            final CharSequence actualText) {
+        assertTrue(TextUtils.equals(expectedText, actualText));
+        assertTrue(actualText instanceof Spanned);
+        final Spanned spanned = (Spanned)actualText;
+        final SuggestionSpan[] suggestionSpans = spanned.getSpans(0, spanned.length(),
+                SuggestionSpan.class);
+        assertEquals(1, suggestionSpans.length);
+        final SuggestionSpan suggestionSpan = suggestionSpans[0];
+        if (reuiredSuggestionSpanFlags != 0) {
+            assertTrue((suggestionSpan.getFlags() & reuiredSuggestionSpanFlags) != 0);
+        }
+        if (requiredSpanFlags != 0) {
+            assertTrue((spanned.getSpanFlags(suggestionSpan) & requiredSpanFlags) != 0);
+        }
+        if (expectedSuggestions != null) {
+            final String[] actualSuggestions = suggestionSpan.getSuggestions();
+            assertEquals(expectedSuggestions.length, actualSuggestions.length);
+            for (int i = 0; i < expectedSuggestions.length; ++i) {
+                assertEquals(expectedSuggestions[i], actualSuggestions[i]);
+            }
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+    public void testGetTextWithAutoCorrectionIndicatorUnderline() {
+        final String ORIGINAL_TEXT = "Hey!";
+        final CharSequence text = SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(
+                getContext(), ORIGINAL_TEXT);
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+            assertNotSuggestionSpan(ORIGINAL_TEXT, text);
+            return;
+        }
+
+        assertSuggestionSpan(ORIGINAL_TEXT,
+                SuggestionSpan.FLAG_AUTO_CORRECTION /* reuiredSuggestionSpanFlags */,
+                Spanned.SPAN_COMPOSING | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE /* requiredSpanFlags */,
+                new String[]{}, text);
+    }
+
+    public void testGetTextWithSuggestionSpan() {
+        final SuggestedWordInfo prediction1 =
+                createWordInfo("Quality", SuggestedWordInfo.KIND_PREDICTION);
+        final SuggestedWordInfo prediction2 =
+                createWordInfo("Speed", SuggestedWordInfo.KIND_PREDICTION);
+        final SuggestedWordInfo prediction3 =
+                createWordInfo("Price", SuggestedWordInfo.KIND_PREDICTION);
+
+        final SuggestedWordInfo typed =
+                createWordInfo("Hey", SuggestedWordInfo.KIND_TYPED);
+
+        final SuggestedWordInfo[] corrections =
+                new SuggestedWordInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE * 2];
+        for (int i = 0; i < corrections.length; ++i) {
+            corrections[i] = createWordInfo("correction" + i, SuggestedWordInfo.KIND_CORRECTION);
+        }
+
+        // SuggestionSpan will not be attached when {@link SuggestedWords#INPUT_STYLE_PREDICTION}
+        // is specified.
+        {
+            final SuggestedWords predictedWords = new SuggestedWords(
+                    new ArrayList<>(Arrays.asList(prediction1, prediction2, prediction3)),
+                    null /* rawSuggestions */,
+                    null /* typedWord */,
+                    false /* typedWordValid */,
+                    false /* willAutoCorrect */,
+                    false /* isObsoleteSuggestions */,
+                    SuggestedWords.INPUT_STYLE_PREDICTION,
+                    SuggestedWords.NOT_A_SEQUENCE_NUMBER);
+            final String PICKED_WORD = prediction2.mWord;
+            assertNotSuggestionSpan(
+                    PICKED_WORD,
+                    SuggestionSpanUtils.getTextWithSuggestionSpan(getContext(), PICKED_WORD,
+                            predictedWords));
+        }
+
+        final ArrayList<SuggestedWordInfo> suggestedWordList = new ArrayList<>();
+        suggestedWordList.add(typed);
+        suggestedWordList.add(prediction1);
+        suggestedWordList.add(prediction2);
+        suggestedWordList.add(prediction3);
+        suggestedWordList.addAll(Arrays.asList(corrections));
+        final SuggestedWords typedAndCollectedWords = new SuggestedWords(
+                suggestedWordList,
+                null /* rawSuggestions */,
+                null /* typedWord */,
+                false /* typedWordValid */,
+                false /* willAutoCorrect */,
+                false /* isObsoleteSuggestions */,
+                SuggestedWords.INPUT_STYLE_TYPING,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
+
+        for (final SuggestedWordInfo pickedWord : suggestedWordList) {
+            final String PICKED_WORD = pickedWord.mWord;
+
+            final ArrayList<String> expectedSuggestions = new ArrayList<>();
+            for (SuggestedWordInfo suggestedWordInfo : suggestedWordList) {
+                if (expectedSuggestions.size() >= SuggestionSpan.SUGGESTIONS_MAX_SIZE) {
+                    break;
+                }
+                if (suggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_PREDICTION)) {
+                    // Currently predictions are not filled into SuggestionSpan.
+                    continue;
+                }
+                final String suggestedWord = suggestedWordInfo.mWord;
+                if (TextUtils.equals(PICKED_WORD, suggestedWord)) {
+                    // Typed word itself is not added to SuggestionSpan.
+                    continue;
+                }
+                expectedSuggestions.add(suggestedWord);
+            }
+
+            assertSuggestionSpan(
+                    PICKED_WORD,
+                    0 /* reuiredSuggestionSpanFlags */,
+                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE /* requiredSpanFlags */,
+                    expectedSuggestions.toArray(new String[expectedSuggestions.size()]),
+                    SuggestionSpanUtils.getTextWithSuggestionSpan(getContext(), PICKED_WORD,
+                            typedAndCollectedWords));
+        }
+    }
+
+    public void testFindFirstLocaleFromSuggestionSpans() {
+        final String[] suggestions = new String[] {"Quality", "Speed", "Price"};
+        final SuggestionSpan nullLocaleSpan = new SuggestionSpan((Locale)null, suggestions, 0);
+        final SuggestionSpan emptyLocaleSpan = new SuggestionSpan(new Locale(""), suggestions, 0);
+        final SuggestionSpan enUsLocaleSpan = new SuggestionSpan(Locale.US, suggestions, 0);
+        final SuggestionSpan jaJpLocaleSpan = new SuggestionSpan(Locale.JAPAN, suggestions, 0);
+
+        assertEquals(null, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {}));
+
+        assertEquals(null, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {emptyLocaleSpan}));
+
+        assertEquals(Locale.US, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {enUsLocaleSpan}));
+
+        assertEquals(Locale.US, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {nullLocaleSpan, enUsLocaleSpan}));
+
+        assertEquals(Locale.US, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {nullLocaleSpan, emptyLocaleSpan, enUsLocaleSpan}));
+
+        assertEquals(Locale.JAPAN, SuggestionSpanUtils.findFirstLocaleFromSuggestionSpans(
+                new SuggestionSpan[] {nullLocaleSpan, jaJpLocaleSpan, enUsLocaleSpan}));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java
deleted file mode 100644
index a25d6d6..0000000
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.res.Resources;
-import android.text.InputType;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.RunInLocale;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.Locale;
-
-abstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBase {
-    public void testActionUnspecified() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "unspecifiled "
-                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
-        }
-    }
-
-    public void testActionNone() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NONE,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
-        }
-    }
-
-    public void testActionSearch() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEARCH,
-                    KeyboardIconsSet.NAME_SEARCH_KEY);
-        }
-    }
-
-    public abstract void testActionGo();
-    public abstract void testActionSend();
-    public abstract void testActionNext();
-    public abstract void testActionDone();
-    public abstract void testActionPrevious();
-
-    public void testActionCustom() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            final CharSequence customLabel = "customLabel";
-            final EditorInfo editorInfo = new EditorInfo();
-            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
-            editorInfo.actionLabel = customLabel;
-            doTestActionKeyLabel(tag, subtype, editorInfo, customLabel);
-        }
-    }
-
-    private static void doTestActionKey(final String tag, final KeyboardLayoutSet layoutSet,
-            final int elementId, final CharSequence label, final int iconId) {
-        final Keyboard keyboard = layoutSet.getKeyboard(elementId);
-        final Key enterKey = keyboard.getKey(Constants.CODE_ENTER);
-        assertNotNull(tag + " enter key on " + keyboard.mId, enterKey);
-        assertEquals(tag + " enter label " + enterKey, label, enterKey.getLabel());
-        assertEquals(tag + " enter icon " + enterKey, iconId, enterKey.getIconId());
-    }
-
-    protected void doTestActionKeyLabelResId(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final int labelResId) {
-        final Locale labelLocale = subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)
-                ? null : SubtypeLocaleUtils.getSubtypeLocale(subtype);
-        doTestActionKeyLabelResIdInLocale(tag, subtype, actionId, labelLocale, labelResId);
-    }
-
-    protected void doTestActionKeyLabelResIdInLocale(final String tag,
-            final InputMethodSubtype subtype, final int actionId, final Locale labelLocale,
-            final int labelResId) {
-        final EditorInfo editorInfo = new EditorInfo();
-        editorInfo.imeOptions = actionId;
-        final RunInLocale<String> job = new RunInLocale<String>() {
-            @Override
-            protected String job(final Resources res) {
-                return res.getString(labelResId);
-            }
-        };
-        final String label = job.runInLocale(getContext().getResources(), labelLocale);
-        doTestActionKeyLabel(tag, subtype, editorInfo, label);
-    }
-
-    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
-            final EditorInfo editorInfo, final CharSequence label) {
-        // Test text layouts.
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
-        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test number password layouts.
-        editorInfo.inputType =
-                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
-        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-    }
-
-    protected void doTestActionKeyIcon(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final String iconName) {
-        final int iconId = KeyboardIconsSet.getIconId(iconName);
-        final EditorInfo editorInfo = new EditorInfo();
-        editorInfo.imeOptions = actionId;
-        // Test text layouts.
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
-        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, null /* label */, iconId);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, null /* label */, iconId);
-        // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, null /* label */, iconId);
-        // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
-        // Test number password layout.
-        editorInfo.inputType =
-                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
-        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
deleted file mode 100644
index 322a344..0000000
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.res.Resources;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.utils.RunInLocale;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.Locale;
-
-@MediumTest
-public class KeyboardLayoutSetActionLabelKlpTests extends KeyboardLayoutSetActionLabelBase {
-    @Override
-    protected int getKeyboardThemeForTests() {
-        return KeyboardTheme.THEME_ID_KLP;
-    }
-
-    @Override
-    public void testActionGo() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_GO,
-                    R.string.label_go_key);
-        }
-    }
-
-    @Override
-    public void testActionSend() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_SEND,
-                    R.string.label_send_key);
-        }
-    }
-
-    @Override
-    public void testActionNext() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_NEXT,
-                    R.string.label_next_key);
-        }
-    }
-
-    @Override
-    public void testActionDone() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_DONE,
-                    R.string.label_done_key);
-        }
-    }
-
-    @Override
-    public void testActionPrevious() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS,
-                    R.string.label_previous_key);
-        }
-    }
-
-    // Working variable to simulate system locale changing.
-    private Locale mSystemLocale = Locale.getDefault();
-
-    private void doTestActionLabelInLocale(final InputMethodSubtype subtype,
-            final Locale labelLocale, final Locale systemLocale) {
-        // Simulate system locale changing, see {@link SystemBroadcastReceiver}.
-        if (!systemLocale.equals(mSystemLocale)) {
-            KeyboardLayoutSet.onSystemLocaleChanged();
-            mSystemLocale = systemLocale;
-        }
-        final String tag = "label=" + labelLocale + " system=" + systemLocale
-                + " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-        final RunInLocale<Void> job = new RunInLocale<Void>() {
-            @Override
-            public Void job(final Resources res) {
-                doTestActionKeyIcon(tag + " unspecified", subtype,
-                        EditorInfo.IME_ACTION_UNSPECIFIED, KeyboardIconsSet.NAME_ENTER_KEY);
-                doTestActionKeyIcon(tag + " none", subtype,
-                        EditorInfo.IME_ACTION_NONE, KeyboardIconsSet.NAME_ENTER_KEY);
-                doTestActionKeyLabelResIdInLocale(tag + " go", subtype,
-                        EditorInfo.IME_ACTION_GO, labelLocale, R.string.label_go_key);
-                doTestActionKeyIcon(tag + " search", subtype,
-                        EditorInfo.IME_ACTION_SEARCH, KeyboardIconsSet.NAME_SEARCH_KEY);
-                doTestActionKeyLabelResIdInLocale(tag + " send", subtype,
-                        EditorInfo.IME_ACTION_SEND, labelLocale, R.string.label_send_key);
-                doTestActionKeyLabelResIdInLocale(tag + " next", subtype,
-                        EditorInfo.IME_ACTION_NEXT, labelLocale, R.string.label_next_key);
-                doTestActionKeyLabelResIdInLocale(tag + " done", subtype,
-                        EditorInfo.IME_ACTION_DONE, labelLocale, R.string.label_done_key);
-                doTestActionKeyLabelResIdInLocale(tag + " previous", subtype,
-                        EditorInfo.IME_ACTION_PREVIOUS, labelLocale, R.string.label_previous_key);
-                return null;
-            }
-        };
-        job.runInLocale(getContext().getResources(), systemLocale);
-    }
-
-    public void testActionLabelInOtherLocale() {
-        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
-        final InputMethodSubtype italian = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.ITALIAN.toString(), SubtypeLocaleUtils.QWERTY);
-        // An action label should be displayed in subtype's locale regardless of the system locale.
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.US);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.FRENCH);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.ITALIAN);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.JAPANESE);
-    }
-
-    public void testNoLanguageSubtypeActionLabel() {
-        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
-        final InputMethodSubtype noLanguage = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
-        // An action label of no language keyboard should be displayed in the system locale.
-        doTestActionLabelInLocale(noLanguage, Locale.US, Locale.US);
-        doTestActionLabelInLocale(noLanguage, Locale.FRENCH, Locale.FRENCH);
-        doTestActionLabelInLocale(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
-        doTestActionLabelInLocale(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
deleted file mode 100644
index 028b3e4..0000000
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-@MediumTest
-public class KeyboardLayoutSetActionLabelLxxTests extends KeyboardLayoutSetActionLabelBase {
-    @Override
-    protected int getKeyboardThemeForTests() {
-        return KeyboardTheme.THEME_ID_LXX_LIGHT;
-    }
-
-    @Override
-    public void testActionGo() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_GO,
-                    KeyboardIconsSet.NAME_GO_KEY);
-        }
-    }
-
-    @Override
-    public void testActionSend() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEND,
-                    KeyboardIconsSet.NAME_SEND_KEY);
-        }
-    }
-
-    @Override
-    public void testActionNext() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NEXT,
-                    KeyboardIconsSet.NAME_NEXT_KEY);
-        }
-    }
-
-    @Override
-    public void testActionDone() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_DONE,
-                    KeyboardIconsSet.NAME_DONE_KEY);
-        }
-    }
-
-    @Override
-    public void testActionPrevious() {
-        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
-            final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS,
-                    KeyboardIconsSet.NAME_PREVIOUS_KEY);
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetNavigateMoreKeysBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetNavigateMoreKeysBase.java
index 8a55455..21333b0 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetNavigateMoreKeysBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetNavigateMoreKeysBase.java
@@ -22,9 +22,9 @@
 
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Arrays;
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
deleted file mode 100644
index 6b0652c..0000000
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetSubtypesCountTests.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.ArrayList;
-
-@SmallTest
-public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
-    private static final int NUMBER_OF_SUBTYPES = 76;
-    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 45;
-    private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
-
-    @Override
-    protected int getKeyboardThemeForTests() {
-        return KeyboardTheme.THEME_ID_KLP;
-    }
-
-    private static String toString(final ArrayList<InputMethodSubtype> subtypeList) {
-        final StringBuilder sb = new StringBuilder();
-        for (int index = 0; index < subtypeList.size(); index++) {
-            final InputMethodSubtype subtype = subtypeList.get(index);
-            sb.append(index + ": ");
-            sb.append(SubtypeLocaleUtils.getSubtypeNameForLogging(subtype));
-            sb.append("\n");
-        }
-        return sb.toString();
-    }
-
-    public final void testAllSubtypesCount() {
-        final ArrayList<InputMethodSubtype> allSubtypesList = getAllSubtypesList();
-        assertEquals(toString(allSubtypesList), NUMBER_OF_SUBTYPES, allSubtypesList.size());
-    }
-
-    public final void testAsciiCapableSubtypesCount() {
-        final ArrayList<InputMethodSubtype> asciiCapableSubtypesList =
-                getAsciiCapableSubtypesList();
-        assertEquals(toString(asciiCapableSubtypesList),
-                NUMBER_OF_ASCII_CAPABLE_SUBTYPES, asciiCapableSubtypesList.size());
-    }
-
-    public final void testAdditionalSubtypesCount() {
-        final ArrayList<InputMethodSubtype> additionalSubtypesList = getAdditionalSubtypesList();
-        assertEquals(toString(additionalSubtypesList),
-                NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES, additionalSubtypesList.size());
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
index a002bbe..29787ac 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetTestsBase.java
@@ -26,9 +26,11 @@
 
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
 import com.android.inputmethod.keyboard.KeyboardLayoutSet.Builder;
-import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
 import com.android.inputmethod.latin.utils.ResourceUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -39,9 +41,27 @@
 public abstract class KeyboardLayoutSetTestsBase extends AndroidTestCase {
     // All input method subtypes of LatinIME.
     private final ArrayList<InputMethodSubtype> mAllSubtypesList = new ArrayList<>();
-    private final ArrayList<InputMethodSubtype> mAsciiCapableSubtypesList = new ArrayList<>();
-    private final ArrayList<InputMethodSubtype> mAdditionalSubtypesList = new ArrayList<>();
 
+    public interface SubtypeFilter {
+        public boolean accept(final InputMethodSubtype subtype);
+    }
+
+    public static final SubtypeFilter FILTER_IS_ASCII_CAPABLE = new SubtypeFilter() {
+        @Override
+        public boolean accept(InputMethodSubtype subtype) {
+            return InputMethodSubtypeCompatUtils.isAsciiCapable(subtype);
+        }
+    };
+
+    public static final SubtypeFilter FILTER_IS_ADDITIONAL_SUBTYPE = new SubtypeFilter() {
+        @Override
+        public boolean accept(InputMethodSubtype subtype) {
+            return AdditionalSubtypeUtils.isAdditionalSubtype(subtype);
+        }
+    };
+
+    private RichInputMethodManager mRichImm;
+    private InputMethodSubtype[] mSavedAdditionalSubtypes;
     private int mScreenMetrics;
 
     protected abstract int getKeyboardThemeForTests();
@@ -49,46 +69,57 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        final Context context = getContext();
+        final Resources res = context.getResources();
+        RichInputMethodManager.init(context);
+        mRichImm = RichInputMethodManager.getInstance();
+
+        // Save and reset additional subtypes preference.
+        mSavedAdditionalSubtypes = mRichImm.getAdditionalSubtypes();
+        final InputMethodSubtype[] predefinedAdditionalSubtypes =
+                AdditionalSubtypeUtils.createAdditionalSubtypesArray(
+                        AdditionalSubtypeUtils.createPrefSubtypes(
+                                res.getStringArray(R.array.predefined_subtypes)));
+        mRichImm.setAdditionalInputMethodSubtypes(predefinedAdditionalSubtypes);
+
         final KeyboardTheme keyboardTheme = KeyboardTheme.searchKeyboardThemeById(
-                getKeyboardThemeForTests());
+                getKeyboardThemeForTests(), KeyboardTheme.KEYBOARD_THEMES);
         setContext(new ContextThemeWrapper(getContext(), keyboardTheme.mStyleId));
         KeyboardLayoutSet.onKeyboardThemeChanged();
 
-        final Context context = getContext();
-        mScreenMetrics = context.getResources().getInteger(R.integer.config_screen_metrics);
-        RichInputMethodManager.init(context);
-        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        mScreenMetrics = Settings.readScreenMetrics(res);
 
-        final InputMethodInfo imi = richImm.getInputMethodInfoOfThisIme();
+        final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
         final int subtypeCount = imi.getSubtypeCount();
         for (int index = 0; index < subtypeCount; index++) {
-            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
-            if (AdditionalSubtypeUtils.isAdditionalSubtype(subtype)) {
-                mAdditionalSubtypesList.add(subtype);
-                continue;
-            }
-            mAllSubtypesList.add(subtype);
-            if (InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)) {
-                mAsciiCapableSubtypesList.add(subtype);
-            }
+            mAllSubtypesList.add(imi.getSubtypeAt(index));
         }
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        // Restore additional subtypes preference.
+        mRichImm.setAdditionalInputMethodSubtypes(mSavedAdditionalSubtypes);
+        super.tearDown();
+    }
+
     protected final ArrayList<InputMethodSubtype> getAllSubtypesList() {
         return mAllSubtypesList;
     }
 
-    protected final ArrayList<InputMethodSubtype> getAsciiCapableSubtypesList() {
-        return mAsciiCapableSubtypesList;
-    }
-
-    protected final ArrayList<InputMethodSubtype> getAdditionalSubtypesList() {
-        return mAdditionalSubtypesList;
+    protected final ArrayList<InputMethodSubtype> getSubtypesFilteredBy(
+            final SubtypeFilter filter) {
+        final ArrayList<InputMethodSubtype> list = new ArrayList<>();
+        for (final InputMethodSubtype subtype : mAllSubtypesList) {
+            if (filter.accept(subtype)) {
+                list.add(subtype);
+            }
+        }
+        return list;
     }
 
     protected final boolean isPhone() {
-        return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_PHONE
-                || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_PHONE;
+        return Constants.isPhone(mScreenMetrics);
     }
 
     protected final InputMethodSubtype getSubtype(final Locale locale,
@@ -101,7 +132,7 @@
                 return subtype;
             }
         }
-        for (final InputMethodSubtype subtype : mAsciiCapableSubtypesList) {
+        for (final InputMethodSubtype subtype : getSubtypesFilteredBy(FILTER_IS_ASCII_CAPABLE)) {
             final Locale subtypeLocale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
             if (locale.equals(subtypeLocale)) {
                 // Create additional subtype.
@@ -116,21 +147,22 @@
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo) {
         return createKeyboardLayoutSet(subtype, editorInfo, false /* voiceInputKeyEnabled */,
-                false /* languageSwitchKeyEnabled */);
+                false /* languageSwitchKeyEnabled */, false /* splitLayoutEnabled */);
     }
 
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
-            final boolean languageSwitchKeyEnabled) {
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
         final Context context = getContext();
         final Resources res = context.getResources();
         final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
         final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
         final Builder builder = new Builder(context, editorInfo);
         builder.setKeyboardGeometry(keyboardWidth, keyboardHeight)
-                .setSubtype(subtype)
+                .setSubtype(RichInputMethodSubtype.getRichInputMethodSubtype(subtype))
                 .setVoiceInputKeyEnabled(voiceInputKeyEnabled)
-                .setLanguageSwitchKeyEnabled(languageSwitchKeyEnabled);
+                .setLanguageSwitchKeyEnabled(languageSwitchKeyEnabled)
+                .setSplitLayoutEnabledByUser(splitLayoutEnabled);
         return builder.build();
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java
new file mode 100644
index 0000000..1e1f82f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015 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;
+
+import static org.junit.Assert.assertEquals;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+
+@SmallTest
+public class KeyboardLayoutTest {
+
+    @Test
+    public void testNewKeyboardLayout() {
+        KeyboardLayout keyboardLayout = KeyboardLayout
+                .newKeyboardLayout(new ArrayList<Key>(), 11, 12, 13, 14);
+
+        assertEquals(11, keyboardLayout.mMostCommonKeyWidth);
+        assertEquals(12, keyboardLayout.mMostCommonKeyHeight);
+        assertEquals(13, keyboardLayout.mKeyboardWidth);
+        assertEquals(14, keyboardLayout.mKeyboardHeight);
+
+        assertEquals(0, keyboardLayout.getKeyCodes().length);
+        assertEquals(0, keyboardLayout.getKeyWidths().length);
+        assertEquals(0, keyboardLayout.getKeyHeights().length);
+        assertEquals(0, keyboardLayout.getKeyXCoordinates().length);
+        assertEquals(0, keyboardLayout.getKeyYCoordinates().length);
+
+        Key key1 = new Key("label1", 101, 102, "101", "101hint", 103, 104, 105, 106, 1100, 1101,
+                10, 10);
+        Key key2 = new Key("label2", 201, 103, "201", "201hint", 203, 204, 205, 206, 2100, 2101,
+                10, 10);
+
+        ArrayList<Key> sortedKeys = new ArrayList<>(2);
+        sortedKeys.add(key1);
+        sortedKeys.add(key2);
+        keyboardLayout = KeyboardLayout.newKeyboardLayout(sortedKeys, 11, 12, 13, 14);
+        assertEquals(2, keyboardLayout.getKeyCodes().length);
+        assertEquals(2, keyboardLayout.getKeyWidths().length);
+        assertEquals(2, keyboardLayout.getKeyHeights().length);
+        assertEquals(2, keyboardLayout.getKeyXCoordinates().length);
+        assertEquals(2, keyboardLayout.getKeyYCoordinates().length);
+
+        assertEquals(102, keyboardLayout.getKeyCodes()[0]);
+        // xCo + horizontalGap/2
+        assertEquals(105 + 5, keyboardLayout.getKeyXCoordinates()[0]);
+        assertEquals(106, keyboardLayout.getKeyYCoordinates()[0]);
+        // width - horizontalGap
+        assertEquals(1100 - 10, keyboardLayout.getKeyWidths()[0]);
+        // height - verticalGap
+        assertEquals(1101 - 10, keyboardLayout.getKeyHeights()[0]);
+
+        assertEquals(103, keyboardLayout.getKeyCodes()[1]);
+        // xCo + horizontalGap/2
+        assertEquals(205 + 5, keyboardLayout.getKeyXCoordinates()[1]);
+        assertEquals(206, keyboardLayout.getKeyYCoordinates()[1]);
+        // width - horizontalGap
+        assertEquals(2100 - 10, keyboardLayout.getKeyWidths()[1]);
+        // height - verticalGap
+        assertEquals(2101 - 10, keyboardLayout.getKeyHeights()[1]);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
index c20954f..33e88c1 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardThemeTests.java
@@ -16,18 +16,20 @@
 
 package com.android.inputmethod.keyboard;
 
-import static com.android.inputmethod.compat.BuildCompatUtils.VERSION_CODES_LXX;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_ICS;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_KLP;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_DARK;
 import static com.android.inputmethod.keyboard.KeyboardTheme.THEME_ID_LXX_LIGHT;
 
 import android.content.SharedPreferences;
+import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.preference.PreferenceManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import java.util.Arrays;
+
 @SmallTest
 public class KeyboardThemeTests extends AndroidTestCase {
     private SharedPreferences mPrefs;
@@ -77,7 +79,9 @@
     }
 
     private void assertKeyboardTheme(final int sdkVersion, final int expectedThemeId) {
-        assertEquals(expectedThemeId, KeyboardTheme.getKeyboardTheme(mPrefs, sdkVersion).mThemeId);
+        final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
+                mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
+        assertEquals(expectedThemeId, actualTheme.mThemeId);
     }
 
     /*
@@ -127,7 +131,7 @@
     }
 
     public void testKeyboardThemePreferenceOnLxx() {
-        assertKeyboardThemePreferenceOnLxx(VERSION_CODES_LXX);
+        assertKeyboardThemePreferenceOnLxx(Build.VERSION_CODES.LOLLIPOP);
     }
 
     /*
@@ -139,8 +143,8 @@
         final String oldPrefKey = KeyboardTheme.KLP_KEYBOARD_THEME_KEY;
         setKeyboardThemePreference(oldPrefKey, previousThemeId);
 
-        final KeyboardTheme defaultTheme =
-                KeyboardTheme.getDefaultKeyboardTheme(mPrefs, sdkVersion);
+        final KeyboardTheme defaultTheme = KeyboardTheme.getDefaultKeyboardTheme(
+                mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
 
         assertNotNull(defaultTheme);
         assertEquals(expectedThemeId, defaultTheme.mThemeId);
@@ -180,7 +184,7 @@
     }
 
     public void testDefaultKeyboardThemeOnLxx() {
-        assertDefaultKeyboardThemeOnLxx(VERSION_CODES_LXX);
+        assertDefaultKeyboardThemeOnLxx(Build.VERSION_CODES.LOLLIPOP);
     }
 
     /*
@@ -194,7 +198,8 @@
         // Clean up new keyboard theme preference to simulate "upgrade to LXX keyboard".
         setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
 
-        final KeyboardTheme theme = KeyboardTheme.getKeyboardTheme(mPrefs, sdkVersion);
+        final KeyboardTheme theme = KeyboardTheme.getKeyboardTheme(
+                mPrefs, sdkVersion, KeyboardTheme.KEYBOARD_THEMES);
 
         assertNotNull(theme);
         assertEquals(expectedThemeId, theme.mThemeId);
@@ -246,7 +251,7 @@
 
     // Upgrading keyboard on L.
     public void testUpgradeKeyboardToLxxOnLxx() {
-        assertUpgradeKeyboardToLxxOnLxx(VERSION_CODES_LXX);
+        assertUpgradeKeyboardToLxxOnLxx(Build.VERSION_CODES.LOLLIPOP);
     }
 
     /*
@@ -299,7 +304,7 @@
 
     private void assertUpgradePlatformToLxxFrom(final int oldSdkVersion) {
         // Forced to switch to LXX theme.
-        final int newSdkVersion = VERSION_CODES_LXX;
+        final int newSdkVersion = Build.VERSION_CODES.LOLLIPOP;
         assertUpgradePlatformFromTo(
                 oldSdkVersion, newSdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
         assertUpgradePlatformFromTo(
@@ -324,8 +329,8 @@
 
     // Update platform from L to L.
     public void testUpgradePlatformToLxxFromLxx() {
-        final int oldSdkVersion = VERSION_CODES_LXX;
-        final int newSdkVersion = VERSION_CODES_LXX;
+        final int oldSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+        final int newSdkVersion = Build.VERSION_CODES.LOLLIPOP;
         assertUpgradePlatformFromTo(
                 oldSdkVersion, newSdkVersion, THEME_ID_NULL, THEME_ID_LXX_LIGHT);
         assertUpgradePlatformFromTo(
@@ -341,4 +346,86 @@
         assertUpgradePlatformFromTo(
                 oldSdkVersion, newSdkVersion, THEME_ID_ILLEGAL, THEME_ID_LXX_LIGHT);
     }
+
+    /*
+     * Test that KeyboardTheme array should be sorted by descending order of
+     * {@link KeyboardTheme#mMinApiVersion}.
+     */
+    private static void assertSortedKeyboardThemeArray(final KeyboardTheme[] array) {
+        assertNotNull(array);
+        final int length = array.length;
+        assertTrue("array length=" + length, length > 0);
+        for (int index = 0; index < length - 1; index++) {
+            final KeyboardTheme theme = array[index];
+            final KeyboardTheme nextTheme = array[index + 1];
+            assertTrue("sorted MinApiVersion: "
+                    + theme.mThemeName + ": minApiVersion=" + theme.mMinApiVersion,
+                    theme.mMinApiVersion >= nextTheme.mMinApiVersion);
+        }
+    }
+
+    public void testSortedKeyboardTheme() {
+        assertSortedKeyboardThemeArray(KeyboardTheme.KEYBOARD_THEMES);
+    }
+
+    public void testSortedAvailableKeyboardTheme() {
+        assertSortedKeyboardThemeArray(KeyboardTheme.getAvailableThemeArray(getContext()));
+    }
+
+    /*
+     * Test for missing selected theme.
+     */
+    private static KeyboardTheme[] LIMITED_THEMES = {
+        KeyboardTheme.searchKeyboardThemeById(THEME_ID_ICS, KeyboardTheme.KEYBOARD_THEMES),
+        KeyboardTheme.searchKeyboardThemeById(THEME_ID_KLP, KeyboardTheme.KEYBOARD_THEMES)
+    };
+    static {
+        Arrays.sort(LIMITED_THEMES);
+        assertSortedKeyboardThemeArray(LIMITED_THEMES);
+    }
+
+    public void testMissingSelectedThemeIcs() {
+        // Clean up preferences.
+        setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+        setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+
+        final int sdkVersion = VERSION_CODES.ICE_CREAM_SANDWICH;
+        final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
+        setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_LIGHT);
+
+        final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
+                mPrefs, sdkVersion, LIMITED_THEMES);
+        // LXX_LIGHT is missing, fall-back to KLP.
+        assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
+    }
+
+    public void testMissingSelectedThemeKlp() {
+        // Clean up preferences.
+        setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+        setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+
+        final int sdkVersion = VERSION_CODES.KITKAT;
+        final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
+        setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_LIGHT);
+
+        final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
+                mPrefs, sdkVersion, LIMITED_THEMES);
+        // LXX_LIGHT is missing, fall-back to KLP.
+        assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
+    }
+
+    public void testMissingSelectedThemeLxx() {
+        // Clean up preferences.
+        setKeyboardThemePreference(KeyboardTheme.KLP_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+        setKeyboardThemePreference(KeyboardTheme.LXX_KEYBOARD_THEME_KEY, THEME_ID_NULL);
+
+        final int sdkVersion = Build.VERSION_CODES.LOLLIPOP;
+        final String oldPrefKey = KeyboardTheme.getPreferenceKey(sdkVersion);
+        setKeyboardThemePreference(oldPrefKey, THEME_ID_LXX_DARK);
+
+        final KeyboardTheme actualTheme = KeyboardTheme.getKeyboardTheme(
+                mPrefs, sdkVersion, LIMITED_THEMES);
+        // LXX_DARK is missing, fall-back to KLP.
+        assertEquals(THEME_ID_KLP, actualTheme.mThemeId);
+    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/action/ActionTestsBase.java b/tests/src/com/android/inputmethod/keyboard/action/ActionTestsBase.java
new file mode 100644
index 0000000..1ea68e4
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/ActionTestsBase.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.InputType;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.keyboard.KeyboardLayoutSetTestsBase;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.Locale;
+
+abstract class ActionTestsBase extends KeyboardLayoutSetTestsBase {
+    static class ExpectedActionKey {
+        static ExpectedActionKey newIconKey(final String iconName) {
+            final int iconId = KeyboardIconsSet.getIconId(iconName);
+            return new ExpectedActionKey(ExpectedKeyVisual.newInstance(iconId));
+        }
+
+        static ExpectedActionKey newLabelKey(final String label) {
+            return new ExpectedActionKey(ExpectedKeyVisual.newInstance(label));
+        }
+
+        static ExpectedActionKey newLabelKey(final int labelResId,
+                final Locale labelLocale, final Context context) {
+            final RunInLocale<String> getString = new RunInLocale<String>() {
+                @Override
+                protected String job(final Resources res) {
+                    return res.getString(labelResId);
+                }
+            };
+            return newLabelKey(getString.runInLocale(context.getResources(), labelLocale));
+        }
+
+        private final ExpectedKeyVisual mVisual;
+
+        private ExpectedActionKey(final ExpectedKeyVisual visual) {
+            mVisual = visual;
+        }
+
+        public int getIconId() { return mVisual.getIconId(); }
+
+        public String getLabel() { return mVisual.getLabel(); }
+    }
+
+    protected static Locale getLabelLocale(final InputMethodSubtype subtype) {
+        final String localeString = subtype.getLocale();
+        if (localeString.equals(SubtypeLocaleUtils.NO_LANGUAGE)) {
+            return null;
+        }
+        return LocaleUtils.constructLocaleFromString(localeString);
+    }
+
+    private static void assertActionKey(final String tag, final KeyboardLayoutSet layoutSet,
+            final int elementId, final ExpectedActionKey expectedKey) {
+        final Keyboard keyboard = layoutSet.getKeyboard(elementId);
+        final Key actualKey = keyboard.getKey(Constants.CODE_ENTER);
+        assertNotNull(tag + " enter key on " + keyboard.mId, actualKey);
+        assertEquals(tag + " label " + expectedKey, expectedKey.getLabel(), actualKey.getLabel());
+        assertEquals(tag + " icon " + expectedKey, expectedKey.getIconId(), actualKey.getIconId());
+    }
+
+    protected void doTestActionKey(final String tag, final InputMethodSubtype subtype,
+            final int actionId, final ExpectedActionKey expectedKey) {
+        final EditorInfo editorInfo = new EditorInfo();
+        editorInfo.imeOptions = actionId;
+        doTestActionKey(tag, subtype, editorInfo, expectedKey);
+    }
+
+    protected void doTestActionKey(final String tag, final InputMethodSubtype subtype,
+            final EditorInfo editorInfo, final ExpectedActionKey expectedKey) {
+        // Test text layouts.
+        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, expectedKey);
+        // Test phone number layouts.
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, expectedKey);
+        // Test normal number layout.
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
+        // Test number password layout.
+        editorInfo.inputType =
+                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
+        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
+        assertActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionCustomTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionCustomTests.java
new file mode 100644
index 0000000..cb1c6ad
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionCustomTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionCustomTests extends KlpActionTestsBase {
+    public void testActionCustom() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final EditorInfo editorInfo = new EditorInfo();
+            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
+            editorInfo.actionLabel = "customLabel";
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey("customLabel");
+            doTestActionKey(tag, subtype, editorInfo, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionDoneTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionDoneTests.java
new file mode 100644
index 0000000..e0a87a7
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionDoneTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionDoneTests extends KlpActionTestsBase {
+    public void testActionDone() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_done_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_DONE, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionGoTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionGoTests.java
new file mode 100644
index 0000000..865b598
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionGoTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionGoTests extends KlpActionTestsBase {
+    public void testActionGo() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_go_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_GO, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionLabelTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionLabelTests.java
new file mode 100644
index 0000000..07c604e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionLabelTests.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.content.res.Resources;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.Locale;
+
+@MediumTest
+public class KlpActionLabelTests extends KlpActionTestsBase {
+    void doTestActionKeys(final InputMethodSubtype subtype, final String tag,
+            final ExpectedActionKey unspecifiedKey, final ExpectedActionKey noneKey,
+            final ExpectedActionKey goKey, final ExpectedActionKey searchKey,
+            final ExpectedActionKey sendKey, final ExpectedActionKey nextKey,
+            final ExpectedActionKey doneKey, final ExpectedActionKey previousKey) {
+        doTestActionKey(
+                tag + " unspecified", subtype, EditorInfo.IME_ACTION_UNSPECIFIED, unspecifiedKey);
+        doTestActionKey(tag + " none", subtype, EditorInfo.IME_ACTION_NONE, noneKey);
+        doTestActionKey(tag + " go", subtype, EditorInfo.IME_ACTION_GO, goKey);
+        doTestActionKey(tag + " search", subtype, EditorInfo.IME_ACTION_SEARCH, searchKey);
+        doTestActionKey(tag + " send", subtype, EditorInfo.IME_ACTION_SEND, sendKey);
+        doTestActionKey(tag + " next", subtype, EditorInfo.IME_ACTION_NEXT, nextKey);
+        doTestActionKey(tag + " done", subtype, EditorInfo.IME_ACTION_DONE, doneKey);
+        doTestActionKey(tag + " previous", subtype, EditorInfo.IME_ACTION_PREVIOUS, previousKey);
+    }
+
+    // Working variable to simulate system locale changing.
+    private Locale mSystemLocale = Locale.getDefault();
+
+    private void doTestActionKeysInLocaleWithStringResources(final InputMethodSubtype subtype,
+            final Locale labelLocale, final Locale systemLocale) {
+        // Simulate system locale changing, see {@link SystemBroadcastReceiver}.
+        if (!systemLocale.equals(mSystemLocale)) {
+            KeyboardLayoutSet.onSystemLocaleChanged();
+            mSystemLocale = systemLocale;
+        }
+        final ExpectedActionKey enterKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        final ExpectedActionKey goKey = ExpectedActionKey.newLabelKey(
+                R.string.label_go_key, labelLocale, getContext());
+        final ExpectedActionKey searchKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
+        final ExpectedActionKey sendKey = ExpectedActionKey.newLabelKey(
+                R.string.label_send_key, labelLocale, getContext());
+        final ExpectedActionKey nextKey = ExpectedActionKey.newLabelKey(
+                R.string.label_next_key, labelLocale, getContext());
+        final ExpectedActionKey doneKey = ExpectedActionKey.newLabelKey(
+                R.string.label_done_key, labelLocale, getContext());
+        final ExpectedActionKey previousKey = ExpectedActionKey.newLabelKey(
+                R.string.label_previous_key, labelLocale, getContext());
+        final String tag = "label=" + labelLocale + " system=" + systemLocale
+                + " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+        final RunInLocale<Void> job = new RunInLocale<Void>() {
+            @Override
+            public Void job(final Resources res) {
+                doTestActionKeys(subtype, tag, enterKey, enterKey, goKey, searchKey, sendKey,
+                        nextKey, doneKey, previousKey);
+                return null;
+            }
+        };
+        job.runInLocale(getContext().getResources(), systemLocale);
+    }
+
+    public void testActionLabelInOtherLocale() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final InputMethodSubtype italian = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.ITALIAN.toString(), SubtypeLocaleUtils.QWERTY);
+        // An action label should be displayed in subtype's locale regardless of the system locale.
+        doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.US);
+        doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.FRENCH);
+        doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionKeysInLocaleWithStringResources(italian, Locale.ITALIAN, Locale.JAPANESE);
+    }
+
+    public void testNoLanguageSubtypeActionLabel() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final InputMethodSubtype noLanguage = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
+        // An action label of no language keyboard should be displayed in the system locale.
+        doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.US, Locale.US);
+        doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.FRENCH, Locale.FRENCH);
+        doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionKeysInLocaleWithStringResources(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
+    }
+
+    private void doTestActionKeysInLocaleWithKeyboardTextsSet(final InputMethodSubtype subtype,
+            final Locale labelLocale, final Locale systemLocale) {
+        // Simulate system locale changing, see {@link SystemBroadcastReceiver}.
+        if (!systemLocale.equals(mSystemLocale)) {
+            KeyboardLayoutSet.onSystemLocaleChanged();
+            mSystemLocale = systemLocale;
+        }
+        final KeyboardTextsSet textsSet = new KeyboardTextsSet();
+        textsSet.setLocale(labelLocale, getContext());
+        final ExpectedActionKey enterKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        final ExpectedActionKey goKey = ExpectedActionKey.newLabelKey(
+                textsSet.getText("label_go_key"));
+        final ExpectedActionKey searchKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
+        final ExpectedActionKey sendKey = ExpectedActionKey.newLabelKey(
+                textsSet.getText("label_send_key"));
+        final ExpectedActionKey nextKey = ExpectedActionKey.newLabelKey(
+                textsSet.getText("label_next_key"));
+        final ExpectedActionKey doneKey = ExpectedActionKey.newLabelKey(
+                textsSet.getText("label_done_key"));
+        final ExpectedActionKey previousKey = ExpectedActionKey.newLabelKey(
+                textsSet.getText("label_previous_key"));
+        final String tag = "label=" + subtype.getLocale() + " system=" + systemLocale
+                + " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+        final RunInLocale<Void> job = new RunInLocale<Void>() {
+            @Override
+            public Void job(final Resources res) {
+                doTestActionKeys(subtype, tag, enterKey, enterKey, goKey, searchKey, sendKey,
+                        nextKey, doneKey, previousKey);
+                return null;
+            }
+        };
+        job.runInLocale(getContext().getResources(), systemLocale);
+    }
+
+    public void testHinglishActionLabel() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final Locale hi_ZZ = new Locale("hi", "ZZ");
+        final InputMethodSubtype hiLatn = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                hi_ZZ.toString(), SubtypeLocaleUtils.QWERTY);
+        // This is a preliminary subtype and may not exist.
+        if (hiLatn == null) {
+            return;
+        }
+        // An action label should be displayed in subtype's locale regardless of the system locale.
+        doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, new Locale("hi"));
+        doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.US);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.FRENCH);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.ITALIAN);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(hiLatn, hi_ZZ, Locale.JAPANESE);
+    }
+
+    public void testSerbianLatinActionLabel() {
+        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
+        final Locale sr_ZZ = new Locale("sr", "ZZ");
+        final InputMethodSubtype srLatn = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                sr_ZZ.toString(), "serbian_qwertz");
+        // This is a preliminary subtype and may not exist.
+        if (srLatn == null) {
+            return;
+        }
+        // An action label should be displayed in subtype's locale regardless of the system locale.
+        doTestActionKeysInLocaleWithKeyboardTextsSet(srLatn, sr_ZZ, new Locale("sr"));
+        doTestActionKeysInLocaleWithKeyboardTextsSet(srLatn, sr_ZZ, Locale.US);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(srLatn, sr_ZZ, Locale.FRENCH);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(srLatn, sr_ZZ, Locale.ITALIAN);
+        doTestActionKeysInLocaleWithKeyboardTextsSet(srLatn, sr_ZZ, Locale.JAPANESE);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionNextTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionNextTests.java
new file mode 100644
index 0000000..c67740c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionNextTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionNextTests extends KlpActionTestsBase {
+    public void testActionNext() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_next_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NEXT, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionNoneTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionNoneTests.java
new file mode 100644
index 0000000..0be2ecb
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionNoneTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionNoneTests extends KlpActionTestsBase {
+    public void testActionNone() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NONE, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionPreviousTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionPreviousTests.java
new file mode 100644
index 0000000..af6a154
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionPreviousTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionPreviousTests extends KlpActionTestsBase {
+    public void testActionPrevious() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_previous_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionSearchTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionSearchTests.java
new file mode 100644
index 0000000..adc3fee
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionSearchTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionSearchTests extends KlpActionTestsBase {
+    public void testActionSearch() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEARCH, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionSendTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionSendTests.java
new file mode 100644
index 0000000..82f97a2
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionSendTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionSendTests extends KlpActionTestsBase {
+    public void testActionSend() {
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_send_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEND, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionTestsBase.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionTestsBase.java
new file mode 100644
index 0000000..511f995
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionTestsBase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.KeyboardTheme;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+abstract class KlpActionTestsBase extends ActionTestsBase {
+    // Filter a subtype whose name should be displayed using {@link Locale#ROOT}, such like
+    // Hinglish (hi_ZZ) and Serbian-Latn (sr_ZZ).
+    static final SubtypeFilter SUBTYPE_FILTER_NAME_IN_BASE_LOCALE = new SubtypeFilter() {
+        @Override
+        public boolean accept(final InputMethodSubtype subtype) {
+            return Locale.ROOT.equals(
+                    SubtypeLocaleUtils.getDisplayLocaleOfSubtypeLocale(subtype.getLocale()));
+        }
+    };
+
+    protected ArrayList<InputMethodSubtype> mSubtypesWhoseNameIsDisplayedInItsLocale;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSubtypesWhoseNameIsDisplayedInItsLocale = getSubtypesFilteredBy(new SubtypeFilter() {
+            @Override
+            public boolean accept(final InputMethodSubtype subtype) {
+                return !SUBTYPE_FILTER_NAME_IN_BASE_LOCALE.accept(subtype);
+            }
+        });
+    }
+
+    @Override
+    protected int getKeyboardThemeForTests() {
+        return KeyboardTheme.THEME_ID_KLP;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/KlpActionUnspecifiedTests.java b/tests/src/com/android/inputmethod/keyboard/action/KlpActionUnspecifiedTests.java
new file mode 100644
index 0000000..307e273
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/KlpActionUnspecifiedTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class KlpActionUnspecifiedTests extends KlpActionTestsBase {
+    public void testActionUnspecified() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        for (final InputMethodSubtype subtype : mSubtypesWhoseNameIsDisplayedInItsLocale) {
+            final String tag = "unspecifiled "
+                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionCustomTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionCustomTests.java
new file mode 100644
index 0000000..d561f45
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionCustomTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionCustomTests extends LxxActionTestsBase {
+    public void testActionCustom() {
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            final EditorInfo editorInfo = new EditorInfo();
+            editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
+            editorInfo.actionLabel = "customLabel";
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey("customLabel");
+            doTestActionKey(tag, subtype, editorInfo, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionDoneTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionDoneTests.java
new file mode 100644
index 0000000..b818bb1
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionDoneTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionDoneTests extends LxxActionTestsBase {
+    public void testActionDone() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_DONE_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_DONE, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionGoTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionGoTests.java
new file mode 100644
index 0000000..8001f71
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionGoTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionGoTests extends LxxActionTestsBase {
+    public void testActionGo() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_GO_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_GO, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionNextTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionNextTests.java
new file mode 100644
index 0000000..09a8c87
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionNextTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionNextTests extends LxxActionTestsBase {
+    public void testActionNext() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_NEXT_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NEXT, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionNoneTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionNoneTests.java
new file mode 100644
index 0000000..98595e9
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionNoneTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionNoneTests extends LxxActionTestsBase {
+    public void testActionNone() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NONE, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionPreviousTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionPreviousTests.java
new file mode 100644
index 0000000..2327889
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionPreviousTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionPreviousTests extends LxxActionTestsBase {
+    public void testActionPrevious() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_PREVIOUS_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionSearchTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionSearchTests.java
new file mode 100644
index 0000000..7e1d86b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionSearchTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionSearchTests extends LxxActionTestsBase {
+    public void testActionSearch() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEARCH, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionSendTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionSendTests.java
new file mode 100644
index 0000000..fa0134f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionSendTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionSendTests extends LxxActionTestsBase {
+    public void testActionSend() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEND_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEND, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionTestsBase.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionTestsBase.java
new file mode 100644
index 0000000..70de9a6
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionTestsBase.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import com.android.inputmethod.keyboard.KeyboardTheme;
+
+abstract class LxxActionTestsBase extends ActionTestsBase {
+    @Override
+    protected int getKeyboardThemeForTests() {
+        return KeyboardTheme.THEME_ID_LXX_LIGHT;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/action/LxxActionUnspecifiedTests.java b/tests/src/com/android/inputmethod/keyboard/action/LxxActionUnspecifiedTests.java
new file mode 100644
index 0000000..711ca26
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/action/LxxActionUnspecifiedTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.action;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+@LargeTest
+public class LxxActionUnspecifiedTests extends LxxActionTestsBase {
+    public void testActionUnspecified() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        for (final InputMethodSubtype subtype : getAllSubtypesList()) {
+            final String tag = "unspecifiled "
+                    + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED, expectedKey);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
index 8e26e7f..1cdc787 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java
@@ -17,11 +17,11 @@
 package com.android.inputmethod.keyboard.internal;
 
 import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
+import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
 
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 @SmallTest
 public final class KeySpecParserTests extends KeySpecParserTestsBase {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTestsBase.java
index b8cb11b..79cf10e 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTestsBase.java
@@ -19,8 +19,8 @@
 import static com.android.inputmethod.keyboard.internal.KeyboardCodesSet.PREFIX_CODE;
 import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
 import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.PREFIX_ICON;
-import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT;
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
+import static com.android.inputmethod.latin.common.Constants.CODE_OUTPUT_TEXT;
+import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
 
 import android.test.AndroidTestCase;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index 3ffd0a9..1474c8d 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -18,7 +18,7 @@
 
 import android.test.AndroidTestCase;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 public class KeyboardStateTestsBase extends AndroidTestCase
         implements MockKeyboardSwitcher.MockConstants {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelperTests.java b/tests/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelperTests.java
deleted file mode 100644
index 6ea2758..0000000
--- a/tests/src/com/android/inputmethod/keyboard/internal/LanguageOnSpacebarHelperTests.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2014 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.internal;
-
-import static com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE;
-import static com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper.FORMAT_TYPE_LANGUAGE_ONLY;
-import static com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper.FORMAT_TYPE_NONE;
-
-import android.content.Context;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.RichInputMethodManager;
-import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
-import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-@SmallTest
-public class LanguageOnSpacebarHelperTests extends AndroidTestCase {
-    private final LanguageOnSpacebarHelper mLanguageOnSpacebarHelper =
-            new LanguageOnSpacebarHelper();
-
-    private RichInputMethodManager mRichImm;
-
-    InputMethodSubtype EN_US_QWERTY;
-    InputMethodSubtype EN_GB_QWERTY;
-    InputMethodSubtype FR_AZERTY;
-    InputMethodSubtype FR_CA_QWERTY;
-    InputMethodSubtype FR_CH_SWISS;
-    InputMethodSubtype FR_CH_QWERTY;
-    InputMethodSubtype FR_CH_QWERTZ;
-    InputMethodSubtype ZZ_QWERTY;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        final Context context = getContext();
-        RichInputMethodManager.init(context);
-        mRichImm = RichInputMethodManager.getInstance();
-        SubtypeLocaleUtils.init(context);
-
-        EN_US_QWERTY = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.US.toString(), "qwerty");
-        EN_GB_QWERTY = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.UK.toString(), "qwerty");
-        FR_AZERTY = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.FRENCH.toString(), "azerty");
-        FR_CA_QWERTY = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.CANADA_FRENCH.toString(), "qwerty");
-        FR_CH_SWISS = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                "fr_CH", "swiss");
-        FR_CH_QWERTZ = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                "fr_CH", "qwertz");
-        FR_CH_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                "fr_CH", "qwerty");
-        ZZ_QWERTY = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
-    }
-
-    private static List<InputMethodSubtype> asList(final InputMethodSubtype ... subtypes) {
-        return Arrays.asList(subtypes);
-    }
-
-    public void testOneSubtype() {
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(asList(EN_US_QWERTY));
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */);
-        assertEquals("one same English (US)", FORMAT_TYPE_NONE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("one same NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(asList(FR_AZERTY));
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */);
-        assertEquals("one diff English (US)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("one diff NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-    }
-
-    public void testTwoSubtypes() {
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(asList(EN_US_QWERTY, FR_AZERTY));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */);
-        assertEquals("two same English (US)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("two same French)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_AZERTY));
-        assertEquals("two same NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */);
-        assertEquals("two diff English (US)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("two diff French", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_AZERTY));
-        assertEquals("two diff NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-    }
-
-    public void testSameLanuageSubtypes() {
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(
-                asList(EN_US_QWERTY, EN_GB_QWERTY, FR_AZERTY, ZZ_QWERTY));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */);
-        assertEquals("two same English (US)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("two same English (UK)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_GB_QWERTY));
-        assertEquals("two same NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */);
-        assertEquals("two diff English (US)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_US_QWERTY));
-        assertEquals("two diff English (UK)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(EN_GB_QWERTY));
-        assertEquals("two diff NoLanguage", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(ZZ_QWERTY));
-    }
-
-    public void testMultiSameLanuageSubtypes() {
-        mLanguageOnSpacebarHelper.updateEnabledSubtypes(
-                asList(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(true /* isSame */);
-        assertEquals("multi same French", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_AZERTY));
-        assertEquals("multi same French (CA)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CA_QWERTY));
-        assertEquals("multi same French (CH)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_SWISS));
-        assertEquals("multi same French (CH) (QWERTY)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_QWERTY));
-        assertEquals("multi same French (CH) (QWERTZ)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_QWERTZ));
-
-        mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false /* isSame */);
-        assertEquals("multi diff French", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_AZERTY));
-        assertEquals("multi diff French (CA)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CA_QWERTY));
-        assertEquals("multi diff French (CH)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_SWISS));
-        assertEquals("multi diff French (CH) (QWERTY)", FORMAT_TYPE_FULL_LOCALE,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_QWERTY));
-        assertEquals("multi diff French (CH) (QWERTZ)", FORMAT_TYPE_LANGUAGE_ONLY,
-                mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(FR_CH_QWERTZ));
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index a353e5a..4b2ec95 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -18,7 +18,8 @@
 
 import android.text.TextUtils;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
 
 public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
@@ -26,7 +27,7 @@
         // Argument for {@link KeyboardState#onPressKey} and {@link KeyboardState#onReleaseKey}.
         public static final boolean NOT_SLIDING = false;
         public static final boolean SLIDING = true;
-        // Argument for {@link KeyboardState#onCodeInput}.
+        // Argument for {@link KeyboardState#onEvent}.
         public static final boolean SINGLE = true;
         public static final boolean MULTI = false;
         public static final int CAP_MODE_OFF = Constants.TextUtils.CAP_MODE_OFF;
@@ -183,7 +184,11 @@
         } else {
             mAutoCapsState = mAutoCapsMode;
         }
-        mState.onCodeInput(code, mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
+        final Event event =
+                Event.createSoftwareKeypressEvent(code /* codePoint */, code /* keyCode */,
+                        Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+                        false /* isKeyRepeat */);
+        mState.onEvent(event, mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
     }
 
     public void onFinishSlidingInput() {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java
index 922d2a8..8f4648c 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java
@@ -16,52 +16,33 @@
 
 package com.android.inputmethod.keyboard.internal;
 
-import android.app.Instrumentation;
 import android.content.Context;
 import android.content.res.Resources;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
 
-import java.lang.reflect.Field;
-import java.util.ArrayList;
+import com.android.inputmethod.latin.R;
+
 import java.util.Arrays;
 import java.util.Locale;
 
-@MediumTest
-public class MoreKeySpecSplitTests extends InstrumentationTestCase {
+@SmallTest
+public class MoreKeySpecSplitTests extends AndroidTestCase {
     private static final Locale TEST_LOCALE = Locale.ENGLISH;
-    final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
+    private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        final Instrumentation instrumentation = getInstrumentation();
-        final Context targetContext = instrumentation.getTargetContext();
-        mTextsSet.setLocale(TEST_LOCALE, targetContext);
-        final String[] testResourceNames = getAllResourceIdNames(
-                com.android.inputmethod.latin.tests.R.string.class);
-        final Context testContext = instrumentation.getContext();
-        final Resources testRes = testContext.getResources();
-        final String testResPackageName = testRes.getResourcePackageName(
-                // This dummy raw resource is needed to be able to load string resources from a test
-                // APK successfully.
-                com.android.inputmethod.latin.tests.R.raw.dummy_resource_for_testing);
-        mTextsSet.loadStringResourcesInternal(testRes, testResourceNames, testResPackageName);
+        final Context targetContext = getContext();
+        final Resources targetRes = targetContext.getResources();
+        final String targetPackageName = targetRes.getResourcePackageName(
+                R.string.english_ime_name);
+        mTextsSet.setLocale(TEST_LOCALE, targetRes, targetPackageName);
     }
 
-    private static String[] getAllResourceIdNames(final Class<?> resourceIdClass) {
-        final ArrayList<String> names = new ArrayList<>();
-        for (final Field field : resourceIdClass.getFields()) {
-            if (field.getType() == int.class) {
-                names.add(field.getName());
-            }
-        }
-        return names.toArray(new String[names.size()]);
-    }
-
-    private static <T> void assertArrayEquals(final String message, final T[] expected,
-            final T[] actual) {
+    static <T> void assertArrayEquals(final String message, final T[] expected, final T[] actual) {
         if (expected == actual) {
             return;
         }
@@ -109,14 +90,6 @@
     private static final String SURROGATE1 = PAIR1 + PAIR2;
     private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3;
 
-    public void testResolveNullText() {
-        assertNull("resolve null", mTextsSet.resolveTextReference(null));
-    }
-
-    public void testResolveEmptyText() {
-        assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string"));
-    }
-
     public void testSplitZero() {
         assertTextArray("Empty string", "");
         assertTextArray("Empty entry", ",");
@@ -224,132 +197,14 @@
                 "\\!", "\\!TEXT/EMPTY_STRING");
     }
 
-    public void testSplitResourceError() {
-        assertError("Incomplete resource name", "!text/", "!text/");
-        assertError("Non existing resource", "!text/non_existing");
+    public void testSplitTextReferenceError() {
+        assertError("Incomplete text name", "!text/", "!text/");
+        assertError("Non existing text", "!text/non_existing");
     }
 
-    public void testSplitResourceZero() {
-        assertTextArray("Empty string",
-                "!text/empty_string");
-    }
-
-    public void testSplitResourceSingle() {
-        assertTextArray("Single char",
-                "!text/single_char", "a");
-        assertTextArray("Space",
-                "!text/space", " ");
-        assertTextArray("Single label",
-                "!text/single_label", "abc");
-        assertTextArray("Spaces",
-                "!text/spaces", "   ");
-        assertTextArray("Spaces in label",
-                "!text/spaces_in_label", "a b c");
-        assertTextArray("Spaces at beginning of label",
-                "!text/spaces_at_beginning_of_label", " abc");
-        assertTextArray("Spaces at end of label",
-                "!text/spaces_at_end_of_label", "abc ");
-        assertTextArray("label surrounded by spaces",
-                "!text/label_surrounded_by_spaces", " abc ");
-
-        assertTextArray("Escape and single char",
-                "\\\\!text/single_char", "\\\\a");
-    }
-
-    public void testSplitResourceSingleEscaped() {
-        assertTextArray("Escaped char",
-                "!text/escaped_char", "\\a");
-        assertTextArray("Escaped comma",
-                "!text/escaped_comma", "\\,");
-        assertTextArray("Escaped comma escape",
-                "!text/escaped_comma_escape", "a\\,\\");
-        assertTextArray("Escaped escape",
-                "!text/escaped_escape", "\\\\");
-        assertTextArray("Escaped label",
-                "!text/escaped_label", "a\\bc");
-        assertTextArray("Escaped label at beginning",
-                "!text/escaped_label_at_beginning", "\\abc");
-        assertTextArray("Escaped label at end",
-                "!text/escaped_label_at_end", "abc\\");
-        assertTextArray("Escaped label with comma",
-                "!text/escaped_label_with_comma", "a\\,c");
-        assertTextArray("Escaped label with comma at beginning",
-                "!text/escaped_label_with_comma_at_beginning", "\\,bc");
-        assertTextArray("Escaped label with comma at end",
-                "!text/escaped_label_with_comma_at_end", "ab\\,");
-        assertTextArray("Escaped label with successive",
-                "!text/escaped_label_with_successive", "\\,\\\\bc");
-        assertTextArray("Escaped label with escape",
-                "!text/escaped_label_with_escape", "a\\\\c");
-    }
-
-    public void testSplitResourceMulti() {
-        assertTextArray("Multiple chars",
-                "!text/multiple_chars", "a", "b", "c");
-        assertTextArray("Multiple chars surrounded by spaces",
-                "!text/multiple_chars_surrounded_by_spaces",
-                " a ", " b ", " c ");
-        assertTextArray("Multiple labels",
-                "!text/multiple_labels", "abc", "def", "ghi");
-        assertTextArray("Multiple labels surrounded by spaces",
-                "!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
-    }
-
-    public void testSplitResourcetMultiEscaped() {
-        assertTextArray("Multiple chars with comma",
-                "!text/multiple_chars_with_comma",
-                "a", "\\,", "c");
-        assertTextArray("Multiple chars with comma surrounded by spaces",
-                "!text/multiple_chars_with_comma_surrounded_by_spaces",
-                " a ", " \\, ", " c ");
-        assertTextArray("Multiple labels with escape",
-                "!text/multiple_labels_with_escape",
-                "\\abc", "d\\ef", "gh\\i");
-        assertTextArray("Multiple labels with escape surrounded by spaces",
-                "!text/multiple_labels_with_escape_surrounded_by_spaces",
-                " \\abc ", " d\\ef ", " gh\\i ");
-        assertTextArray("Multiple labels with comma and escape",
-                "!text/multiple_labels_with_comma_and_escape",
-                "ab\\\\", "d\\\\\\,", "g\\,i");
-        assertTextArray("Multiple labels with comma and escape surrounded by spaces",
-                "!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
-                " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
-    }
-
-    public void testSplitMultipleResources() {
-        assertTextArray("Literals and resources",
-                "1,!text/multiple_chars,z", "1", "a", "b", "c", "z");
-        assertTextArray("Literals and resources and escape at end",
-                "\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\");
-        assertTextArray("Multiple single resource chars and labels",
-                "!text/single_char,!text/single_label,!text/escaped_comma",
-                "a", "abc", "\\,");
-        assertTextArray("Multiple single resource chars and labels 2",
-                "!text/single_char,!text/single_label,!text/escaped_comma_escape",
-                "a", "abc", "a\\,\\");
-        assertTextArray("Multiple multiple resource chars and labels",
-                "!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma",
-                "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
-        assertTextArray("Concatenated resources",
-                "!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma",
-                "a", "b", "cabc", "def", "ghia", "\\,", "c");
-        assertTextArray("Concatenated resource and literal",
-                "abc!text/multiple_labels",
-                "abcabc", "def", "ghi");
-    }
-
-    public void testSplitIndirectReference() {
-        assertTextArray("Indirect",
-                "!text/indirect_string", "a", "b", "c");
-        assertTextArray("Indirect with literal",
-                "1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
-        assertTextArray("Indirect2",
-                "!text/indirect2_string", "a", "b", "c");
-    }
-
-    public void testSplitInfiniteIndirectReference() {
-        assertError("Infinite indirection",
-                "1,!text/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
+    public void testSplitEmptyTextReference() {
+        // Note that morekeys_q of English locale is empty.
+        assertTextArray("Empty string", "!text/morekeys_q");
     }
 
     public void testLabelReferece() {
@@ -360,12 +215,6 @@
 
         assertTextArray("Settings as more key", "!text/keyspec_settings",
                 "!icon/settings_key|!code/key_settings");
-
-        assertTextArray("Indirect naviagte actions as more key",
-                "!text/keyspec_indirect_navigate_actions",
-                "!fixedColumnOrder!2",
-                "!hasLabels!", "Prev|!code/key_action_previous",
-                "!hasLabels!", "Next|!code/key_action_next");
     }
 
     public void testUselessUpperCaseSpecifier() {
@@ -394,14 +243,6 @@
         assertTextArray("INDIRECT2",
                 "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING");
 
-        assertTextArray("Upper indirect",
-                "!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS");
-        assertTextArray("Upper indirect with literal",
-                "1,!text/upper_indirect_string_with_literal,2",
-                "1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2");
-        assertTextArray("Upper indirect2",
-                "!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING");
-
         assertTextArray("UPPER INDIRECT",
                 "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING");
         assertTextArray("Upper INDIRECT with literal",
@@ -413,9 +254,6 @@
         assertTextArray("INFINITE INDIRECTION",
                 "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2");
 
-        assertTextArray("Upper infinite indirection",
-                "1,!text/upper_infinite_indirection,2",
-                "1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2");
         assertTextArray("Upper INFINITE INDIRECTION",
                 "1,!TEXT/UPPER_INFINITE_INDIRECTION,2",
                 "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2");
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecStringReferenceTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecStringReferenceTests.java
new file mode 100644
index 0000000..e06ecae
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecStringReferenceTests.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2014 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.internal;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.tests.R;
+
+import java.util.Locale;
+
+@SmallTest
+public class MoreKeySpecStringReferenceTests extends InstrumentationTestCase {
+    private static final Locale TEST_LOCALE = Locale.ENGLISH;
+    private final KeyboardTextsSet mTextsSet = new KeyboardTextsSet();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        final Instrumentation instrumentation = getInstrumentation();
+        final Context testContext = instrumentation.getContext();
+        final Resources testRes = testContext.getResources();
+        final String testPackageName = testRes.getResourcePackageName(R.string.empty_string);
+        mTextsSet.setLocale(TEST_LOCALE, testRes, testPackageName);
+    }
+
+    private void assertTextArray(final String message, final String value,
+            final String ... expectedArray) {
+        final String resolvedActual = mTextsSet.resolveTextReference(value);
+        final String[] actual = MoreKeySpec.splitKeySpecs(resolvedActual);
+        final String[] expected = (expectedArray.length == 0) ? null : expectedArray;
+        MoreKeySpecSplitTests.assertArrayEquals(message, expected, actual);
+    }
+
+    private void assertError(final String message, final String value, final String ... expected) {
+        try {
+            assertTextArray(message, value, expected);
+            fail(message);
+        } catch (Exception pcpe) {
+            // success.
+        }
+    }
+
+    public void testResolveNullText() {
+        assertEquals("resolve null",
+                mTextsSet.resolveTextReference(null), null);
+    }
+
+    public void testResolveEmptyText() {
+        assertEquals("resolve empty text",
+                mTextsSet.resolveTextReference("!string/empty_string"), null);
+    }
+
+    public void testSplitSingleEscaped() {
+        assertTextArray("Escaped !string", "\\!string",
+                "\\!string");
+        assertTextArray("Escaped !string/", "\\!string/",
+                "\\!string/");
+        assertTextArray("Escaped !STRING/", "\\!STRING/",
+                "\\!STRING/");
+        assertTextArray("Escaped !string/name", "\\!string/empty_string",
+                "\\!string/empty_string");
+        assertTextArray("Escaped !STRING/NAME", "\\!STRING/EMPTY_STRING",
+                "\\!STRING/EMPTY_STRING");
+    }
+
+    public void testSplitMultiEscaped() {
+        assertTextArray("Multiple escaped !string", "\\!,\\!string/empty_string",
+                "\\!", "\\!string/empty_string");
+        assertTextArray("Multiple escaped !STRING", "\\!,\\!STRING/EMPTY_STRING",
+                "\\!", "\\!STRING/EMPTY_STRING");
+    }
+
+    public void testSplitStringReferenceError() {
+        assertError("Incomplete resource name", "!string/", "!string/");
+        assertError("Non existing resource", "!string/non_existing");
+    }
+
+    public void testSplitEmptyStringReference() {
+        assertTextArray("Empty string", "!string/empty_string");
+    }
+
+    public void testSplitResourceSingle() {
+        assertTextArray("Single char", "!string/single_char",
+                "a");
+        assertTextArray("Space", "!string/space",
+                " ");
+        assertTextArray("Single label", "!string/single_label",
+                "abc");
+        assertTextArray("Spaces", "!string/spaces",
+                "   ");
+        assertTextArray("Spaces in label", "!string/spaces_in_label",
+                "a b c");
+        assertTextArray("Spaces at beginning of label", "!string/spaces_at_beginning_of_label",
+                " abc");
+        assertTextArray("Spaces at end of label", "!string/spaces_at_end_of_label",
+                "abc ");
+        assertTextArray("label surrounded by spaces", "!string/label_surrounded_by_spaces",
+                " abc ");
+        assertTextArray("Escape and single char", "\\\\!string/single_char",
+                "\\\\a");
+    }
+
+    public void testSplitResourceSingleEscaped() {
+        assertTextArray("Escaped char",
+                "!string/escaped_char", "\\a");
+        assertTextArray("Escaped comma",
+                "!string/escaped_comma", "\\,");
+        assertTextArray("Escaped comma escape",
+                "!string/escaped_comma_escape", "a\\,\\");
+        assertTextArray("Escaped escape",
+                "!string/escaped_escape", "\\\\");
+        assertTextArray("Escaped label",
+                "!string/escaped_label", "a\\bc");
+        assertTextArray("Escaped label at beginning",
+                "!string/escaped_label_at_beginning", "\\abc");
+        assertTextArray("Escaped label at end",
+                "!string/escaped_label_at_end", "abc\\");
+        assertTextArray("Escaped label with comma",
+                "!string/escaped_label_with_comma", "a\\,c");
+        assertTextArray("Escaped label with comma at beginning",
+                "!string/escaped_label_with_comma_at_beginning", "\\,bc");
+        assertTextArray("Escaped label with comma at end",
+                "!string/escaped_label_with_comma_at_end", "ab\\,");
+        assertTextArray("Escaped label with successive",
+                "!string/escaped_label_with_successive", "\\,\\\\bc");
+        assertTextArray("Escaped label with escape",
+                "!string/escaped_label_with_escape", "a\\\\c");
+    }
+
+    public void testSplitResourceMulti() {
+        assertTextArray("Multiple chars",
+                "!string/multiple_chars", "a", "b", "c");
+        assertTextArray("Multiple chars surrounded by spaces",
+                "!string/multiple_chars_surrounded_by_spaces",
+                " a ", " b ", " c ");
+        assertTextArray("Multiple labels",
+                "!string/multiple_labels", "abc", "def", "ghi");
+        assertTextArray("Multiple labels surrounded by spaces",
+                "!string/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi ");
+    }
+
+    public void testSplitResourcetMultiEscaped() {
+        assertTextArray("Multiple chars with comma",
+                "!string/multiple_chars_with_comma",
+                "a", "\\,", "c");
+        assertTextArray("Multiple chars with comma surrounded by spaces",
+                "!string/multiple_chars_with_comma_surrounded_by_spaces",
+                " a ", " \\, ", " c ");
+        assertTextArray("Multiple labels with escape",
+                "!string/multiple_labels_with_escape",
+                "\\abc", "d\\ef", "gh\\i");
+        assertTextArray("Multiple labels with escape surrounded by spaces",
+                "!string/multiple_labels_with_escape_surrounded_by_spaces",
+                " \\abc ", " d\\ef ", " gh\\i ");
+        assertTextArray("Multiple labels with comma and escape",
+                "!string/multiple_labels_with_comma_and_escape",
+                "ab\\\\", "d\\\\\\,", "g\\,i");
+        assertTextArray("Multiple labels with comma and escape surrounded by spaces",
+                "!string/multiple_labels_with_comma_and_escape_surrounded_by_spaces",
+                " ab\\\\ ", " d\\\\\\, ", " g\\,i ");
+    }
+
+    public void testSplitMultipleResources() {
+        assertTextArray("Literals and resources",
+                "1,!string/multiple_chars,z",
+                "1", "a", "b", "c", "z");
+        assertTextArray("Literals and resources and escape at end",
+                "\\1,!string/multiple_chars,z\\",
+                "\\1", "a", "b", "c", "z\\");
+        assertTextArray("Multiple single resource chars and labels",
+                "!string/single_char,!string/single_label,!string/escaped_comma",
+                "a", "abc", "\\,");
+        assertTextArray("Multiple single resource chars and labels 2",
+                "!string/single_char,!string/single_label,!string/escaped_comma_escape",
+                "a", "abc", "a\\,\\");
+        assertTextArray("Multiple multiple resource chars and labels",
+                "!string/multiple_chars,!string/multiple_labels,!string/multiple_chars_with_comma",
+                "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c");
+        assertTextArray("Concatenated resources",
+                "!string/multiple_chars!string/multiple_labels!string/multiple_chars_with_comma",
+                "a", "b", "cabc", "def", "ghia", "\\,", "c");
+        assertTextArray("Concatenated resource and literal",
+                "abc!string/multiple_labels",
+                "abcabc", "def", "ghi");
+    }
+
+    public void testSplitIndirectReference() {
+        assertTextArray("Indirect",
+                "!string/indirect_string", "a", "b", "c");
+        assertTextArray("Indirect with literal",
+                "1,!string/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2");
+        assertTextArray("Indirect2",
+                "!string/indirect2_string", "a", "b", "c");
+    }
+
+    public void testSplitInfiniteIndirectReference() {
+        assertError("Infinite indirection",
+                "1,!string/infinite_indirection,2", "1", "infinite", "<infinite>", "loop", "2");
+    }
+
+    public void testLabelReferece() {
+        assertTextArray("Indirect naviagte actions as more key",
+                "!string/keyspec_indirect_navigate_actions",
+                "!fixedColumnOrder!2",
+                "!hasLabels!", "ActionPrevious|!code/key_action_previous",
+                "!hasLabels!", "ActionNext|!code/key_action_next");
+    }
+
+    public void testUselessUpperCaseSpecifier() {
+        assertTextArray("EMPTY STRING",
+                "!STRING/EMPTY_STRING", "!STRING/EMPTY_STRING");
+
+        assertTextArray("SINGLE CHAR",
+                "!STRING/SINGLE_CHAR", "!STRING/SINGLE_CHAR");
+        assertTextArray("Escape and SINGLE CHAR",
+                "\\\\!STRING/SINGLE_CHAR", "\\\\!STRING/SINGLE_CHAR");
+
+        assertTextArray("MULTIPLE CHARS",
+                "!STRING/MULTIPLE_CHARS", "!STRING/MULTIPLE_CHARS");
+
+        assertTextArray("Literals and RESOURCES",
+                "1,!STRING/MULTIPLE_CHARS,z", "1", "!STRING/MULTIPLE_CHARS", "z");
+        assertTextArray("Multiple single RESOURCE chars and LABELS 2",
+                "!STRING/SINGLE_CHAR,!STRING/SINGLE_LABEL,!STRING/ESCAPED_COMMA_ESCAPE",
+                "!STRING/SINGLE_CHAR", "!STRING/SINGLE_LABEL", "!STRING/ESCAPED_COMMA_ESCAPE");
+
+        assertTextArray("INDIRECT",
+                "!STRING/INDIRECT_STRING", "!STRING/INDIRECT_STRING");
+        assertTextArray("INDIRECT with literal",
+                "1,!STRING/INDIRECT_STRING_WITH_LITERAL,2",
+                "1", "!STRING/INDIRECT_STRING_WITH_LITERAL", "2");
+        assertTextArray("INDIRECT2",
+                "!STRING/INDIRECT2_STRING", "!STRING/INDIRECT2_STRING");
+
+        assertTextArray("Upper indirect",
+                "!string/upper_indirect_string", "!STRING/MULTIPLE_CHARS");
+        assertTextArray("Upper indirect with literal",
+                "1,!string/upper_indirect_string_with_literal,2",
+                "1", "x", "!STRING/MULTIPLE_CHARS", "y", "2");
+        assertTextArray("Upper indirect2",
+                "!string/upper_indirect2_string", "!STRING/UPPER_INDIRECT_STRING");
+
+        assertTextArray("UPPER INDIRECT",
+                "!STRING/upper_INDIRECT_STRING", "!STRING/upper_INDIRECT_STRING");
+        assertTextArray("Upper INDIRECT with literal",
+                "1,!STRING/upper_INDIRECT_STRING_WITH_LITERAL,2",
+                "1", "!STRING/upper_INDIRECT_STRING_WITH_LITERAL", "2");
+        assertTextArray("Upper INDIRECT2",
+                "!STRING/upper_INDIRECT2_STRING", "!STRING/upper_INDIRECT2_STRING");
+
+        assertTextArray("INFINITE INDIRECTION",
+                "1,!STRING/INFINITE_INDIRECTION,2", "1", "!STRING/INFINITE_INDIRECTION", "2");
+
+        assertTextArray("Upper infinite indirection",
+                "1,!string/upper_infinite_indirection,2",
+                "1", "infinite", "!STRING/INFINITE_INDIRECTION", "loop", "2");
+        assertTextArray("Upper INFINITE INDIRECTION",
+                "1,!STRING/UPPER_INFINITE_INDIRECTION,2",
+                "1", "!STRING/UPPER_INFINITE_INDIRECTION", "2");
+
+        assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY",
+                "!STRING/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY",
+                "!STRING/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY");
+     }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
index 6c0d749..d9e5d10 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java
@@ -17,11 +17,11 @@
 package com.android.inputmethod.keyboard.internal;
 
 import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED;
-import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED;
+import static com.android.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
 
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Arrays;
 import java.util.Locale;
@@ -78,6 +78,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testEmptyEntry() {
         assertInsertAdditionalMoreKeys("null more keys and null additons",
                 null,
@@ -106,6 +107,7 @@
                 new String[] { "a", "A", "b", "B", "c", "d" });
     }
 
+    @SuppressWarnings("static-method")
     public void testInsertAdditionalMoreKeys() {
         // Escaped marker.
         assertInsertAdditionalMoreKeys("escaped marker",
@@ -306,6 +308,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testGetBooleanValue() {
         assertGetBooleanValue("Has label", HAS_LABEL,
                 new String[] { HAS_LABEL, "a", "b", "c" },
@@ -345,6 +348,7 @@
         assertArrayEquals(message, expected, actual);
     }
 
+    @SuppressWarnings("static-method")
     public void testGetIntValue() {
         assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1,
                 new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" },
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Arabic.java b/tests/src/com/android/inputmethod/keyboard/layout/Arabic.java
index 3f85e4b..ff05f92 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Arabic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Arabic.java
@@ -18,26 +18,25 @@
 
 import com.android.inputmethod.keyboard.layout.Symbols.RtlSymbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted.RtlSymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
 public final class Arabic extends LayoutBase {
     private static final String LAYOUT_NAME = "arabic";
 
-    public Arabic(final LayoutCustomizer customizer) {
-        super(customizer, ArabicSymbols.class, ArabicSymbolsShifted.class);
+    public Arabic(final Locale locale) {
+        super(new ArabicCustomizer(locale), ArabicSymbols.class, ArabicSymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class ArabicCustomizer extends LayoutCustomizer {
-        public ArabicCustomizer(final Locale locale) {
-            super(locale);
-        }
+    private static class ArabicCustomizer extends LayoutCustomizer {
+        ArabicCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return ARABIC_ALPHABET_KEY; }
@@ -141,12 +140,11 @@
     ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) {
         if (isPhone) {
             return ALPHABET_COMMON;
-        } else {
-            final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON);
-            // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
-            builder.insertKeysAtRow(3, 2, "\u0626");
-            return builder.build();
         }
+        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON);
+        // U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE
+        builder.insertKeysAtRow(3, 2, "\u0626");
+        return builder.build();
     }
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
index 2cecedc..cbbeff4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/ArmenianPhonetic.java
@@ -16,9 +16,10 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -28,15 +29,16 @@
 public final class ArmenianPhonetic extends LayoutBase {
     private static final String LAYOUT_NAME = "armenian_phonetic";
 
-    public ArmenianPhonetic(final LayoutCustomizer customizer) {
-        super(customizer, ArmenianSymbols.class, ArmenianSymbolsShifted.class);
+    public ArmenianPhonetic(final Locale locale) {
+        super(new ArmenianPhoneticCustomizer(locale), ArmenianSymbols.class,
+                ArmenianSymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class ArmenianPhoneticCustomizer extends LayoutCustomizer {
-        public ArmenianPhoneticCustomizer(final Locale locale) { super(locale); }
+    private static class ArmenianPhoneticCustomizer extends LayoutCustomizer {
+        ArmenianPhoneticCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public int getNumberOfRows() { return 5; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Azerty.java b/tests/src/com/android/inputmethod/keyboard/layout/Azerty.java
index a094963..f3176d0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Azerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Azerty.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java b/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
index 2101ddf..339cab4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Bengali.java
@@ -16,11 +16,9 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 /**
  * The Bengali keyboard.
@@ -35,32 +33,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class BengaliCustomizer extends LayoutCustomizer {
-        public BengaliCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return BENGALI_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
-        }
-
-        @Override
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { return EMPTY_KEYS; }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0995: "क" BENGALI LETTER KA
-        // U+0996: "ख" BENGALI LETTER KHA
-        // U+0997: "ग" BENGALI LETTER GA
-        private static final ExpectedKey BENGALI_ALPHABET_KEY = key(
-                "\u0995\u0996\u0997", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java b/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java
new file mode 100644
index 0000000..bb1dc10
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/BengaliAkkhor.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2014 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.layout;
+
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+/**
+ * The Bengali Akkhor keyboard.
+ */
+public final class BengaliAkkhor extends LayoutBase {
+    private static final String LAYOUT_NAME = "bengali_akkhor";
+
+    public BengaliAkkhor(final LayoutCustomizer customizer) {
+        super(customizer, Symbols.class, SymbolsShifted.class);
+    }
+
+    @Override
+    public String getName() { return LAYOUT_NAME; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetShiftLayout(boolean isPhone, final int elementId) {
+        if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
+            return getCommonAlphabetLayout(isPhone);
+        }
+        return ALPHABET_SHIFTED_COMMON;
+    }
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    // U+09A7: "ধ" BENGALI LETTER DHA
+                    // U+09E7: "১" BENGALI DIGIT ONE
+                    // U+09A7/U+09CD/U+09AC:
+                    //     "ধ্ব্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A7/U+09CD/U+09AF:
+                    //     "ধ্য্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A7/U+09CD/U+09B0:
+                    //     "ধ্র" BENGALI LETTER DHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A7", joinMoreKeys("\u09E7", "\u09A7\u09CD\u09AC", "\u09A7\u09CD\u09AF",
+                            "\u09A7\u09CD\u09B0")),
+                    // U+09A5: "থ" BENGALI LETTER THA
+                    // U+09E8: "২" BENGALI DIGIT TWO
+                    // U+09A5/U+09CD/U+09AF:
+                    //     "থ্য" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A5/U+09CD/U+09B0:
+                    //     "থ্র" BENGALI LETTER THA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A5", joinMoreKeys("\u09E8", "\u09A5\u09CD\u09AF",
+                            "\u09A5\u09CD\u09B0")),
+                    // U+09C7: "ে" BENGALI VOWEL SIGN E
+                    // U+09E9: "৩" BENGALI DIGIT THREE
+                    // U+098F: "এ" BENGALI LETTER E
+                    key("\u09C7", joinMoreKeys("\u09E9", "\u098F")),
+                    // U+09B0: "র" BENGALI LETTER RA
+                    // U+09EA: "৪" BENGALI DIGIT FOUR
+                    key("\u09B0", joinMoreKeys("\u09EA")),
+                    // U+09A4: "ত" BENGALI LETTER TA
+                    // U+09EB: "৫" BENGALI DIGIT FIVE
+                    // U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                    // U+09A4/U+09CD/U+09A4:
+                    //     "ত্ত" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09A4/U+09CD/U+09A8:
+                    //     "ত্ন" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09A4/U+09CD/U+09AC:
+                    //     "ত্ব" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A4/U+09CD/U+09AE:
+                    //     "ত্ম" BENGALI LETTER TA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u09A4", joinMoreKeys("\u09EB", "\u09CE", "\u09A4\u09CD\u09A4",
+                            "\u09A4\u09CD\u09A8", "\u09A4\u09CD\u09AC", "\u09A4\u09CD\u09AE")),
+                    // U+09DF: "য়" BENGALI LETTER YYA
+                    // U+09EC: "৬" BENGALI DIGIT SIX
+                    key("\u09DF", joinMoreKeys("\u09EC")),
+                    // U+09C1: "ু" BENGALI VOWEL SIGN U
+                    // U+09ED: "৭" BENGALI DIGIT SEVEN
+                    // U+0989: "উ" BENGALI LETTER U
+                    key("\u09C1", joinMoreKeys("\u09ED", "\u0989")),
+                    // U+09BF: "ি" BENGALI VOWEL SIGN I
+                    // U+09EE: "৮" BENGALI DIGIT EIGHT
+                    // U+0987: "ই BENGALI LETTER I
+                    key("\u09Bf", joinMoreKeys("\u09EE", "\u0987")),
+                    // U+09CB: "ো" BENGALI VOWEL SIGN O
+                    // U+09EF: "৯" BENGALI DIGIT NINE
+                    // U+0993: "ও" BENGALI LETTER O
+                    key("\u09CB", joinMoreKeys("\u09EF", "\u0993")),
+                    // U+09AA: "প" BENGALI LETTER PA
+                    // U+09E6: "০" BENGALI DIGIT ZERO
+                    // U+09AA/U+09CD/U+09A4:
+                    //     "প্ত" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09AA/U+09CD/U+09A8:
+                    //     "প্ন" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09AA/U+09CD/U+09AA:
+                    //     "প্প" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09AA/U+09CD/U+09AF:
+                    //     "প্য" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AA/U+09CD/U+09B0:
+                    //     "প্র" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AA/U+09CD/U+09B2:
+                    //     "প্ল" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+09AA/U+09CD/U+09B8:
+                    //     "প্স" BENGALI LETTER PA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    key("\u09AA", joinMoreKeys("\u09E6", "\u09AA\u09CD\u09A4", "\u09AA\u09CD\u09A8",
+                            "\u09AA\u09CD\u09AA", "\u09AA\u09CD\u09AF", "\u09AA\u09CD\u09B0",
+                            "\u09AA\u09CD\u09B2", "\u09AA\u09CD\u09B8")),
+                    // U+0986: "আ" BENGALI LETTER AA
+                    key("\u0986"))
+            .setKeysOfRow(2,
+                    // U+09BE: "া BENGALI VOWEL SIGN AA
+                    // U+0986: "আ" BENGALI LETTER AA
+                    key("\u09BE", moreKey("\u0986")),
+                    // U+09B8: "স" BENGALI LETTER SA
+                    // U+09B8/U+09CD/U+09AC:
+                    //     "স্ব" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B8/U+09CD/U+09A4:
+                    //     "স্ত" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B8/U+09CD/U+099F:
+                    //     "স্ট" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B8/U+09CD/U+0995:
+                    //     "স্ক" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B8/U+09CD/U+09AA:
+                    //     "স্প" BENGALI LETTER SA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    key("\u09B8", joinMoreKeys("\u09B8\u09CD\u09AC", "\u09B8\u09CD\u09A4",
+                            "\u09B8\u09CD\u099F", "\u09B8\u09CD\u0995", "\u09B8\u09CD\u09AA")),
+                    // U+09A6: "দ" BENGALI LETTER DA
+                    // U+09A6/U+09CD/U+09A6:
+                    //     "দ্দ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09A6/U+09CD/U+09A7:
+                    //     "দ্ধ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09A6/U+09CD/U+09AC:
+                    //     "দ্ব" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A6/U+09CD/U+09AD:
+                    //     "দ্ভ" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                    // U+09A6/U+09CD/U+09AE:
+                    //     "দ্ম" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09A6/U+09CD/U+09AF:
+                    //     "দ্য" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09A6/U+09CD/U+09B0:
+                    //     "দ্র" BENGALI LETTER DA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u09A6", joinMoreKeys("\u09A6\u09CD\u09A6", "\u09A6\u09CD\u09A7",
+                            "\u09A6\u09CD\u09AC", "\u09A6\u09CD\u09AD", "\u09A6\u09CD\u09AE",
+                            "\u09A6\u09CD\u09AF", "\u09A6\u09CD\u09B0")),
+                    // U+09C3: "ৃ" BENGALI VOWEL SIGN VOCALIC R
+                    // U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                    key("\u09C3", moreKey("\u098B")),
+                    // U+0997: "গ" BENGALI LETTER GA
+                    // U+0997/U+09CD/U+09A7:
+                    //     "গ্ধ" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER DH A
+                    // U+0997/U+09CD/U+09B0:
+                    //     "গ্র" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+0997/U+09CD/U+09B2:
+                    //     "গ্ল" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+0997/U+09CD/U+09A8:
+                    //     "গ্ন" BENGALI LETTER GA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    key("\u0997", joinMoreKeys("\u0997\u09CD\u09A7", "\u0997\u09CD\u09B0",
+                            "\u0997\u09CD\u09B2", "\u0997\u09CD\u09A8")),
+                    // U+09CD: "্" BENGALI SIGN VIRAMA
+                    key("\u09CD"),
+                    // U+099C: "জ" BENGALI LETTER JA
+                    // U+099C/U+09CD/U+099E:
+                    //     "জ্ঞ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER NYA
+                    // U+099C/U+09CD/U+099C:
+                    //     "জ্জ" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    // U+099C/U+09CD/U+09AF:
+                    //     "জ্ব" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+099C/U+09CD/U+09AC:
+                    //     "জ্য" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+099C/U+09CD/U+09B0:
+                    //     "জ্র" BENGALI LETTER JA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    key("\u099C", joinMoreKeys("\u099C\u09CD\u099E", "\u099C\u09CD\u099C",
+                            "\u099C\u09CD\u09AF", "\u099C\u09CD\u09AC", "\u099C\u09CD\u09B0")),
+                    // U+0995: "ক" BENGALI LETTER KA
+                    // U+0995/U+09CD/U+09B7:
+                    //     "ক্ষ" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SSA
+                    // U+0995/U+09CD/U+0995:
+                    //     "ক্ক" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+0995/U+09CD/U+099F:
+                    //     "ক্ট" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+0995/U+09CD/U+09A4:
+                    //     "ক্ত" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+0995/U+09CD/U+09B0:
+                    //     "ক্র" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+0995/U+09CD/U+09B8:
+                    //     "ক্স" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    // U+0995/U+09CD/U+09B2:
+                    //     "ক্ল" BENGALI LETTER KA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u0995", joinMoreKeys("\u0995\u09CD\u09B7", "\u0995\u09CD\u0995",
+                            "\u0995\u09CD\u099F", "\u0995\u09CD\u09A4", "\u0995\u09CD\u09B0",
+                            "\u0995\u09CD\u09B8", "\u0995\u09CD\u09B2")),
+                    // U+09B2: "ল" BENGALI LETTER LA
+                    // U+09B2/U+09CD/U+0995:
+                    //     "ল্ক" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B2/U+09CD/U+0997:
+                    //     "ল্গ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER GA
+                    // U+09B2/U+09CD/U+099F:
+                    //     "ল্ট" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B2/U+09CD/U+09A1:
+                    //     "ল্ড" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09B2/U+09CD/U+09A4:
+                    //     "ল্ত" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B2/U+09CD/U+09A6:
+                    //     "ল্দ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09B2/U+09CD/U+09A7:
+                    //     "ল্ধ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09B2/U+09CD/U+09AA:
+                    //     "ল্প" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09B2/U+09CD/U+09AB:
+                    //     "ল্ফ" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                    // U+09B2/U+09CD/U+09AC:
+                    //     "ল্ব" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B2/U+09CD/U+09AE:
+                    //     "ল্ম" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B2/U+09CD/U+09B2:
+                    //     "ল্ল" BENGALI LETTER LA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B2", joinMoreKeys("\u09B2\u09CD\u0995", "\u09B2\u09CD\u0997",
+                            "\u09B2\u09CD\u099F", "\u09B2\u09CD\u09A1", "\u09B2\u09CD\u09A4",
+                            "\u09B2\u09CD\u09A6", "\u09B2\u09CD\u09A7", "\u09B2\u09CD\u09AA",
+                            "\u09B2\u09CD\u09AB", "\u09B2\u09CD\u09AC", "\u09B2\u09CD\u09AE",
+                            "\u09B2\u09CD\u09B2")),
+                    // U+0987: "ই" BENGALI LETTER I
+                    key("\u0987"),
+                    // U+0989: "উ" BENGALI LETTER U
+                    key("\u0989"))
+            .setKeysOfRow(3,
+                    // U+09AF: "য" BENGALI LETTER YA
+                    // U+09CD/U+09AF: "্য" BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    key("\u09AF", moreKey("\u09CD\u09AF")),
+                    // U+09B7: "ষ" BENGALI LETTER SSA
+                    // U+09B7/U+09CD/U+0995:
+                    //     "ষ্ক" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER KA
+                    // U+09B7/U+09CD/U+099F:
+                    //     "ষ্ট" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09B7/U+09CD/U+09A0:
+                    //     "ষ্ঠ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER TTHA
+                    // U+09B7/U+09CD/U+09A3:
+                    //     "ষ্ণ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                    // U+09B7/U+09CD/U+09AA:
+                    //     "ষ্প" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09B7/U+09CD/U+09AB:
+                    //     "ষ্ফ" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER PHA
+                    // U+09B7/U+09CD/U+09AE:
+                    //     "ষ্ম" BENGALI LETTER SSA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u09B7", joinMoreKeys("\u09B7\u09CD\u0995", "\u09B7\u09CD\u099F",
+                            "\u09B7\u09CD\u09A0", "\u09B7\u09CD\u09A3", "\u09B7\u09CD\u09AA",
+                            "\u09B7\u09CD\u09AB", "\u09B7\u09CD\u09AE")),
+                    // U+099A: "চ" BENGALI LETTER CA
+                    // U+099A/U+09CD/U+099A:
+                    //     "চ্চ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+099A/U+09CD/U+099B:
+                    //     "চ্ছ" BENGALI LETTER CA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    key("\u099A", joinMoreKeys("\u099A\u09CD\u099A", "\u099A\u09CD\u099B")),
+                    // U+09AD: "ভ" BENGALI LETTER BHA
+                    // U+09AD/U+09CD/U+09AF:
+                    //     "ভ্" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AD/U+09CD/U+09B0:
+                    //     "ভ্র" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AD/U+09CD/U+09B2:
+                    //     "ভ্ল" BENGALI LETTER BHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AD", joinMoreKeys("\u09AD\u09CD\u09AF", "\u09AD\u09CD\u09B0",
+                            "\u09AD\u09CD\u09B2")),
+                    // U+09AC: "ব" BENGALI LETTER BA
+                    // U+09CD/U+09AC: "্ব" BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AC/U+09CD/U+09B0:
+                    //     "ব্র" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AC/U+09CD/U+099C:
+                    //     "ব্জ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    // U+09AC/U+09CD/U+09A6:
+                    //     "ব্দ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09AC/U+09CD/U+09A7:
+                    //     "ব্ধ" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09AC/U+09CD/U+09AC:
+                    //     "ব্ব" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AC/U+09CD/U+09B2:
+                    //     "ব্ল" BENGALI LETTER BA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    // U+09F1: "ৱ" BENGALI LETTER RA WITH MIDDLE DIAGONAL
+                    // U+09F0: "ৰ" BENGALI LETTER RA WITH LOWER DIAGONAL
+                    key("\u09AC", joinMoreKeys("\u09CD\u09AC", "\u09AC\u09CD\u09B0",
+                            "\u09AC\u09CD\u099C", "\u09AC\u09CD\u09A6", "\u09AC\u09CD\u09A7",
+                            "\u09AC\u09CD\u09AC", "\u09AC\u09CD\u09B2", "\u09F1", "\u09F0")),
+                    // U+09A8: "ন" BENGALI LETTER NA
+                    // U+09A8/U+09CD/U+09A4:
+                    //     "ন্ত" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09A8/U+09CD/U+09A5:
+                    //     "ন্থ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER THA
+                    // U+09A8/U+09CD/U+099F:
+                    //     "ন্ট" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09A8/U+09CD/U+09A6:
+                    //     "ন্দ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DA
+                    // U+09A8/U+09CD/U+09A7:
+                    //     "ন্ধ" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DHA
+                    // U+09A8/U+09CD/U+09A1:
+                    //     "ন্ড" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09A8/U+09CD/U+09A8:
+                    //     "ন্ন" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09A8/U+09CD/U+09AC:
+                    //     "ন্ব" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09A8/U+09CD/U+09AE:
+                    //     "ন্ম" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09A8/U+09CD/U+09B8:
+                    //     "ন্স" BENGALI LETTER NA/BENGALI SIGN VIRAMA/BENGALI LETTER SA
+                    key("\u09A8", joinMoreKeys("\u09A8\u09CD\u09A4", "\u09A8\u09CD\u09A5",
+                            "\u09A8\u09CD\u099F", "\u09A8\u09CD\u09A6", "\u09A8\u09CD\u09A7",
+                            "\u09A8\u09CD\u09A1", "\u09A8\u09CD\u09A8", "\u09A8\u09CD\u09AC",
+                            "\u09A8\u09CD\u09AE", "\u09A8\u09CD\u09B8")),
+                    // U+09AE: "ম" BENGALI LETTER MA
+                    // U+09AE/U+09CD/U+09A8:
+                    //     "ম্ন" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09AE/U+09CD/U+09AA:
+                    //     "ম্প" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER PA
+                    // U+09AE/U+09CD/U+09AC:
+                    //     "ম্ব" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09AE/U+09CD/U+09AD:
+                    //     "ম্ভ" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER BHA
+                    // U+09AE/U+09CD/U+09AE:
+                    //     "ম্ম" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09AE/U+09CD/U+09B0:
+                    //     "ম্র" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AE/U+09CD/U+09B2:
+                    //     "ম্ল" BENGALI LETTER MA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AE", joinMoreKeys("\u09AE\u09CD\u09A8", "\u09AE\u09CD\u09AA",
+                            "\u09AE\u09CD\u09AC", "\u09AE\u09CD\u09AD", "\u09AE\u09CD\u09AE",
+                            "\u09AE\u09CD\u09B0", "\u09AE\u09CD\u09B2")),
+                    // U+098F: "এ" BENGALI LETTER E
+                    key("\u098F"),
+                    // U+0993: "ও" BENGALI LETTER O
+                    key("\u0993"))
+            .build();
+
+    private static final ExpectedKey[][] ALPHABET_SHIFTED_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    // U+09A2: "ঢ" BENGALI LETTER DDHA
+                    key("\u09A2"),
+                    // U+09A0: "ঠ" BENGALI LETTER TTHA
+                    key("\u09A0"),
+                    // U+09C8: "ৈ" BENGALI VOWEL SIGN AI
+                    // U+0990: "ঐ" BENGALI LETTER AI
+                    key("\u09C8", moreKey("\u0990")),
+                    // U+09DC: "ড়" BENGALI LETTER RRA
+                    // U+09BC: "়" BENGALI SIGN NUKTA
+                    key("\u09DC", moreKey("\u09BC")),
+                    // U+099F: "ট" BENGALI LETTER TTA
+                    // U+09F3: "৳" BENGALI RUPEE SIGN
+                    // U+099F/U+09CD/U+099F:
+                    //     "ট্ট" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+099F/U+09CD/U+09AC:
+                    //     "ট্ব" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+099F/U+09CD/U+09AE:
+                    //     "ট্ম" BENGALI LETTER TTA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    key("\u099F", joinMoreKeys("\u09F3", "\u099F\u09CD\u099F", "\u099F\u09CD\u09AC",
+                            "\u099F\u09CD\u09AE")),
+                    // U+099E: "ঞ" BENGALI LETTER NYA
+                    // U+099E/U+09CD/U+099A:
+                    //     "ঞ্চ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+099E/U+09CD/U+099B:
+                    //     "ঞ্ছ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    // U+099E/U+09CD/U+099C:
+                    //     "ঞ্জ" BENGALI LETTER NYA/BENGALI SIGN VIRAMA/BENGALI LETTER JA
+                    key("\u099E", joinMoreKeys("\u099E\u09CD\u099A", "\u099E\u09CD\u099B",
+                            "\u099E\u09CD\u099C")),
+                    // U+09C2: "ূ" BENGALI VOWEL SIGN UU
+                    // U+098A: "ঊ" BENGALI LETTER UU
+                    key("\u09C2", moreKey("\u098A")),
+                    // U+09C0: "ী" BENGALI VOWEL SIGN II
+                    // U+0988: "ঈ" BENGALI LETTER II
+                    key("\u09C0", moreKey("\u0988")),
+                    // U+09CC: "ৌ" BENGALI VOWEL SIGN AU
+                    // U+099A: "ঔ" BENGALI LETTER CA
+                    // U+09D7: "ৗ" BENGALI AU LENGTH MARK
+                    key("\u09CC", joinMoreKeys("\u099A", "\u09D7")),
+                    // U+09AB: "ফ" BENGALI LETTER PHA
+                    // U+09AB/U+09CD/U+099F:
+                    //     "ফ্ট" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER TTA
+                    // U+09AB/U+09CD/U+09AF:
+                    //     "ফ্য" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER YA
+                    // U+09AB/U+09CD/U+09B0:
+                    //     "ফ্র" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09AB/U+09CD/U+09B2:
+                    //     "ফ্ল" BENGALI LETTER PHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09AB", joinMoreKeys("\u09AB\u09CD\u099F", "\u09AB\u09CD\u09AF",
+                            "\u09AB\u09CD\u09B0", "\u09AB\u09CD\u09B2")),
+                    // U+098B: "ঋ" BENGALI LETTER VOCALIC R
+                    // U+098C: "ঌ" BENGALI LETTER VOCALIC L
+                    // U+09E1: "ৡ" BENGALI LETTER VOCALIC LL
+                    // U+09F4: "৴" BENGALI CURRENCY NUMERATOR ONE
+                    // U+09F5: "৵" BENGALI CURRENCY NUMERATOR TWO
+                    // U+09F6: "৶" BENGALI CURRENCY NUMERATOR THREE
+                    // U+09E2: " ৢ" BENGALI VOWEL SIGN VOCALIC L
+                    // U+09E3: " ৣ" BENGALI VOWEL SIGN VOCALIC LL
+                    key("\u098B", joinMoreKeys("\u098C", "\u09E1", "\u09F4", "\u09F5", "\u09F6",
+                            "\u09E2", "\u09E3")))
+            .setKeysOfRow(2,
+                    // U+0985: "অ" BENGALI LETTER A
+                    key("\u0985"),
+                    // U+09B6: "শ" BENGALI LETTER SHA
+                    // U+09B6/U+09CD/U+099A:
+                    //     "শ্চ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CA
+                    // U+09B6/U+09CD/U+099B:
+                    //     "শ্ছ" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER CHA
+                    // U+09B6/U+09CD/U+09A4:
+                    //     "শ্ত" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER TA
+                    // U+09B6/U+09CD/U+09A8:
+                    //     "শ্ন" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09B6/U+09CD/U+09AC:
+                    //     "শ্ব" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B6/U+09CD/U+09AE:
+                    //     "শ্ম" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B6/U+09CD/U+09B0:
+                    //     "শ্র" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09B6/U+09CD/U+09B2:
+                    //     "শ্ল" BENGALI LETTER SHA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B6", joinMoreKeys("\u09B6\u09CD\u099A", "\u09B6\u09CD\u099B",
+                            "\u09B6\u09CD\u09A4", "\u09B6\u09CD\u09A8", "\u09B6\u09CD\u09AC",
+                            "\u09B6\u09CD\u09AE", "\u09B6\u09CD\u09B0", "\u09B6\u09CD\u09B2")),
+                    // U+09A1: "ড" BENGALI LETTER DDA
+                    // U+09A1/U+09CD/U+09A1:
+                    //     "ড্ড" BENGALI LETTER DDA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    key("\u09A1", moreKey("\u09A1\u09CD\u09A1")),
+                    // U+09DD: "ঢ়" BENGALI LETTER RHA
+                    key("\u09DD"),
+                    // U+0998: "ঘ" BENGALI LETTER GHA
+                    key("\u0998"),
+                    // U+09B9: "হ" BENGALI LETTER HA
+                    // U+09BD: "ঽ" BENGALI SIGN AVAGRAHA
+                    // U+09B9/U+09CD/U+09A3:
+                    //     "হ্ণ" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NNA
+                    // U+09B9/U+09CD/U+09A8:
+                    //     "হ্ন" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER NA
+                    // U+09B9/U+09CD/U+09AC:
+                    //     "হ্ব" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER BA
+                    // U+09B9/U+09CD/U+09AE:
+                    //     "হ্ম" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER MA
+                    // U+09B9/U+09CD/U+09B0:
+                    //     "হ্র" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER RA
+                    // U+09B9/U+09CD/U+09B2:
+                    //     "হ্ল" BENGALI LETTER HA/BENGALI SIGN VIRAMA/BENGALI LETTER LA
+                    key("\u09B9", joinMoreKeys("\u09BD", "\u09B9\u09CD\u09A3", "\u09B9\u09CD\u09A8",
+                            "\u09B9\u09CD\u09AC", "\u09B9\u09CD\u09AE", "\u09B9\u09CD\u09B0",
+                            "\u09B9\u09CD\u09B2")),
+                    // U+099D: "ঝ" BENGALI LETTER JHA
+                    key("\u099D"),
+                    // U+0996: "খ" BENGALI LETTER KHA
+                    key("\u0996"),
+                    // U+09CE: "ৎ" BENGALI LETTER KHANDA TA
+                    key("\u09CE"),
+                    // U+0988: "ঈ" BENGALI LETTER II
+                    key("\u0988"),
+                    // U+098A: "ঊ" BENGALI LETTER UU
+                    key("\u098A"))
+            .setKeysOfRow(3,
+                    // U+0964: "।" DEVANAGARI DANDA
+                    // U+0965: "॥" DEVANAGARI DOUBLE DANDA
+                    key("\u0964", moreKey("\u0965")),
+                    // U+0999: "ঙ BENGALI LETTER NGA
+                    // U+0999/U+09CD/U+0995: "ঙ্ক"
+                    // U+0999/U+09CD/U+0996: "ঙ্খ"
+                    // U+0999/U+09CD/U+0997: "ঙ্গ"
+                    key("\u0999", joinMoreKeys("\u0999\u09CD\u0995", "\u0999\u09CD\u0996",
+                            "\u0999\u09CD\u0997")),
+                    // U+099B: "ছ" BENGALI LETTER CHA
+                    key("\u099B"),
+                    // U+0983: "ঃ" BENGALI SIGN VISARGA
+                    key("\u0983"),
+                    // U+0981: "ঁ" BENGALI SIGN CANDRABINDU
+                    key("\u0981"),
+                    // U+09A3: "ণ" BENGALI LETTER NNA
+                    // U+09A3/U+09CD/U+099F:
+                    //     "ণ্ট" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER TT/A
+                    // U+09A3/U+09CD/U+09A1:
+                    //     "ণ্ড" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER DDA
+                    // U+09A3/U+09CD/U+09A3:
+                    //     "ণ্ণ" BENGALI LETTER NNA/BENGALI SIGN VIRAMA/BENGALI LETTER NN
+                    key("\u09A3", joinMoreKeys("\u09A3\u09CD\u099F", "\u09A3\u09CD\u09A1",
+                            "\u09A3\u09CD\u09A3")),
+                    // U+0982: "ং" BENGALI SIGN ANUSVARA
+                    key("\u0982"),
+                    // U+0990: "ঐ" BENGALI LETTER AI
+                    key("\u0990"),
+                    // U+0994: "ঔ" BENGALI LETTER AU
+                    key("\u0994"))
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Bulgarian.java b/tests/src/com/android/inputmethod/keyboard/layout/Bulgarian.java
index 3282e44..bbe0384 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Bulgarian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Bulgarian.java
@@ -16,7 +16,8 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -25,17 +26,17 @@
 public final class Bulgarian extends LayoutBase {
     private static final String LAYOUT_NAME = "bulgarian";
 
-    public Bulgarian(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Bulgarian(final Locale locale) {
+        super(new BulgarianCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class BulgarianCustomizer extends LayoutCustomizer {
+    private static class BulgarianCustomizer extends LayoutCustomizer {
         private final EastSlavicCustomizer mEastSlavicCustomizer;
 
-        public BulgarianCustomizer(final Locale locale) {
+        BulgarianCustomizer(final Locale locale) {
             super(locale);
             mEastSlavicCustomizer = new EastSlavicCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/BulgarianBds.java b/tests/src/com/android/inputmethod/keyboard/layout/BulgarianBds.java
index 20a5f7d..74372b9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/BulgarianBds.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/BulgarianBds.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -25,15 +25,15 @@
 public final class BulgarianBds extends LayoutBase {
     private static final String LAYOUT_NAME = "bulgarian_bds";
 
-    public BulgarianBds(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public BulgarianBds(final Locale locale) {
+        super(new BulgarianBdsCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class BulgarianBdsCustomizer extends EastSlavicCustomizer {
-        public BulgarianBdsCustomizer(final Locale locale) { super(locale); }
+    private static class BulgarianBdsCustomizer extends EastSlavicCustomizer {
+        BulgarianBdsCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Colemak.java b/tests/src/com/android/inputmethod/keyboard/layout/Colemak.java
index a4a9701..3f8ce28 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Colemak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Colemak.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Dvorak.java b/tests/src/com/android/inputmethod/keyboard/layout/Dvorak.java
index ba94c8d..7cb3b92 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Dvorak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Dvorak.java
@@ -17,12 +17,9 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey.ExpectedAdditionalMoreKey;
-import com.android.inputmethod.latin.settings.CustomInputStyleSettingsFragment;
-
-import java.util.Locale;
 
 /**
  * The Dvorak alphabet keyboard.
@@ -37,52 +34,17 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class DvorakCustomizer extends LayoutCustomizer {
-        public DvorakCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
-            return isPhone ? joinKeys(SHIFT_KEY): joinKeys(SHIFT_KEY, key("q"));
-        }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : joinKeys(key("z"), SHIFT_KEY);
-        }
-
-        @Override
-        public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            // U+00A1: "¡" INVERTED EXCLAMATION MARK
-            return isPhone ? joinKeys(key("q", SETTINGS_KEY))
-                    : joinKeys(key("!", joinMoreKeys("\u00A1", SETTINGS_KEY)));
-        }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            final ExpectedAdditionalMoreKey[] punctuationMoreKeys =
-                    convertToAdditionalMoreKeys(getPunctuationMoreKeys(isPhone));
-            // U+00BF: "¿" INVERTED QUESTION MARK
-            return isPhone
-                    ? joinKeys(key("z", punctuationMoreKeys))
-                    : joinKeys(key("?", joinMoreKeys(punctuationMoreKeys, "\u00BF")));
-        }
-
-        private static ExpectedAdditionalMoreKey[] convertToAdditionalMoreKeys(
-                final ExpectedKey ... moreKeys) {
-            final ExpectedAdditionalMoreKey[] additionalMoreKeys =
-                    new ExpectedAdditionalMoreKey[moreKeys.length];
-            for (int index = 0; index < moreKeys.length; index++) {
-                additionalMoreKeys[index] = ExpectedAdditionalMoreKey.newInstance(moreKeys[index]);
-            }
-            return additionalMoreKeys;
-        }
-    }
-
     @Override
     public ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) {
         return ALPHABET_COMMON;
     }
 
+    /**
+     * Get the left most key of the first row.
+     * @param isPhone true if requesting phone's keys.
+     * @param elementId the element id of the requesting shifted mode.
+     * @return the left most key of the first row.
+     */
     protected ExpectedKey getRow1_1Key(final boolean isPhone, final int elementId) {
         if (elementId == KeyboardId.ELEMENT_ALPHABET
                 || elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
@@ -91,6 +53,12 @@
         return key("\"", additionalMoreKey("1"));
     }
 
+    /**
+     * Get the 2nd left key of the first row.
+     * @param isPhone true if requesting phone's keys.
+     * @param elementId the element id of the requesting shifted mode.
+     * @return the 2nd left key of the first row.
+     */
     protected ExpectedKey getRow1_2Key(final boolean isPhone, final int elementId) {
         if (elementId == KeyboardId.ELEMENT_ALPHABET
                 || elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
@@ -99,6 +67,12 @@
         return key("<", additionalMoreKey("2"));
     }
 
+    /**
+     * Get the 3rd left key of the first row.
+     * @param isPhone true if requesting phone's keys.
+     * @param elementId the element id of the requesting shifted mode.
+     * @return the 3rd left key of the first row.
+     */
     protected ExpectedKey getRow1_3Key(final boolean isPhone, final int elementId) {
         if (elementId == KeyboardId.ELEMENT_ALPHABET
                 || elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/EastSlavic.java b/tests/src/com/android/inputmethod/keyboard/layout/EastSlavic.java
index 7fcc974..f95d2d2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/EastSlavic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/EastSlavic.java
@@ -16,11 +16,9 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 public final class EastSlavic extends LayoutBase {
     private static final String LAYOUT_NAME = "east_slavic";
@@ -32,26 +30,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class EastSlavicCustomizer extends LayoutCustomizer {
-        public EastSlavicCustomizer(final Locale locale) {
-            super(locale);
-        }
-
-        @Override
-        public final ExpectedKey getAlphabetKey() { return EAST_SLAVIC_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0410: "А" CYRILLIC CAPITAL LETTER A
-        // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
-        // U+0412: "В" CYRILLIC CAPITAL LETTER VE
-        private static final ExpectedKey EAST_SLAVIC_ALPHABET_KEY = key(
-                "\u0410\u0411\u0412", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Farsi.java b/tests/src/com/android/inputmethod/keyboard/layout/Farsi.java
index 7390457..6dc4559 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Farsi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Farsi.java
@@ -18,26 +18,25 @@
 
 import com.android.inputmethod.keyboard.layout.Symbols.RtlSymbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted.RtlSymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
 public final class Farsi extends LayoutBase {
     private static final String LAYOUT_NAME = "farsi";
 
-    public Farsi(final LayoutCustomizer customizer) {
-        super(customizer, FarsiSymbols.class, FarsiSymbolsShifted.class);
+    public Farsi(final Locale locale) {
+        super(new FarsiCustomizer(locale), FarsiSymbols.class, FarsiSymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class FarsiCustomizer extends LayoutCustomizer {
-        public FarsiCustomizer(final Locale locale) {
-            super(locale);
-        }
+    private static class FarsiCustomizer extends LayoutCustomizer {
+        FarsiCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return FARSI_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Georgian.java b/tests/src/com/android/inputmethod/keyboard/layout/Georgian.java
index 6f20dfc..d1ac5fd 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Georgian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Georgian.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Georgian extends LayoutBase {
     private static final String LAYOUT_NAME = "georgian";
 
-    public Georgian(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Georgian(final Locale locale) {
+        super(new GeorgianCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class GeorgianCustomizer extends LayoutCustomizer {
-        public GeorgianCustomizer(final Locale locale) { super(locale); }
+    private static class GeorgianCustomizer extends LayoutCustomizer {
+        GeorgianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return GEORGIAN_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Greek.java b/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
index 475052c..0209c2a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Greek.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Greek extends LayoutBase {
     private static final String LAYOUT_NAME = "greek";
 
-    public Greek(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Greek(final Locale locale) {
+        super(new GreekCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class GreekCustomizer extends EuroCustomizer {
-        public GreekCustomizer(final Locale locale) { super(locale); }
+    private static class GreekCustomizer extends EuroCustomizer {
+        GreekCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return GREEK_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java b/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java
index 552f0d3..1b91b47 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java
@@ -18,26 +18,25 @@
 
 import com.android.inputmethod.keyboard.layout.Symbols.RtlSymbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted.RtlSymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
 public final class Hebrew extends LayoutBase {
     private static final String LAYOUT_NAME = "hebrew";
 
-    public Hebrew(final LayoutCustomizer customizer) {
-        super(customizer, HebrewSymbols.class, RtlSymbolsShifted.class);
+    public Hebrew(final Locale locale) {
+        super(new HebrewCustomizer(locale), HebrewSymbols.class, RtlSymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class HebrewCustomizer extends LayoutCustomizer {
-        public HebrewCustomizer(final Locale locale) {
-            super(locale);
-        }
+    private static class HebrewCustomizer extends LayoutCustomizer {
+        HebrewCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return HEBREW_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java b/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
index b12b8be..82f67ac 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Hindi.java
@@ -19,11 +19,9 @@
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 /**
  * The Hindi keyboard.
@@ -38,50 +36,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class HindiCustomizer extends LayoutCustomizer {
-        public HindiCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return HINDI_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey getSymbolsKey() { return HINDI_SYMBOLS_KEY; }
-
-        @Override
-        public ExpectedKey getBackToSymbolsKey() { return HINDI_BACK_TO_SYMBOLS_KEY; }
-
-        @Override
-        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
-
-        @Override
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
-        }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0915: "क" DEVANAGARI LETTER KA
-        // U+0916: "ख" DEVANAGARI LETTER KHA
-        // U+0917: "ग" DEVANAGARI LETTER GA
-        private static final ExpectedKey HINDI_ALPHABET_KEY = key(
-                "\u0915\u0916\u0917", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-        // U+0967: "१" DEVANAGARI DIGIT ONE
-        // U+0968: "२" DEVANAGARI DIGIT TWO
-        // U+0969: "३" DEVANAGARI DIGIT THREE
-        private static final String HINDI_SYMBOLS_LABEL = "?\u0967\u0968\u0969";
-        private static final ExpectedKey HINDI_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
-                Constants.CODE_SWITCH_ALPHA_SYMBOL);
-        private static final ExpectedKey HINDI_BACK_TO_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
-                Constants.CODE_SHIFT);
-
-        // U+20B9: "₹" INDIAN RUPEE SIGN
-        private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9",
-                Symbols.CURRENCY_GENERIC_MORE_KEYS);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java b/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
index c2a15f3..a2e3399 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/HindiCompact.java
@@ -18,8 +18,8 @@
 
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
+import com.android.inputmethod.keyboard.layout.customizer.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -31,41 +31,20 @@
 public final class HindiCompact extends LayoutBase {
     private static final String LAYOUT_NAME = "hindi_compact";
 
-    public HindiCompact(final LayoutCustomizer customizer) {
-        super(customizer, HindiSymbols.class, SymbolsShifted.class);
+    public HindiCompact(final Locale locale) {
+        super(new HindiCompactCustomizer(locale), HindiSymbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class HindiCompactCustomizer extends HindiCustomizer {
-        public HindiCompactCustomizer(final Locale locale) { super(locale); }
+    private static class HindiCompactCustomizer extends HindiCustomizer {
+        HindiCompactCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
             return EMPTY_KEYS;
         }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            // U+0964: "।" DEVANAGARI DANDA
-            final ExpectedKey periodKey = key("\u0964", getPunctuationMoreKeys(isPhone));
-            return joinKeys(periodKey);
-        }
-
-        @Override
-        public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? HINDI_PHONE_PUNCTUATION_MORE_KEYS : HINDI_TABLET_PUNCTUATION_MORE_KEYS;
-        }
-
-        // Punctuation more keys for phone form factor.
-        private static final ExpectedKey[] HINDI_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
-                ",", ".", "?", "!", "#", ")", "(", "/", ";",
-                "'", "@", ":", "-", "\"", "+", "%", "&");
-        // Punctuation more keys for tablet form factor.
-        private static final ExpectedKey[] HINDI_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
-                ",", ".", "'", "#", ")", "(", "/", ";",
-                "@", ":", "-", "\"", "+", "%", "&");
     }
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Kannada.java b/tests/src/com/android/inputmethod/keyboard/layout/Kannada.java
index 8bee1f8..5a8d32c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Kannada.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Kannada.java
@@ -16,9 +16,10 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -28,15 +29,15 @@
 public final class Kannada extends LayoutBase {
     private static final String LAYOUT_NAME = "kannada";
 
-    public Kannada(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Kannada(final Locale locale) {
+        super(new KannadaCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class KannadaCustomizer extends LayoutCustomizer {
-        public KannadaCustomizer(final Locale locale) { super(locale); }
+    private static class KannadaCustomizer extends LayoutCustomizer {
+        KannadaCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return KANNADA_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
index 7e4f159..4d82f09 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Khmer.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Khmer extends LayoutBase {
     private static final String LAYOUT_NAME = "khmer";
 
-    public Khmer(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Khmer(final Locale locale) {
+        super(new KhmerCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class KhmerCustomizer extends LayoutCustomizer {
-        public KhmerCustomizer(final Locale locale) { super(locale); }
+    private static class KhmerCustomizer extends LayoutCustomizer {
+        KhmerCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public int getNumberOfRows() { return 5; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
index aaa1c8a..149f753 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Lao.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Lao extends LayoutBase {
     private static final String LAYOUT_NAME = "lao";
 
-    public Lao(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Lao(final Locale locale) {
+        super(new LaoCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class LaoCustomizer extends LayoutCustomizer {
-        public LaoCustomizer(final Locale locale) { super(locale); }
+    private static class LaoCustomizer extends LayoutCustomizer {
+        LaoCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public int getNumberOfRows() { return 5; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
index b05789b..285a50c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/LayoutBase.java
@@ -17,11 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
 
 import java.util.Locale;
 
@@ -29,200 +28,6 @@
  * The base class of keyboard layout.
  */
 public abstract class LayoutBase extends AbstractLayoutBase {
-    /**
-     * This class is used to customize common keyboard layout to language specific layout.
-     */
-    public static class LayoutCustomizer {
-        private final Locale mLocale;
-
-        // Empty keys definition to remove keys by adding this.
-        protected static final ExpectedKey[] EMPTY_KEYS = joinKeys();
-
-        public LayoutCustomizer(final Locale locale) {
-            mLocale = locale;
-        }
-
-        public final Locale getLocale() {
-            return mLocale;
-        }
-
-        public int getNumberOfRows() {
-            return 4;
-        }
-
-        /**
-         * Set accented letters to common layout.
-         * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
-         *        layout.
-         * @return the {@link ExpectedKeyboardBuilder} object that contains accented letters as
-         *        "more keys".
-         */
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder;
-        }
-
-        /**
-         * Get the function key to switch to alphabet layout.
-         * @return the {@link ExpectedKey} of the alphabet key.
-         */
-        public ExpectedKey getAlphabetKey() { return ALPHABET_KEY; }
-
-        /**
-         * Get the function key to switch to symbols layout.
-         * @return the {@link ExpectedKey} of the symbols key.
-         */
-        public ExpectedKey getSymbolsKey() { return SYMBOLS_KEY; }
-
-        /**
-         * Get the function key to switch to symbols shift layout.
-         * @param isPhone true if requesting phone's key.
-         * @return the {@link ExpectedKey} of the symbols shift key.
-         */
-        public ExpectedKey getSymbolsShiftKey(boolean isPhone) {
-            return isPhone ? SYMBOLS_SHIFT_KEY : TABLET_SYMBOLS_SHIFT_KEY;
-        }
-
-        /**
-         * Get the function key to switch from symbols shift to symbols layout.
-         * @return the {@link ExpectedKey} of the back to symbols key.
-         */
-        public ExpectedKey getBackToSymbolsKey() { return BACK_TO_SYMBOLS_KEY; }
-
-        /**
-         * Get the currency key.
-         * @return the {@link ExpectedKey} of the currency key.
-         */
-        public ExpectedKey getCurrencyKey() { return Symbols.CURRENCY_DOLLAR; }
-
-        /**
-         * Get other currencies keys.
-         * @return the array of {@link ExpectedKey} that represents other currency keys.
-         */
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_THAN_DOLLAR;
-        }
-
-        /**
-         * Get "more keys" of double quotation mark.
-         * @return the array of {@link ExpectedKey} of more double quotation marks in natural order.
-         */
-        public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_9LR; }
-
-        /**
-         * Get "more keys" of single quotation mark.
-         * @return the array of {@link ExpectedKey} of more single quotation marks in natural order.
-         */
-        public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_9LR; }
-
-        /**
-         * Get double angle quotation marks in natural order.
-         * @return the array of {@link ExpectedKey} of double angle quotation marks in natural
-         *         order.
-         */
-        public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_LR; }
-
-        /**
-         * Get single angle quotation marks in natural order.
-         * @return the array of {@link ExpectedKey} of single angle quotation marks in natural
-         *         order.
-         */
-        public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_LR; }
-
-        /**
-         * Get the left shift keys.
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that should be placed at left edge of the
-         *         keyboard.
-         */
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
-            return joinKeys(SHIFT_KEY);
-        }
-
-        /**
-         * Get the right shift keys.
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that should be placed at right edge of the
-         *         keyboard.
-         */
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : joinKeys(EXCLAMATION_AND_QUESTION_MARKS, SHIFT_KEY);
-        }
-
-        /**
-         * Get the enter key.
-         * @param isPhone true if requesting phone's key.
-         * @return the array of {@link ExpectedKey} that should be placed as an enter key.
-         */
-        public ExpectedKey getEnterKey(final boolean isPhone) {
-            return isPhone ? key(ENTER_KEY, EMOJI_ACTION_KEY) : ENTER_KEY;
-        }
-
-        /**
-         * Get the emoji key.
-         * @param isPhone true if requesting phone's key.
-         * @return the array of {@link ExpectedKey} that should be placed as an emoji key.
-         */
-        public ExpectedKey getEmojiKey(final boolean isPhone) {
-            return EMOJI_NORMAL_KEY;
-        }
-
-        /**
-         * Get the space keys.
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that should be placed at the center of the
-         *         keyboard.
-         */
-        public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
-            return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY);
-        }
-
-        /**
-         * Get the keys left to the spacebar.
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that should be placed at left of the spacebar.
-         */
-        public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            // U+002C: "," COMMA
-            return joinKeys(key("\u002C", SETTINGS_KEY));
-        }
-
-        /**
-         * Get the keys right to the spacebar.
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that should be placed at right of the spacebar.
-         */
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            final ExpectedKey periodKey = key(".", getPunctuationMoreKeys(isPhone));
-            return joinKeys(periodKey);
-        }
-
-        /**
-         * Get "more keys" for the punctuation key (usually the period key).
-         * @param isPhone true if requesting phone's keys.
-         * @return the array of {@link ExpectedKey} that are "more keys" of the punctuation key.
-         */
-        public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? PHONE_PUNCTUATION_MORE_KEYS : TABLET_PUNCTUATION_MORE_KEYS;
-        }
-    }
-
-    /**
-     * The layout customize class for countries that use Euro.
-     */
-    public static class EuroCustomizer extends LayoutCustomizer {
-        public EuroCustomizer(final Locale locale) {
-            super(locale);
-        }
-
-        @Override
-        public final ExpectedKey getCurrencyKey() { return Symbols.CURRENCY_EURO; }
-
-        @Override
-        public final ExpectedKey[] getOtherCurrencyKeys() {
-            return SymbolsShifted.CURRENCIES_OTHER_THAN_EURO;
-        }
-    }
-
     private final LayoutCustomizer mCustomizer;
     private final Symbols mSymbols;
     private final SymbolsShifted mSymbolsShifted;
@@ -258,77 +63,6 @@
      */
     public final LayoutCustomizer getCustomizer() { return mCustomizer; }
 
-    // Icon ids.
-    private static final int ICON_DELETE = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_DELETE_KEY);
-    private static final int ICON_SPACE = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_SPACE_KEY);
-    private static final int ICON_TAB = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_TAB_KEY);
-    private static final int ICON_SHORTCUT = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_SHORTCUT_KEY);
-    private static final int ICON_SETTINGS = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_SETTINGS_KEY);
-    private static final int ICON_LANGUAGE_SWITCH = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY);
-    private static final int ICON_ENTER = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_ENTER_KEY);
-    private static final int ICON_EMOJI_ACTION = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_EMOJI_ACTION_KEY);
-    private static final int ICON_EMOJI_NORMAL = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY);
-    private static final int ICON_SHIFT = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_SHIFT_KEY);
-    private static final int ICON_SHIFTED_SHIFT = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED);
-    private static final int ICON_ZWNJ = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_ZWNJ_KEY);
-    private static final int ICON_ZWJ = KeyboardIconsSet.getIconId(
-            KeyboardIconsSet.NAME_ZWJ_KEY);
-
-    // Functional keys.
-    public static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);
-    public static final ExpectedKey TAB_KEY = key(ICON_TAB, Constants.CODE_TAB);
-    public static final ExpectedKey SHORTCUT_KEY = key(ICON_SHORTCUT, Constants.CODE_SHORTCUT);
-    public static final ExpectedKey SETTINGS_KEY = key(ICON_SETTINGS, Constants.CODE_SETTINGS);
-    public static final ExpectedKey LANGUAGE_SWITCH_KEY = key(
-            ICON_LANGUAGE_SWITCH, Constants.CODE_LANGUAGE_SWITCH);
-    public static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER);
-    public static final ExpectedKey EMOJI_ACTION_KEY = key(ICON_EMOJI_ACTION, Constants.CODE_EMOJI);
-    public static final ExpectedKey EMOJI_NORMAL_KEY = key(ICON_EMOJI_NORMAL, Constants.CODE_EMOJI);
-    public static final ExpectedKey SPACE_KEY = key(ICON_SPACE, Constants.CODE_SPACE);
-    static final ExpectedKey CAPSLOCK_MORE_KEY = key(" ", Constants.CODE_CAPSLOCK);
-    public static final ExpectedKey SHIFT_KEY = key(ICON_SHIFT,
-            Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY);
-    public static final ExpectedKey SHIFTED_SHIFT_KEY = key(ICON_SHIFTED_SHIFT,
-            Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY);
-    static final ExpectedKey ALPHABET_KEY = key("ABC", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    static final ExpectedKey SYMBOLS_KEY = key("?123", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    static final ExpectedKey BACK_TO_SYMBOLS_KEY = key("?123", Constants.CODE_SHIFT);
-    static final ExpectedKey SYMBOLS_SHIFT_KEY = key("= \\ <", Constants.CODE_SHIFT);
-    static final ExpectedKey TABLET_SYMBOLS_SHIFT_KEY = key("~ [ <", Constants.CODE_SHIFT);
-
-    // U+00A1: "¡" INVERTED EXCLAMATION MARK
-    // U+00BF: "¿" INVERTED QUESTION MARK
-    static final ExpectedKey[] EXCLAMATION_AND_QUESTION_MARKS = joinKeys(
-            key("!", moreKey("\u00A1")), key("?", moreKey("\u00BF")));
-    // U+200C: ZERO WIDTH NON-JOINER
-    // U+200D: ZERO WIDTH JOINER
-    static final ExpectedKey ZWNJ_KEY = key(ICON_ZWNJ, "\u200C");
-    static final ExpectedKey ZWJ_KEY = key(ICON_ZWJ, "\u200D");
-    // Domain key
-    public static final ExpectedKey DOMAIN_KEY =
-            key(".com", joinMoreKeys(".net", ".org", ".gov", ".edu")).preserveCase();
-
-    // Punctuation more keys for phone form factor.
-    public static final ExpectedKey[] PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
-            ",", "?", "!", "#", ")", "(", "/", ";",
-            "'", "@", ":", "-", "\"", "+", "%", "&");
-    // Punctuation more keys for tablet form factor.
-    public static final ExpectedKey[] TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
-            ",", "'", "#", ")", "(", "/", ";",
-            "@", ":", "-", "\"", "+", "%", "&");
-
     /**
      * Helper method to create alphabet layout adding special function keys.
      * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
@@ -386,7 +120,7 @@
     ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) {
         final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(
                 getCommonAlphabetLayout(isPhone));
-        getCustomizer().setAccentedLetters(builder);
+        getCustomizer().setAccentedLetters(builder, elementId);
         builder.toUpperCase(getLocale());
         return builder.build();
     }
@@ -411,7 +145,7 @@
         final ExpectedKeyboardBuilder builder;
         if (elementId == KeyboardId.ELEMENT_ALPHABET) {
             builder = new ExpectedKeyboardBuilder(getCommonAlphabetLayout(isPhone));
-            getCustomizer().setAccentedLetters(builder);
+            getCustomizer().setAccentedLetters(builder, elementId);
         } else {
             final ExpectedKey[][] commonLayout = getCommonAlphabetShiftLayout(isPhone, elementId);
             if (commonLayout == null) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Malayalam.java b/tests/src/com/android/inputmethod/keyboard/layout/Malayalam.java
index b44b888..3497c35 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Malayalam.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Malayalam.java
@@ -16,9 +16,10 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -28,15 +29,15 @@
 public final class Malayalam extends LayoutBase {
     private static final String LAYOUT_NAME = "malayalam";
 
-    public Malayalam(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Malayalam(final Locale locale) {
+        super(new MalayalamCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class MalayalamCustomizer extends LayoutCustomizer {
-        public MalayalamCustomizer(final Locale locale) { super(locale); }
+    private static class MalayalamCustomizer extends LayoutCustomizer {
+        MalayalamCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return MALAYALAM_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java b/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
index 00cf838..af26ec5 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Marathi.java
@@ -18,8 +18,8 @@
 
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
+import com.android.inputmethod.keyboard.layout.customizer.DevanagariCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -31,20 +31,37 @@
 public final class Marathi extends LayoutBase {
     private static final String LAYOUT_NAME = "marathi";
 
-    public Marathi(final LayoutCustomizer customizer) {
-        super(customizer, HindiSymbols.class, SymbolsShifted.class);
+    public Marathi(final Locale locale) {
+        super(new MarathiCustomizer(locale), HindiSymbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class MarathiCustomizer extends HindiCustomizer {
-        public MarathiCustomizer(final Locale locale) { super(locale); }
+    private static class MarathiCustomizer extends DevanagariCustomizer {
+        MarathiCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+        @Override
+        public ExpectedKey[] getOtherCurrencyKeys() {
+            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+        }
 
         @Override
         public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
             return EMPTY_KEYS;
         }
+
+        @Override
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+        }
+
+        // U+20B9: "₹" INDIAN RUPEE SIGN
+        private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9",
+                Symbols.CURRENCY_GENERIC_MORE_KEYS);
     }
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Mongolian.java b/tests/src/com/android/inputmethod/keyboard/layout/Mongolian.java
index 3c6c058..288a17e 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Mongolian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Mongolian.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -25,17 +25,15 @@
 public final class Mongolian extends LayoutBase {
     private static final String LAYOUT_NAME = "mongolian";
 
-    public Mongolian(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Mongolian(final Locale locale) {
+        super(new MongolianCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class MongolianMNCustomizer extends EastSlavicCustomizer {
-        public MongolianMNCustomizer(final Locale locale) {
-            super(locale);
-        }
+    private static class MongolianCustomizer extends EastSlavicCustomizer {
+        MongolianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_TUGRIK; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java b/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
deleted file mode 100644
index 3c70d32..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/Myanmar.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout;
-
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
-
-/**
- * The Myanmar alphabet keyboard.
- */
-public final class Myanmar extends LayoutBase {
-    private static final String LAYOUT_NAME = "myanmar";
-
-    public Myanmar(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
-    }
-
-    @Override
-    public String getName() { return LAYOUT_NAME; }
-
-    public static class MyanmarCustomizer extends LayoutCustomizer {
-        public MyanmarCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public int getNumberOfRows() { return 5; }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return MYANMAR_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        @Override
-        public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            // U+002C: "," COMMA
-            // U+104A: "၊" MYANMAR SIGN LITTLE SECTION
-            return isPhone ? joinKeys(key("\u002C", SETTINGS_KEY))
-                    : joinKeys(key("\u104A", moreKey(","), SETTINGS_KEY));
-        }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            // U+104B: "။" MYANMAR SIGN SECTION
-            final ExpectedKey periodKey = key("\u104B", getPunctuationMoreKeys(isPhone));
-            return joinKeys(periodKey);
-        }
-
-        @Override
-        public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? MYANMAR_PHONE_PUNCTUATION_MORE_KEYS
-                    : MYANMAR_TABLET_PUNCTUATION_MORE_KEYS;
-        }
-
-        // U+1000: "က" MYANMAR LETTER KA
-        // U+1001: "ခ" MYANMAR LETTER KHA
-        // U+1002: "ဂ" MYANMAR LETTER GA
-        private static final ExpectedKey MYANMAR_ALPHABET_KEY = key(
-                "\u1000\u1001\u1002", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-
-        // U+104A: "၊" MYANMAR SIGN LITTLE SECTION
-        // Punctuation more keys for phone form factor.
-        private static final ExpectedKey[] MYANMAR_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
-                "\u104A", ".", "?", "!", "#", ")", "(", "/", ";",
-                "...", "'", "@", ":", "-", "\"", "+", "%", "&");
-        // Punctuation more keys for tablet form factor.
-        private static final ExpectedKey[] MYANMAR_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
-                ".", "'", "#", ")", "(", "/", ";", "@",
-                "...", ":", "-", "\"", "+", "%", "&");
-    }
-
-    @Override
-    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
-
-    @Override
-    public ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone,
-            final int elementId) {
-        if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
-            return getCommonAlphabetLayout(isPhone);
-        }
-        return ALPHABET_SHIFTED_COMMON;
-    }
-
-    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
-            .setKeysOfRow(1,
-                    // U+1041: "၁" MYANMAR DIGIT ONE
-                    key("\u1041", moreKey("1")),
-                    // U+1042: "၂" MYANMAR DIGIT TWO
-                    key("\u1042", moreKey("2")),
-                    // U+1043: "၃" MYANMAR DIGIT THREE
-                    key("\u1043", moreKey("3")),
-                    // U+1044: "၄" MYANMAR DIGIT FOUR
-                    key("\u1044", moreKey("4")),
-                    // U+1045: "၅" MYANMAR DIGIT FIVE
-                    key("\u1045", moreKey("5")),
-                    // U+1046: "၆" MYANMAR DIGIT SIX
-                    key("\u1046", moreKey("6")),
-                    // U+1047: "၇" MYANMAR DIGIT SEVEN
-                    key("\u1047", moreKey("7")),
-                    // U+1048: "၈" MYANMAR DIGIT EIGHT
-                    key("\u1048", moreKey("8")),
-                    // U+1049: "၉" MYANMAR DIGIT NINE
-                    key("\u1049", moreKey("9")),
-                    // U+1040: "၀" MYANMAR DIGIT ZERO
-                    key("\u1040", moreKey("0")))
-            .setKeysOfRow(2,
-                    // U+1006: "ဆ" MYANMAR LETTER CHA
-                    // U+1039/U+1006: "္ဆ" MYANMAR SIGN VIRAMA/MYANMAR LETTER CHA
-                    key("\u1006", moreKey("\u1039\u1006")),
-                    // U+1010: "တ" MYANMAR LETTER TA
-                    // U+1039/U+1010: "္တ" MYANMAR SIGN VIRAMA/MYANMAR LETTER TA
-                    key("\u1010", moreKey("\u1039\u1010")),
-                    // U+1014: "န" MYANMAR LETTER NA
-                    // U+1039/U+1014: "္န" MYANMAR SIGN VIRAMA/MYANMAR LETTER NA
-                    key("\u1014", moreKey("\u1039\u1014")),
-                    // U+1019: "မ" MYANMAR LETTER MA
-                    // U+1039/U+1019: "္မ" MYANMAR SIGN VIRAMA/MYANMAR LETTER MA
-                    key("\u1019", moreKey("\u1039\u1019")),
-                    // U+1021: "အ" MYANMAR LETTER A
-                    // U+1015: "ပ" MYANMAR LETTER PA
-                    "\u1021", "\u1015",
-                    // U+1000: "က" MYANMAR LETTER KA
-                    // U+1039/U+1000: "္က" MYANMAR SIGN VIRAMA/MYANMAR LETTER KA
-                    key("\u1000", moreKey("\u1039\u1000")),
-                    // U+1004: "င" MYANMAR LETTER NGA
-                    // U+101E: "သ" MYANMAR LETTER SA
-                    "\u1004", "\u101E",
-                    // U+1005: "စ" MYANMAR LETTER CA
-                    // U+1039/U+1005: "္စ" MYANMAR SIGN VIRAMA/MYANMAR LETTER CA
-                    key("\u1005", moreKey("\u1039\u1005")))
-            .setKeysOfRow(3,
-                    // U+1031: "ေ" MYANMAR VOWEL SIGN E
-                    // U+103B: "ျ" MYANMAR CONSONANT SIGN MEDIAL YA
-                    // U+103C: "ြ" MYANMAR CONSONANT SIGN MEDIAL RA
-                    "\u1031", "\u103B", "\u103C",
-                    // U+103D: "ွ" MYANMAR CONSONANT SIGN MEDIAL WA
-                    // U+103E: "ှ" MYANMAR CONSONANT SIGN MEDIAL HA
-                    // U+103D/U+103E:
-                    //     "ွှ" MYANMAR CONSONANT SIGN MEDIAL WA/MYANMAR CONSONANT SIGN MEDIAL HA
-                    key("\u103D", joinMoreKeys("\u103E", "\u103D\u103E")),
-                    // U+102D: "ိ" MYANMAR VOWEL SIGN I
-                    // U+102E: "ီ" MYANMAR VOWEL SIGN II
-                    key("\u102D", moreKey("\u102E")),
-                    // U+102F: "ု" MYANMAR VOWEL SIGN U
-                    // U+1030: "ူ" MYANMAR VOWEL SIGN UU
-                    key("\u102F", moreKey("\u1030")),
-                    // U+102C: "ာ" MYANMAR VOWEL SIGN AA
-                    // U+102B: "ါ" MYANMAR VOWEL SIGN TALL AA
-                    key("\u102C", moreKey("\u102B")),
-                    // U+103A: "်" MYANMAR SIGN ASAT
-                    // U+1032: "ဲ" MYANMAR VOWEL SIGN AI
-                    key("\u103A", moreKey("\u1032")),
-                    // U+1037: "့" MYANMAR SIGN DOT BELOW
-                    // U+1036: "ံ" MYANMAR SIGN ANUSVARA
-                    key("\u1037", moreKey("\u1036")),
-                    // U+1038: "း" MYANMAR SIGN VISARGA
-                    "\u1038")
-            .setKeysOfRow(4,
-                    // U+1016: "ဖ" MYANMAR LETTER PHA
-                    "\u1016",
-                    // U+1011: "ထ" MYANMAR LETTER THA
-                    // U+1039/U+1011: "္ထ" MYANMAR SIGN VIRAMA/MYANMAR LETTER THA
-                    key("\u1011", moreKey("\u1039\u1011")),
-                    // U+1001: "ခ" MYANMAR LETTER KHA
-                    // U+1039/U+1001: "္ခ" MYANMAR SIGN VIRAMA/MYANMAR LETTER KHA
-                    key("\u1001", moreKey("\u1039\u1001")),
-                    // U+101C: "လ" MYANMAR LETTER LA
-                    // U+1039/U+101C: "္လ" MYANMAR SIGN VIRAMA/MYANMAR LETTER LA
-                    key("\u101C", moreKey("\u1039\u101C")),
-                    // U+1018: "ဘ" MYANMAR LETTER BHA
-                    // U+1039/U+1018: "္ဘ" MYANMAR SIGN VIRAMA/MYANMAR LETTER BHA
-                    key("\u1018", moreKey("\u1039\u1018")),
-                    // U+100A: "ည" MYANMAR LETTER NNYA
-                    // U+1009: "ဉ" MYANMAR LETTER NYA
-                    key("\u100A", moreKey("\u1009")),
-                    // U+101B: "ရ" MYANMAR LETTER RA
-                    // U+101D: "ဝ" MYANMAR LETTER WA
-                    "\u101B", "\u101D")
-            .build();
-
-    private static final ExpectedKey[][] ALPHABET_SHIFTED_COMMON = new ExpectedKeyboardBuilder()
-            .setKeysOfRow(1,
-                    // U+1027: "ဧ" MYANMAR LETTER E
-                    // U+104F: "၏" MYANMAR SYMBOL GENITIVE
-                    // U+1024: "ဤ" MYANMAR LETTER II
-                    // U+1023: "ဣ" MYANMAR LETTER I
-                    // U+104E: "၎" MYANMAR SYMBOL AFOREMENTIONED
-                    // U+1000/U+103B/U+1015/U+103A: "ကျပ်" MYANMAR LETTER KA
-                    //     /MYANMAR CONSONANT SIGN MEDIAL YA/MYANMAR LETTER PA/MYANMAR SIGN ASAT
-                    // U+1029: "ဩ" MYANMAR LETTER O
-                    // U+102A: "ဪ" MYANMAR LETTER AU
-                    // U+104D: "၍" MYANMAR SYMBOL COMPLETED
-                    // U+104C: "၌" MYANMAR SYMBOL LOCATIVE
-                    "\u1027", "\u104F", "\u1024", "\u1023", "\u104E", "\u1000\u103B\u1015\u103A",
-                    "\u1029", "\u102A", "\u104D", "\u104C")
-            .setKeysOfRow(2,
-                    // U+1017: "ဗ" MYANMAR LETTER BA
-                    // U+1039/U+1017: "္ဗ" MYANMAR SIGN VIRAMA/MYANMAR LETTER BA
-                    key("\u1017", moreKey("\u1039\u1017")),
-                    // U+1012: "ဒ" MYANMAR LETTER DA
-                    // U+1039/U+1012: "္ဒ" MYANMAR SIGN VIRAMA/MYANMAR LETTER DA
-                    key("\u1012", moreKey("\u1039\u1012")),
-                    // U+1013: "ဓ" MYANMAR LETTER DHA
-                    // U+1039/U+1013: "္ဓ" MYANMAR SIGN VIRAMA/MYANMAR LETTER DHA
-                    key("\u1013", moreKey("\u1039\u1013")),
-                    // U+1003: "ဃ" MYANMAR LETTER GHA
-                    // U+100E: "ဎ" MYANMAR LETTER DDHA
-                    // U+103F: "ဿ" MYANMAR LETTER GREAT SA
-                    // U+100F: "ဏ" MYANMAR LETTER NNA
-                    "\u1003", "\u100E", "\u103F", "\u100F",
-                    // U+1008: "ဈ" MYANMAR LETTER JHA
-                    // U+1039/U+1008: "္ဈ" MYANMAR SIGN VIRAMA/MYANMAR LETTER JHA
-                    key("\u1008", moreKey("\u1039\u1008")),
-                    // U+1007: "ဇ" MYANMAR LETTER JA
-                    // U+1039/U+1007: "္ဇ" MYANMAR SIGN VIRAMA/MYANMAR LETTER JA
-                    key("\u1007", moreKey("\u1039\u1007")),
-                    // U+1002: "ဂ" MYANMAR LETTER GA
-                    // U+1039/U+1002: "္ဂ" MYANMAR SIGN VIRAMA/MYANMAR LETTER GA
-                    key("\u1002", moreKey("\u1039\u1002")))
-            .setKeysOfRow(3,
-                    // U+101A: "ယ" MYANMAR LETTER YA
-                    // U+1039: "္" MYANMAR SIGN VIRAMA
-                    // U+1004/U+103A/U+1039: "င်္င" MYANMAR LETTER NGA
-                    //     /MYANMAR SIGN ASAT/MYANMAR SIGN VIRAMA
-                    // U+103E: "ှ" MYANMAR CONSONANT SIGN MEDIAL HA
-                    // U+102E: "ီ" MYANMAR VOWEL SIGN II
-                    // U+1030: "ူ" MYANMAR VOWEL SIGN UU
-                    // U+102B: "ါ" MYANMAR VOWEL SIGN TALL AA
-                    // U+1032: "ဲ" MYANMAR VOWEL SIGN AI
-                    // U+1036: "ံ" MYANMAR SIGN ANUSVARA
-                    // U+101F: "ဟ" MYANMAR LETTER HA
-                    "\u101A", "\u1039", "\u1004\u103A\u1039", "\u103E", "\u102E", "\u1030",
-                    "\u102B", "\u1032", "\u1036", "\u101F")
-            .setKeysOfRow(4,
-                    // U+1025: "ဥ" MYANMAR LETTER U
-                    // U+1026: "ဦ" MYANMAR LETTER UU
-                    // U+100C: "ဌ" MYANMAR LETTER TTHA
-                    // U+100B: "ဋ" MYANMAR LETTER TTA
-                    // U+100D: "ဍ" MYANMAR LETTER DDA
-                    // U+1020: "ဠ" MYANMAR LETTER LLA
-                    // U+100B/U+1039/U+100C: "ဋ္ဌ" MYANMAR LETTER TTA
-                    //     /MYANMAR SIGN VIRAMA/MYANMAR LETTER TTHA
-                    "\u1025", "\u1026", "\u100C", "\u100B", "\u100D", "\u1020",
-                    "\u100B\u1039\u100C",
-                    // U+100F/U+1039/U+100D: "ဏ္ဍ" MYANMAR LETTER NNA
-                    //     /MYANMAR SIGN VIRAMA/MYANMAR LETTER DDA
-                    // U+100F/U+1039/U+100C: "ဏ္ဌ" MYANMAR LETTER NNA
-                    //     /MYANMAR SIGN VIRAMA/MYANMAR LETTER TTHA
-                    key("\u100F\u1039\u100D", moreKey("\u100F\u1039\u100C")))
-            .build();
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java b/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
index 7933d07..299cb61 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/NepaliRomanized.java
@@ -19,8 +19,8 @@
 import static com.android.inputmethod.keyboard.layout.DevanagariLetterConstants.*;
 
 import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
+import com.android.inputmethod.keyboard.layout.customizer.NepaliCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -32,35 +32,18 @@
 public final class NepaliRomanized extends LayoutBase {
     private static final String LAYOUT_NAME = "nepali_romanized";
 
-    public NepaliRomanized(final LayoutCustomizer customizer) {
-        super(customizer, HindiSymbols.class, SymbolsShifted.class);
+    public NepaliRomanized(final Locale locale) {
+        super(new NepaliCustomizer(locale), HindiSymbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class NepaliRomanizedCustomizer extends HindiCustomizer {
-        public NepaliRomanizedCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getCurrencyKey() { return CURRENCY_NEPALI; }
-
-        @Override
-        public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
-            return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY, key(ZWNJ_KEY, ZWJ_KEY));
-        }
-
-        // U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN
-        private static final ExpectedKey CURRENCY_NEPALI = key("\u0930\u0941\u002E",
-                Symbols.DOLLAR_SIGN, Symbols.CENT_SIGN, Symbols.EURO_SIGN, Symbols.POUND_SIGN,
-                Symbols.YEN_SIGN, Symbols.PESO_SIGN);
-    }
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
 
     @Override
-    ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
-
-    @Override
-    ExpectedKey[][] getCommonAlphabetShiftLayout(boolean isPhone, final int elementId) {
+    ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) {
         if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
             return getCommonAlphabetLayout(isPhone);
         }
@@ -126,11 +109,9 @@
                     // U+0928: "न" DEVANAGARI LETTER NA
                     // U+092E: "म" DEVANAGARI LETTER MA
                     "\u0937", "\u0921", "\u091A", "\u0935", "\u092C", "\u0928", "\u092E",
-                    // U+0964: "।" DEVANAGARI DANDA
-                    // U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA
-                    key("\u0964", moreKey("\u093D")),
                     // U+094D: "्" DEVANAGARI SIGN VIRAMA
-                    key(SIGN_VIRAMA, "\u094D"))
+                    // U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA
+                    key(SIGN_VIRAMA, "\u094D", moreKey("\u093D")))
             .build();
 
     private static final ExpectedKey[][] ALPHABET_SHIFTED_COMMON = new ExpectedKeyboardBuilder()
@@ -180,8 +161,6 @@
                     // U+0902: "ं" DEVANAGARI SIGN ANUSVARA
                     key(SIGN_ANUSVARA, "\u0902"),
                     // U+0919: "ङ" DEVANAGARI LETTER NGA
-                    "\u0919",
-                    // U+094D: "्" DEVANAGARI SIGN VIRAMA
-                    key(SIGN_VIRAMA, "\u094D"))
+                    "\u0919")
             .build();
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/NepaliTraditional.java b/tests/src/com/android/inputmethod/keyboard/layout/NepaliTraditional.java
index 4d6cded..0a2bea3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/NepaliTraditional.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/NepaliTraditional.java
@@ -20,7 +20,7 @@
 
 import com.android.inputmethod.keyboard.KeyboardId;
 import com.android.inputmethod.keyboard.layout.Hindi.HindiSymbols;
-import com.android.inputmethod.keyboard.layout.NepaliRomanized.NepaliRomanizedCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.NepaliCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -32,93 +32,31 @@
 public final class NepaliTraditional extends LayoutBase {
     private static final String LAYOUT_NAME = "nepali_traditional";
 
-    public NepaliTraditional(final LayoutCustomizer customizer) {
-        super(customizer, HindiSymbols.class, SymbolsShifted.class);
+    public NepaliTraditional(final Locale locale) {
+        super(new NepaliTraditionalCustomizer(locale), HindiSymbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class NepaliTraditionalCustomizer extends NepaliRomanizedCustomizer {
-        public NepaliTraditionalCustomizer(final Locale locale) { super(locale); }
+    private static class NepaliTraditionalCustomizer extends NepaliCustomizer {
+        NepaliTraditionalCustomizer(final Locale locale) { super(locale); }
 
         @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) { return EMPTY_KEYS; }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            if (isPhone) {
-                // U+094D: "्" DEVANAGARI SIGN VIRAMA
-                return joinKeys(key(SIGN_VIRAMA, "\u094D", PHONE_PUNCTUATION_MORE_KEYS));
-            }
-            return super.getKeysRightToSpacebar(isPhone);
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
         }
     }
 
     @Override
-    ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) {
-        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON);
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(3,
-                    // U+0947: "े" DEVANAGARI VOWEL SIGN E
-                    // U+0903: "ः‍" DEVANAGARI SIGN VISARGA
-                    // U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA
-                    key(VOWEL_SIGN_E, "\u0947", joinMoreKeys(
-                            moreKey(SIGN_VISARGA, "\u0903"), "\u093D")),
-                    // U+0964: "।" DEVANAGARI DANDA
-                    "\u0964",
-                    // U+0930: "र" DEVANAGARI LETTER RA
-                    // U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U
-                    key("\u0930", moreKey("\u0930\u0941")));
-        } else {
-            builder.addKeysOnTheRightOfRow(3,
-                    // U+0903: "ः" DEVANAGARI SIGN VISARGA
-                    // U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA
-                    key(SIGN_VISARGA, "\u0903", moreKey("\u093D")),
-                    // U+0947: "े" DEVANAGARI VOWEL SIGN E
-                    key(VOWEL_SIGN_E, "\u0947"),
-                    // U+0964: "।" DEVANAGARI DANDA
-                    "\u0964",
-                    // U+0930: "र" DEVANAGARI LETTER RA
-                    key("\u0930", moreKey("!")),
-                    // U+094D: "्" DEVANAGARI SIGN VIRAMA
-                    key(SIGN_VIRAMA, "\u094D", moreKey("?")));
-        }
-        return builder.build();
-    }
+    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
 
     @Override
-    ExpectedKey[][] getCommonAlphabetShiftLayout(boolean isPhone, final int elementId) {
+    ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) {
         if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
             return getCommonAlphabetLayout(isPhone);
         }
-        final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(
-                ALPHABET_SHIFTED_COMMON);
-        if (isPhone) {
-            builder.addKeysOnTheRightOfRow(3,
-                    // U+0902: "ं" DEVANAGARI SIGN ANUSVARA
-                    key(SIGN_ANUSVARA, "\u0902"),
-                    // U+0919: "ङ" DEVANAGARI LETTER NGA
-                    "\u0919",
-                    // U+0948: "ै" DEVANAGARI VOWEL SIGN AI
-                    // U+0936/U+094D/U+0930:
-                    //     "श्र" DEVANAGARI LETTER SHA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA
-                    key(VOWEL_SIGN_AI, "\u0948", moreKey("\u0936\u094D\u0930")));
-        } else {
-            builder.addKeysOnTheRightOfRow(3,
-                    // U+0902: "ं" DEVANAGARI SIGN ANUSVARA
-                    key(SIGN_ANUSVARA, "\u0902"),
-                    // U+0919: "ङ" DEVANAGARI LETTER NGA
-                    "\u0919",
-                    // U+0948: "ै" DEVANAGARI VOWEL SIGN AI
-                    // U+0936/U+094D/U+0930:
-                    //     "श्र" DEVANAGARI LETTER SHA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA
-                    key(VOWEL_SIGN_AI, "\u0948", moreKey("\u0936\u094D\u0930")),
-                    // U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U
-                    key("\u0930\u0941", moreKey("!")),
-                    "?");
-        }
-        return builder.build();
+        return ALPHABET_SHIFTED_COMMON;
     }
 
     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
@@ -181,7 +119,17 @@
                     // U+0916: "ख" DEVANAGARI LETTER KHA
                     // U+0926: "द" DEVANAGARI LETTER DA
                     // U+0932: "ल" DEVANAGARI LETTER LA
-                    "\u0936", "\u0939", "\u0905", "\u0916", "\u0926", "\u0932")
+                    "\u0936", "\u0939", "\u0905", "\u0916", "\u0926", "\u0932",
+                    // U+0947: "े" DEVANAGARI VOWEL SIGN E
+                    // U+0903: "ः‍" DEVANAGARI SIGN VISARGA
+                    // U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA
+                    key(VOWEL_SIGN_E, "\u0947", joinMoreKeys(
+                            moreKey(SIGN_VISARGA, "\u0903"), "\u093D")),
+                    // U+094D: "्" DEVANAGARI SIGN VIRAMA
+                    key(SIGN_VIRAMA, "\u094D"),
+                    // U+0930: "र" DEVANAGARI LETTER RA
+                    // U+0930/U+0941: "रु" DEVANAGARI LETTER RA/DEVANAGARI VOWEL SIGN U
+                    key("\u0930", moreKey("\u0930\u0941")))
             .build();
 
     private static final ExpectedKey[][] ALPHABET_SHIFTED_COMMON = new ExpectedKeyboardBuilder()
@@ -264,6 +212,14 @@
                     key(VOWEL_SIGN_AU, "\u094C"),
                     // U+0926/U+094D/U+092F:
                     //     "द्य" DEVANAGARI LETTER DA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER YA
-                    "\u0926\u094D\u092F")
+                    "\u0926\u094D\u092F",
+                    // U+0902: "ं" DEVANAGARI SIGN ANUSVARA
+                    key(SIGN_ANUSVARA, "\u0902"),
+                    // U+0919: "ङ" DEVANAGARI LETTER NGA
+                    "\u0919",
+                    // U+0948: "ै" DEVANAGARI VOWEL SIGN AI
+                    // U+0936/U+094D/U+0930:
+                    //     "श्र" DEVANAGARI LETTER SHA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA
+                    key(VOWEL_SIGN_AI, "\u0948", moreKey("\u0936\u094D\u0930")))
             .build();
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Nordic.java b/tests/src/com/android/inputmethod/keyboard/layout/Nordic.java
index c791c40..4f718e6 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Nordic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Nordic.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
index 3f7340f..0085ac6 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/PcQwerty.java
@@ -17,11 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
-import java.util.Locale;
-
 /**
  * The PC QWERTY alphabet keyboard.
  */
@@ -35,35 +34,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class PcQwertyCustomizer extends LayoutCustomizer {
-        public PcQwertyCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public int getNumberOfRows() { return 5; }
-
-        @Override
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
-            return joinKeys(SHIFT_KEY);
-        }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return joinKeys(SHIFT_KEY);
-        }
-
-        @Override
-        public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            return joinKeys(SETTINGS_KEY);
-        }
-
-        @Override
-        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
-            return isPhone
-                    ? joinKeys(key(ENTER_KEY, EMOJI_ACTION_KEY))
-                    : joinKeys(EMOJI_NORMAL_KEY);
-        }
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) {
         final LayoutCustomizer customizer = getCustomizer();
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
index d790a1e..508df0c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Qwerty.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Qwertz.java b/tests/src/com/android/inputmethod/keyboard/layout/Qwertz.java
index 26ba6cf..cc41fbf 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Qwertz.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Qwertz.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SerbianQwertz.java b/tests/src/com/android/inputmethod/keyboard/layout/SerbianQwertz.java
new file mode 100644
index 0000000..a493628
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SerbianQwertz.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 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.layout;
+
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+public final class SerbianQwertz extends LayoutBase {
+    private static final String LAYOUT_NAME = "serbian_qwertz";
+
+    public SerbianQwertz(final LayoutCustomizer customizer) {
+        super(customizer, Symbols.class, SymbolsShifted.class);
+    }
+
+    @Override
+    public String getName() { return LAYOUT_NAME; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
+
+    public static final String ROW1_11 = "ROW1_11";
+    public static final String ROW2_10 = "ROW2_10";
+    public static final String ROW2_11 = "ROW2_11";
+    public static final String ROW3_8 = "ROW3_8";
+    public static final String ROW3_9 = "ROW3_9";
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    key("q", additionalMoreKey("1")),
+                    key("w", additionalMoreKey("2")),
+                    key("e", additionalMoreKey("3")),
+                    key("r", additionalMoreKey("4")),
+                    key("t", additionalMoreKey("5")),
+                    key("z", additionalMoreKey("6")),
+                    key("u", additionalMoreKey("7")),
+                    key("i", additionalMoreKey("8")),
+                    key("o", additionalMoreKey("9")),
+                    key("p", additionalMoreKey("0")),
+                    ROW1_11)
+            .setKeysOfRow(2, "a", "s", "d", "f", "g", "h", "j", "k", "l", ROW2_10, ROW2_11)
+            .setKeysOfRow(3, "y", "x", "c", "v", "b", "n", "m", ROW3_8, ROW3_9)
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Sinhala.java b/tests/src/com/android/inputmethod/keyboard/layout/Sinhala.java
index 354141d..c3a9351 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Sinhala.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Sinhala.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Sinhala extends LayoutBase {
     private static final String LAYOUT_NAME = "sinhala";
 
-    public Sinhala(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Sinhala(final Locale locale) {
+        super(new SinhalaCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class SinhalaCustomizer extends LayoutCustomizer {
-        public SinhalaCustomizer(final Locale locale) { super(locale); }
+    private static class SinhalaCustomizer extends LayoutCustomizer {
+        SinhalaCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return SINHALA_ALPHABET_KEY; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SouthSlavic.java b/tests/src/com/android/inputmethod/keyboard/layout/SouthSlavic.java
index be8b435..ad82787 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/SouthSlavic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SouthSlavic.java
@@ -16,11 +16,9 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 public final class SouthSlavic extends LayoutBase {
     private static final String LAYOUT_NAME = "south_slavic";
@@ -32,26 +30,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class SouthSlavicLayoutCustomizer extends LayoutCustomizer {
-        public SouthSlavicLayoutCustomizer(final Locale locale) {
-            super(locale);
-        }
-
-        @Override
-        public final ExpectedKey getAlphabetKey() { return SOUTH_SLAVIC_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0410: "А" CYRILLIC CAPITAL LETTER A
-        // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
-        // U+0412: "В" CYRILLIC CAPITAL LETTER VE
-        private static final ExpectedKey SOUTH_SLAVIC_ALPHABET_KEY = key(
-                "\u0410\u0411\u0412", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Spanish.java b/tests/src/com/android/inputmethod/keyboard/layout/Spanish.java
index 225b9f6..fc6f1ea 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Spanish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Spanish.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Swiss.java b/tests/src/com/android/inputmethod/keyboard/layout/Swiss.java
index 01a6020..57e3725 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Swiss.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Swiss.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
index 8030897..7ad7b54 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Symbols.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
@@ -41,13 +41,13 @@
                 customizer.getSingleQuoteMoreKeys(), customizer.getSingleAngleQuoteKeys())));
         if (isPhone) {
             builder.addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
-                    .addKeysOnTheRightOfRow(3, LayoutBase.DELETE_KEY)
+                    .addKeysOnTheRightOfRow(3, DELETE_KEY)
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
                     .addKeysOnTheRightOfRow(4, customizer.getEnterKey(isPhone));
         } else {
             // Tablet symbols keyboard has extra two keys at the left edge of the 3rd row.
             builder.addKeysOnTheLeftOfRow(3, (Object[])joinKeys("\\", "="));
-            builder.addKeysOnTheRightOfRow(1, LayoutBase.DELETE_KEY)
+            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
                     .addKeysOnTheRightOfRow(2, customizer.getEnterKey(isPhone))
                     .addKeysOnTheLeftOfRow(3, customizer.getSymbolsShiftKey(isPhone))
                     .addKeysOnTheRightOfRow(3, customizer.getSymbolsShiftKey(isPhone))
@@ -167,7 +167,7 @@
                     // U+00BF: "¿" INVERTED QUESTION MARK
                     key("?", moreKey("\u00BF")))
             .setKeysOfRow(4,
-                    key(","), key("_"), LayoutBase.SPACE_KEY, key("/"),
+                    key(","), key("_"), SPACE_KEY, key("/"),
                     // U+2026: "…" HORIZONTAL ELLIPSIS
                     key(".", moreKey("\u2026")))
             .build();
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
index 19cb607..6426216 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/SymbolsShifted.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout;
 
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase;
@@ -37,7 +37,7 @@
         builder.replaceKeyOfLabel(OTHER_CURRENCIES, (Object[])customizer.getOtherCurrencyKeys());
         if (isPhone) {
             builder.addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
-                    .addKeysOnTheRightOfRow(3, LayoutBase.DELETE_KEY)
+                    .addKeysOnTheRightOfRow(3, DELETE_KEY)
                     .addKeysOnTheLeftOfRow(4, customizer.getAlphabetKey())
                     .addKeysOnTheRightOfRow(4, customizer.getEnterKey(isPhone));
         } else {
@@ -45,7 +45,7 @@
             // U+00BF: "¿" INVERTED QUESTION MARK
             // U+00A1: "¡" INVERTED EXCLAMATION MARK
             builder.addKeysOnTheRightOfRow(3, (Object[])joinKeys("\u00A1", "\u00BF"));
-            builder.addKeysOnTheRightOfRow(1, LayoutBase.DELETE_KEY)
+            builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
                     .addKeysOnTheRightOfRow(2, customizer.getEnterKey(isPhone))
                     .addKeysOnTheLeftOfRow(3, customizer.getBackToSymbolsKey())
                     .addKeysOnTheRightOfRow(3, customizer.getBackToSymbolsKey())
@@ -122,7 +122,7 @@
                     // U+2264: "≤" LESS-THAN OR EQUAL TO
                     // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
                     key("<", joinMoreKeys("\u2039", "\u2264", "\u00AB")),
-                    LayoutBase.SPACE_KEY,
+                    SPACE_KEY,
                     // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
                     // U+2265: "≥" GREATER-THAN EQUAL TO
                     // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Tamil.java b/tests/src/com/android/inputmethod/keyboard/layout/Tamil.java
index 597b6fa..1413e36 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Tamil.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Tamil.java
@@ -16,11 +16,9 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Locale;
 
 /**
  * The Tamil keyboard.
@@ -35,29 +33,6 @@
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class TamilCustomizer extends LayoutCustomizer {
-        public TamilCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey getAlphabetKey() { return TAMIL_ALPHABET_KEY; }
-
-        @Override
-        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
-            return EMPTY_KEYS;
-        }
-
-        @Override
-        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
-            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
-        }
-
-        // U+0BA4: "த" TAMIL LETTER TA
-        // U+0BAE/U+0BBF: "மி" TAMIL LETTER MA/TAMIL VOWEL SIGN I
-        // U+0BB4/U+0BCD: "ழ்" TAMIL LETTER LLLA/TAMIL SIGN VIRAMA
-        private static final ExpectedKey TAMIL_ALPHABET_KEY = key(
-                "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD", Constants.CODE_SWITCH_ALPHA_SYMBOL);
-    }
-
     @Override
     ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone) { return ALPHABET_COMMON; }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Telugu.java b/tests/src/com/android/inputmethod/keyboard/layout/Telugu.java
index cc8224c..81437f3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Telugu.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Telugu.java
@@ -16,9 +16,10 @@
 
 package com.android.inputmethod.keyboard.layout;
 
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -28,15 +29,15 @@
 public final class Telugu extends LayoutBase {
     private static final String LAYOUT_NAME = "telugu";
 
-    public Telugu(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Telugu(final Locale locale) {
+        super(new TeluguCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class TeluguCustomizer extends LayoutCustomizer {
-        public TeluguCustomizer(final Locale locale) { super(locale); }
+    private static class TeluguCustomizer extends LayoutCustomizer {
+        TeluguCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getAlphabetKey() { return TELUGU_ALPHABET_KEY; }
@@ -139,8 +140,8 @@
                     key("\u0C2A", moreKey("\u0C2B")),
                     // U+0C30: "ర" TELUGU LETTER RA
                     // U+0C31: "ఱ" TELUGU LETTER RRA
-                    // U+0C43: "ృ" TELUGU VOWEL SIGN VOCALIC R
-                    key("\u0C30", joinMoreKeys("\u0C31", "\u0C43")),
+                    // U+0C4D/U+0C30: "్ర" TELUGU SIGN VIRAMA/TELUGU LETTER RA
+                    key("\u0C30", joinMoreKeys("\u0C31", "\u0C4D\u0C30")),
                     // U+0C15: "క" TELUGU LETTER KA
                     // U+0C16: "ఖ" TELUGU LETTER KHA
                     key("\u0C15", moreKey("\u0C16")),
@@ -154,18 +155,21 @@
                     // U+0C20: "ఠ" TELUGU LETTER TTHA
                     key("\u0C1F", moreKey("\u0C20")))
             .setKeysOfRow(3,
-                    // U+0C46: "ె" TELUGU VOWEL SIGN E
+                    // U+0C4A: "ొ" TELUGU VOWEL SIGN O
                     // U+0C12: "ఒ" TELUGU LETTER O
-                    key("\u0C46", moreKey("\u0C12")),
-                    // U+0C02: "ం" TELUGU SIGN ANUSVARA
+                    key("\u0C4A", moreKey("\u0C12")),
+                    // U+0C46: "ె" TELUGU VOWEL SIGN E
                     // U+0C0E: "ఎ" TELUGU LETTER E
-                    key("\u0C02", moreKey("\u0C0E")),
+                    key("\u0C46", moreKey("\u0C0E")),
                     // U+0C2E: "మ" TELUGU LETTER MA
-                    "\u0C2E",
+                    // U+0C02: "ం" TELUGU SIGN ANUSVARA
+                    // U+0C01: "ఁ" TELUGU SIGN CANDRABINDU
+                    key("\u0C2E", joinMoreKeys("\u0C02", "\u0C01")),
                     // U+0C28: "న" TELUGU LETTER NA
                     // U+0C23: "ణ" TELUGU LETTER NNA
                     // U+0C19: "ఙ" TELUGU LETTER NGA
-                    key("\u0C28", joinMoreKeys("\u0C23", "\u0C19")),
+                    // U+0C1E: "ఞ" TELUGU LETTER NYA
+                    key("\u0C28", joinMoreKeys("\u0C23", "\u0C19", "\u0C1E")),
                     // U+0C35: "వ" TELUGU LETTER VA
                     "\u0C35",
                     // U+0C32: "ల" TELUGU LETTER LA
@@ -175,8 +179,8 @@
                     // U+0C36: "శ" TELUGU LETTER SHA
                     key("\u0C38", moreKey("\u0C36")),
                     // U+0C0B: "ఋ" TELUGU LETTER VOCALIC R
-                    // U+0C4D/U+0C30: "్ర" TELUGU SIGN VIRAMA/TELUGU LETTER RA
-                    key("\u0C0B", moreKey("\u0C4D\u0C30")),
+                    // U+0C43: "ృ" TELUGU VOWEL SIGN VOCALIC R
+                    key("\u0C0B", moreKey("\u0C43")),
                     // U+0C37: "ష" TELUGU LETTER SSA
                     // U+0C15/U+0C4D/U+0C37:
                     //     "క్ష" TELUGU LETTER KA/TELUGU SIGN VIRAMA/TELUGU LETTER SSA
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
index cfda294..ce5fd80 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Thai.java
@@ -17,9 +17,10 @@
 package com.android.inputmethod.keyboard.layout;
 
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
@@ -29,15 +30,15 @@
 public final class Thai extends LayoutBase {
     private static final String LAYOUT_NAME = "thai";
 
-    public Thai(final LayoutCustomizer customizer) {
-        super(customizer, Symbols.class, SymbolsShifted.class);
+    public Thai(final Locale locale) {
+        super(new ThaiCustomizer(locale), Symbols.class, SymbolsShifted.class);
     }
 
     @Override
     public String getName() { return LAYOUT_NAME; }
 
-    public static class ThaiCustomizer extends LayoutCustomizer {
-        public ThaiCustomizer(final Locale locale) { super(locale); }
+    private static class ThaiCustomizer extends LayoutCustomizer {
+        ThaiCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public int getNumberOfRows() { return 5; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java b/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java
new file mode 100644
index 0000000..f37fd22
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Uzbek.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 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.layout;
+
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+/**
+ * The Uzbek alphabet keyboard.
+ */
+public final class Uzbek extends LayoutBase {
+    private static final String LAYOUT_NAME = "uzbek";
+
+    public Uzbek(final LayoutCustomizer customizer) {
+        super(customizer, Symbols.class, SymbolsShifted.class);
+    }
+
+    @Override
+    public String getName() { return LAYOUT_NAME; }
+
+    @Override
+    ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
+
+    public static final String ROW1_11 = "ROW1_11";
+    public static final String ROW2_10 = "ROW2_10";
+    public static final String ROW2_11 = "ROW2_11";
+
+    private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+            .setKeysOfRow(1,
+                    key("q", additionalMoreKey("1")),
+                    key("w", additionalMoreKey("2")),
+                    key("e", additionalMoreKey("3")),
+                    key("r", additionalMoreKey("4")),
+                    key("t", additionalMoreKey("5")),
+                    key("y", additionalMoreKey("6")),
+                    key("u", additionalMoreKey("7")),
+                    key("i", additionalMoreKey("8")),
+                    key("o", additionalMoreKey("9")),
+                    key("p", additionalMoreKey("0")),
+                    ROW1_11)
+            .setKeysOfRow(2, "a", "s", "d", "f", "g", "h", "j", "k", "l", ROW2_10, ROW2_11)
+            .setKeysOfRow(3, "z", "x", "c", "v", "b", "n", "m")
+            .build();
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/BengaliCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/BengaliCustomizer.java
new file mode 100644
index 0000000..f13c261
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/BengaliCustomizer.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+public class BengaliCustomizer extends LayoutCustomizer {
+    public BengaliCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getAlphabetKey() { return BENGALI_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0995: "क" BENGALI LETTER KA
+    // U+0996: "ख" BENGALI LETTER KHA
+    // U+0997: "ग" BENGALI LETTER GA
+    private static final ExpectedKey BENGALI_ALPHABET_KEY = key(
+            "\u0995\u0996\u0997", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/DanishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DanishCustomizer.java
new file mode 100644
index 0000000..3d91194
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DanishCustomizer.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class DanishCustomizer extends EuroCustomizer {
+    public DanishCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
+
+    @Override
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
+
+    @Override
+    public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
+
+    @Override
+    public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
+
+    protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW2_10, "\u00E6")
+                .setMoreKeysOf("\u00E6", "\u00E4")
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u00F8")
+                .setMoreKeysOf("\u00F8", "\u00F6");
+    }
+
+    protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a", "\u00E1", "\u00E4", "\u00E0", "\u00E2", "\u00E3", "\u0101");
+    }
+
+    protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o", "\u00F6", "\u00F3", "\u00F4", "\u00F2", "\u00F5", "\u0153",
+                        "\u014D");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setNordicKeys(builder);
+        setMoreKeysOfA(builder);
+        setMoreKeysOfO(builder);
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                .setMoreKeysOf("e", "\u00E9", "\u00EB")
+                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+                .setMoreKeysOf("y", "\u00FD", "\u00FF")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00FB", "\u00F9", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                .setMoreKeysOf("i", "\u00ED", "\u00EF")
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                .setMoreKeysOf("s", "\u00DF", "\u015B", "\u0161")
+                // U+00F0: "ð" LATIN SMALL LETTER ETH
+                .setMoreKeysOf("d", "\u00F0")
+                // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+                .setMoreKeysOf("l", "\u0142")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                .setMoreKeysOf("n", "\u00F1", "\u0144");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/DevanagariCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DevanagariCustomizer.java
new file mode 100644
index 0000000..13f9171
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DevanagariCustomizer.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+public class DevanagariCustomizer extends LayoutCustomizer {
+    public DevanagariCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getAlphabetKey() { return HINDI_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey getSymbolsKey() { return HINDI_SYMBOLS_KEY; }
+
+    @Override
+    public ExpectedKey getBackToSymbolsKey() { return HINDI_BACK_TO_SYMBOLS_KEY; }
+
+    // U+0915: "क" DEVANAGARI LETTER KA
+    // U+0916: "ख" DEVANAGARI LETTER KHA
+    // U+0917: "ग" DEVANAGARI LETTER GA
+    private static final ExpectedKey HINDI_ALPHABET_KEY = key(
+            "\u0915\u0916\u0917", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    // U+0967: "१" DEVANAGARI DIGIT ONE
+    // U+0968: "२" DEVANAGARI DIGIT TWO
+    // U+0969: "३" DEVANAGARI DIGIT THREE
+    private static final String HINDI_SYMBOLS_LABEL = "?\u0967\u0968\u0969";
+    private static final ExpectedKey HINDI_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
+            Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    private static final ExpectedKey HINDI_BACK_TO_SYMBOLS_KEY = key(HINDI_SYMBOLS_LABEL,
+            Constants.CODE_SHIFT);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/DutchCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DutchCustomizer.java
new file mode 100644
index 0000000..825afb6
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DutchCustomizer.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class DutchCustomizer extends EuroCustomizer {
+    public DutchCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
+
+    @Override
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_L9R; }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a",
+                        "\u00E1", "\u00E4", "\u00E2", "\u00E0", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101")
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e",
+                        "\u00E9", "\u00EB", "\u00EA", "\u00E8", "\u0119", "\u0117", "\u0113")
+                // U+0133: "ij" LATIN SMALL LIGATURE IJ
+                .setMoreKeysOf("y", "\u0133")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00FB", "\u00F9", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                // U+0133: "ij" LATIN SMALL LIGATURE IJ
+                .setMoreKeysOf("i",
+                        "\u00ED", "\u00EF", "\u00EC", "\u00EE", "\u012F", "\u012B", "\u0133")
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o",
+                        "\u00F3", "\u00F6", "\u00F4", "\u00F2", "\u00F5", "\u0153", "\u00F8",
+                        "\u014D")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                .setMoreKeysOf("n", "\u00F1", "\u0144");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/DvorakCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DvorakCustomizer.java
new file mode 100644
index 0000000..b7b0187
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/DvorakCustomizer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey.ExpectedAdditionalMoreKey;
+
+import java.util.Locale;
+
+public class DvorakCustomizer extends LayoutCustomizer {
+    public DvorakCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+        return isPhone ? joinKeys(SHIFT_KEY): joinKeys(SHIFT_KEY, key("q"));
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : joinKeys(key("z"), SHIFT_KEY);
+    }
+
+    @Override
+    public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
+        // U+00A1: "¡" INVERTED EXCLAMATION MARK
+        return isPhone ? joinKeys(key("q", SETTINGS_KEY))
+                : joinKeys(key("!", joinMoreKeys("\u00A1", SETTINGS_KEY)));
+    }
+
+    @Override
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        final ExpectedAdditionalMoreKey[] punctuationMoreKeys =
+                convertToAdditionalMoreKeys(getPunctuationMoreKeys(isPhone));
+        // U+00BF: "¿" INVERTED QUESTION MARK
+        return isPhone
+                ? joinKeys(key("z", punctuationMoreKeys))
+                : joinKeys(key("?", joinMoreKeys(punctuationMoreKeys, "\u00BF")));
+    }
+
+    private static ExpectedAdditionalMoreKey[] convertToAdditionalMoreKeys(
+            final ExpectedKey ... moreKeys) {
+        final ExpectedAdditionalMoreKey[] additionalMoreKeys =
+                new ExpectedAdditionalMoreKey[moreKeys.length];
+        for (int index = 0; index < moreKeys.length; index++) {
+            additionalMoreKeys[index] = ExpectedAdditionalMoreKey.newInstance(moreKeys[index]);
+        }
+        return additionalMoreKeys;
+    }
+
+    public static class EnglishDvorakCustomizer extends DvorakCustomizer {
+        private final EnglishCustomizer mEnglishCustomizer;
+
+        public EnglishDvorakCustomizer(final Locale locale) {
+            super(locale);
+            mEnglishCustomizer = new EnglishCustomizer(locale);
+        }
+
+        @Override
+        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+            return mEnglishCustomizer.setAccentedLetters(builder);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/EastSlavicCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EastSlavicCustomizer.java
new file mode 100644
index 0000000..8815b06
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EastSlavicCustomizer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+public class EastSlavicCustomizer extends LayoutCustomizer {
+    public EastSlavicCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public final ExpectedKey getAlphabetKey() { return EAST_SLAVIC_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0410: "А" CYRILLIC CAPITAL LETTER A
+    // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
+    // U+0412: "В" CYRILLIC CAPITAL LETTER VE
+    private static final ExpectedKey EAST_SLAVIC_ALPHABET_KEY = key(
+            "\u0410\u0411\u0412", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/EnglishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EnglishCustomizer.java
new file mode 100644
index 0000000..9a9c6bb
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EnglishCustomizer.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class EnglishCustomizer extends LayoutCustomizer {
+    public EnglishCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0113")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FA", "\u00FB", "\u00FC", "\u00F9", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                .setMoreKeysOf("i", "\u00ED", "\u00EE", "\u00EF", "\u012B", "\u00EC")
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                .setMoreKeysOf("o",
+                        "\u00F3", "\u00F4", "\u00F6", "\u00F2", "\u0153", "\u00F8", "\u014D",
+                        "\u00F5")
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101")
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                .setMoreKeysOf("s", "\u00DF")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                .setMoreKeysOf("c", "\u00E7")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                .setMoreKeysOf("n", "\u00F1");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/EstonianEECustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EstonianEECustomizer.java
new file mode 100644
index 0000000..a7d611a
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EstonianEECustomizer.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class EstonianEECustomizer extends EuroCustomizer {
+    public EstonianEECustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
+
+    @Override
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
+
+    protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW1_11, "\u00FC")
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                .replaceKeyOfLabel(Nordic.ROW2_10, "\u00F6")
+                .setMoreKeysOf("\u00F6", "\u00F5")
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u00E4");
+    }
+
+    protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                .setMoreKeysOf("a", "\u0101", "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u00E5",
+                        "\u00E6", "\u0105");
+    }
+
+    protected void setMoreKeysOfI(final ExpectedKeyboardBuilder builder, final int elementId) {
+        // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+        // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+        // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+        // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+        // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+        // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+        if (elementId == KeyboardId.ELEMENT_ALPHABET) {
+            builder.setMoreKeysOf("i",
+                    "\u012B", "\u00EC", "\u012F", "\u00ED", "\u00EE", "\u00EF", "\u0131");
+        } else {
+            // The upper-case letter of "ı" in Estonian locale is "I". It should be omitted
+            // from the more keys of "I".
+            builder.setMoreKeysOf("i",
+                    "\u012B", "\u00EC", "\u012F", "\u00ED", "\u00EE", "\u00EF");
+        }
+    }
+
+    protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                .setMoreKeysOf("o", "\u00F5", "\u00F2", "\u00F3", "\u00F4", "\u0153", "\u0151",
+                        "\u00F8");
+    }
+
+    protected void setMoreKeysOfU(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+                // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+                .setMoreKeysOf("u", "\u016B", "\u0173", "\u00F9", "\u00FA", "\u00FB", "\u016F",
+                        "\u0171");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder,
+            final int elementId) {
+        setNordicKeys(builder);
+        setMoreKeysOfA(builder);
+        setMoreKeysOfI(builder, elementId);
+        setMoreKeysOfO(builder);
+        setMoreKeysOfU(builder);
+        return builder
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+                .setMoreKeysOf("e",
+                        "\u0113", "\u00E8", "\u0117", "\u00E9", "\u00EA", "\u00EB", "\u0119",
+                        "\u011B")
+                // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+                // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+                // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+                .setMoreKeysOf("r", "\u0157", "\u0159", "\u0155")
+                // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+                // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+                .setMoreKeysOf("t", "\u0163", "\u0165")
+                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+                .setMoreKeysOf("y", "\u00FD", "\u00FF")
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+                .setMoreKeysOf("s", "\u0161", "\u00DF", "\u015B", "\u015F")
+                // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+                .setMoreKeysOf("d", "\u010F")
+                // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+                // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+                .setMoreKeysOf("g", "\u0123", "\u011F")
+                // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+                .setMoreKeysOf("k", "\u0137")
+                // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+                // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+                // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+                // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+                .setMoreKeysOf("l", "\u013C", "\u0142", "\u013A", "\u013E")
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+                // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+                .setMoreKeysOf("z", "\u017E", "\u017C", "\u017A")
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                .setMoreKeysOf("c", "\u010D", "\u00E7", "\u0107")
+                // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                .setMoreKeysOf("n", "\u0146", "\u00F1", "\u0144");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/EuroCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EuroCustomizer.java
new file mode 100644
index 0000000..ee0236d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/EuroCustomizer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+/**
+ * The layout customize class for countries that use Euro.
+ */
+public class EuroCustomizer extends LayoutCustomizer {
+    public EuroCustomizer(final Locale locale) {
+        super(locale);
+    }
+
+    @Override
+    public final ExpectedKey getCurrencyKey() { return Symbols.CURRENCY_EURO; }
+
+    @Override
+    public final ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_THAN_EURO;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/FinnishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/FinnishCustomizer.java
new file mode 100644
index 0000000..a792f91
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/FinnishCustomizer.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class FinnishCustomizer extends EuroCustomizer {
+    public FinnishCustomizer(final Locale locale) { super(locale); }
+
+    protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                .replaceKeyOfLabel(Nordic.ROW2_10, "\u00F6")
+                .setMoreKeysOf("\u00F6","\u00F8")
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u00E4")
+                .setMoreKeysOf("\u00E4", "\u00E6");
+    }
+
+    protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a", "\u00E6", "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u0101");
+    }
+
+    protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o", "\u00F8", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153",
+                        "\u014D");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setNordicKeys(builder);
+        setMoreKeysOfA(builder);
+        setMoreKeysOfO(builder);
+        return builder
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                .setMoreKeysOf("u", "\u00FC")
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                .setMoreKeysOf("s", "\u0161", "\u00DF", "\u015B")
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+                // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+                .setMoreKeysOf("z", "\u017E", "\u017A", "\u017C");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/FrenchCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/FrenchCustomizer.java
new file mode 100644
index 0000000..d7798cc
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/FrenchCustomizer.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class FrenchCustomizer extends LayoutCustomizer {
+    public FrenchCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setAdditionalMoreKeysPositionOf("a", 3)
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E2", "\u00E6", "\u00E1", "\u00E4", "\u00E3", "\u00E5",
+                        "\u0101", "\u00AA")
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setAdditionalMoreKeysPositionOf("e", 5)
+                .setMoreKeysOf("e",
+                        "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
+                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+                .setMoreKeysOf("y", "\u00FF")
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setAdditionalMoreKeysPositionOf("u", 3)
+                .setMoreKeysOf("u", "\u00F9", "\u00FB", "\u00FC", "\u00FA", "\u016B")
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setAdditionalMoreKeysPositionOf("i", 2)
+                .setMoreKeysOf("i", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setAdditionalMoreKeysPositionOf("o", 3)
+                .setMoreKeysOf("o",
+                        "\u00F4", "\u0153", "\u00F6", "\u00F2", "\u00F3", "\u00F5", "\u00F8",
+                        "\u014D", "\u00BA")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
+                .setAdditionalMoreKeysPositionOf("c", 2);
+    }
+
+    public static final class FrenchEuroCustomizer extends FrenchCustomizer {
+        private final EuroCustomizer mEuroCustomizer;
+
+        public FrenchEuroCustomizer(final Locale locale) {
+            super(locale);
+            mEuroCustomizer = new EuroCustomizer(locale);
+        }
+
+        @Override
+        public final ExpectedKey getCurrencyKey() { return mEuroCustomizer.getCurrencyKey(); }
+
+        @Override
+        public final ExpectedKey[] getOtherCurrencyKeys() {
+            return mEuroCustomizer.getOtherCurrencyKeys();
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/GermanCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/GermanCustomizer.java
new file mode 100644
index 0000000..e0e4c78
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/GermanCustomizer.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class GermanCustomizer extends LayoutCustomizer {
+    public GermanCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
+
+    @Override
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
+
+    @Override
+    public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
+
+    @Override
+    public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0117")
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
+                .setAdditionalMoreKeysPositionOf("u", 2)
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o",
+                        "\u00F6", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153", "\u00F8",
+                        "\u014D")
+                .setAdditionalMoreKeysPositionOf("o", 2)
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a",
+                        "\u00E4", "\u00E2", "\u00E0", "\u00E1", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101")
+                .setAdditionalMoreKeysPositionOf("a", 2)
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                .setMoreKeysOf("s", "\u00DF", "\u015B", "\u0161")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                .setMoreKeysOf("n", "\u00F1", "\u0144");
+    }
+
+    public static class GermanEuroCustomizer extends GermanCustomizer {
+        private final EuroCustomizer mEuroCustomizer;
+
+        public GermanEuroCustomizer(final Locale locale) {
+            super(locale);
+            mEuroCustomizer = new EuroCustomizer(locale);
+        }
+
+        @Override
+        public ExpectedKey getCurrencyKey() { return mEuroCustomizer.getCurrencyKey(); }
+
+        @Override
+        public ExpectedKey[] getOtherCurrencyKeys() {
+            return mEuroCustomizer.getOtherCurrencyKeys();
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/HindiCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/HindiCustomizer.java
new file mode 100644
index 0000000..c7fe9db
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/HindiCustomizer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+public class HindiCustomizer extends DevanagariCustomizer {
+    public HindiCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    @Override
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        // U+0964: "।" DEVANAGARI DANDA
+        final ExpectedKey periodKey = key("\u0964", getPunctuationMoreKeys(isPhone));
+        return joinKeys(periodKey);
+    }
+
+    @Override
+    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+        return isPhone ? HINDI_PHONE_PUNCTUATION_MORE_KEYS : HINDI_TABLET_PUNCTUATION_MORE_KEYS;
+    }
+
+    // U+20B9: "₹" INDIAN RUPEE SIGN
+    private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9",
+            Symbols.CURRENCY_GENERIC_MORE_KEYS);
+
+    // Punctuation more keys for phone form factor.
+    private static final ExpectedKey[] HINDI_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+            ",", ".", "?", "!", "#", ")", "(", "/", ";",
+            "'", "@", ":", "-", "\"", "+", "%", "&");
+    // Punctuation more keys for tablet form factor.
+    private static final ExpectedKey[] HINDI_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
+            ",", ".", "'", "#", ")", "(", "/", ";",
+            "@", ":", "-", "\"", "+", "%", "&");
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/ItalianCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/ItalianCustomizer.java
new file mode 100644
index 0000000..3b547fd
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/ItalianCustomizer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class ItalianCustomizer extends LayoutCustomizer {
+    public ItalianCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e",
+                        "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u016B")
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setMoreKeysOf("i", "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u012F", "\u012B")
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setMoreKeysOf("o",
+                        "\u00F2", "\u00F3", "\u00F4", "\u00F6", "\u00F5", "\u0153", "\u00F8",
+                        "\u014D", "\u00BA")
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
+                        "\u0101", "\u00AA");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/LayoutCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/LayoutCustomizer.java
new file mode 100644
index 0000000..27f5534
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/LayoutCustomizer.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * This class is used to customize common keyboard layout to language specific layout.
+ */
+public class LayoutCustomizer extends AbstractLayoutBase {
+    private final Locale mLocale;
+
+    // Empty keys definition to remove keys by adding this.
+    protected static final ExpectedKey[] EMPTY_KEYS = joinKeys();
+
+    public LayoutCustomizer(final Locale locale) {  mLocale = locale; }
+
+    public final Locale getLocale() { return mLocale; }
+
+    public int getNumberOfRows() { return 4; }
+
+    /**
+     * Set accented letters to a specific keyboard element.
+     * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
+     *        layout.
+     * @param elementId the element id of keyboard
+     * @return the {@link ExpectedKeyboardBuilder} object that contains accented letters as
+     *        "more keys".
+     */
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder,
+            final int elementId) {
+        // This method can be overridden by an extended class to provide customized expected
+        // accented letters depending on the shift state of keyboard.
+        // This is a default behavior to call a shift-state-independent
+        // {@link #setAccentedLetters(ExpectedKeyboardBuilder)} implementation, so that
+        // <code>elementId</code> is ignored here.
+        return setAccentedLetters(builder);
+    }
+
+    /**
+     * Set accented letters to common layout.
+     * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard
+     *        layout.
+     * @return the {@link ExpectedKeyboardBuilder} object that contains accented letters as
+     *        "more keys".
+     */
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder;
+    }
+
+    /**
+     * Get the function key to switch to alphabet layout.
+     * @return the {@link ExpectedKey} of the alphabet key.
+     */
+    public ExpectedKey getAlphabetKey() { return ALPHABET_KEY; }
+
+    /**
+     * Get the function key to switch to symbols layout.
+     * @return the {@link ExpectedKey} of the symbols key.
+     */
+    public ExpectedKey getSymbolsKey() { return SYMBOLS_KEY; }
+
+    /**
+     * Get the function key to switch to symbols shift layout.
+     * @param isPhone true if requesting phone's key.
+     * @return the {@link ExpectedKey} of the symbols shift key.
+     */
+    public ExpectedKey getSymbolsShiftKey(boolean isPhone) {
+        return isPhone ? SYMBOLS_SHIFT_KEY : TABLET_SYMBOLS_SHIFT_KEY;
+    }
+
+    /**
+     * Get the function key to switch from symbols shift to symbols layout.
+     * @return the {@link ExpectedKey} of the back to symbols key.
+     */
+    public ExpectedKey getBackToSymbolsKey() { return BACK_TO_SYMBOLS_KEY; }
+
+    /**
+     * Get the currency key.
+     * @return the {@link ExpectedKey} of the currency key.
+     */
+    public ExpectedKey getCurrencyKey() { return Symbols.CURRENCY_DOLLAR; }
+
+    /**
+     * Get other currencies keys.
+     * @return the array of {@link ExpectedKey} that represents other currency keys.
+     */
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_THAN_DOLLAR;
+    }
+
+    /**
+     * Get "more keys" of double quotation mark.
+     * @return the array of {@link ExpectedKey} of more double quotation marks in natural order.
+     */
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_9LR; }
+
+    /**
+     * Get "more keys" of single quotation mark.
+     * @return the array of {@link ExpectedKey} of more single quotation marks in natural order.
+     */
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_9LR; }
+
+    /**
+     * Get double angle quotation marks in natural order.
+     * @return the array of {@link ExpectedKey} of double angle quotation marks in natural
+     *         order.
+     */
+    public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_LR; }
+
+    /**
+     * Get single angle quotation marks in natural order.
+     * @return the array of {@link ExpectedKey} of single angle quotation marks in natural
+     *         order.
+     */
+    public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_LR; }
+
+    /**
+     * Get the left shift keys.
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that should be placed at left edge of the
+     *         keyboard.
+     */
+    public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+        return joinKeys(SHIFT_KEY);
+    }
+
+    /**
+     * Get the right shift keys.
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that should be placed at right edge of the
+     *         keyboard.
+     */
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : joinKeys(EXCLAMATION_AND_QUESTION_MARKS, SHIFT_KEY);
+    }
+
+    /**
+     * Get the enter key.
+     * @param isPhone true if requesting phone's key.
+     * @return the array of {@link ExpectedKey} that should be placed as an enter key.
+     */
+    public ExpectedKey getEnterKey(final boolean isPhone) {
+        return isPhone ? key(ENTER_KEY, EMOJI_ACTION_KEY) : ENTER_KEY;
+    }
+
+    /**
+     * Get the emoji key.
+     * @param isPhone true if requesting phone's key.
+     * @return the array of {@link ExpectedKey} that should be placed as an emoji key.
+     */
+    public ExpectedKey getEmojiKey(final boolean isPhone) {
+        return EMOJI_NORMAL_KEY;
+    }
+
+    /**
+     * Get the space keys.
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that should be placed at the center of the
+     *         keyboard.
+     */
+    public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
+        return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY);
+    }
+
+    /**
+     * Get the keys left to the spacebar.
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that should be placed at left of the spacebar.
+     */
+    public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
+        // U+002C: "," COMMA
+        return joinKeys(key("\u002C", SETTINGS_KEY));
+    }
+
+    /**
+     * Get the keys right to the spacebar.
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that should be placed at right of the spacebar.
+     */
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        final ExpectedKey periodKey = key(".", getPunctuationMoreKeys(isPhone));
+        return joinKeys(periodKey);
+    }
+
+    /**
+     * Get "more keys" for the punctuation key (usually the period key).
+     * @param isPhone true if requesting phone's keys.
+     * @return the array of {@link ExpectedKey} that are "more keys" of the punctuation key.
+     */
+    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+        return isPhone ? PHONE_PUNCTUATION_MORE_KEYS : TABLET_PUNCTUATION_MORE_KEYS;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/NepaliCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NepaliCustomizer.java
new file mode 100644
index 0000000..264322f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NepaliCustomizer.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+public class NepaliCustomizer extends DevanagariCustomizer {
+    public NepaliCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getCurrencyKey() { return CURRENCY_NEPALI; }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+    }
+
+    @Override
+    public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
+        return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY, key(ZWNJ_KEY, ZWJ_KEY));
+    }
+
+    @Override
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        // U+0964: "।" DEVANAGARI DANDA
+        final ExpectedKey periodKey = key("\u0964", getPunctuationMoreKeys(isPhone));
+        return joinKeys(periodKey);
+    }
+
+    @Override
+    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+        return isPhone ? NEPALI_PHONE_PUNCTUATION_MORE_KEYS
+                : NEPALI_TABLET_PUNCTUATION_MORE_KEYS;
+    }
+
+    // U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN
+    private static final ExpectedKey CURRENCY_NEPALI = key("\u0930\u0941\u002E",
+            Symbols.DOLLAR_SIGN, Symbols.CENT_SIGN, Symbols.EURO_SIGN, Symbols.POUND_SIGN,
+            Symbols.YEN_SIGN, Symbols.PESO_SIGN);
+
+    // Punctuation more keys for phone form factor.
+    private static final ExpectedKey[] NEPALI_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+            ".", ",", "?", "!", "#", ")", "(", "/", ";",
+            "'", "@", ":", "-", "\"", "+", "%", "&");
+    // Punctuation more keys for tablet form factor.
+    private static final ExpectedKey[] NEPALI_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
+            ".", ",", "'", "#", ")", "(", "/", ";",
+            "@", ":", "-", "\"", "+", "%", "&");
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/NoLanguageCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NoLanguageCustomizer.java
new file mode 100644
index 0000000..b6bf5bf
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NoLanguageCustomizer.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class NoLanguageCustomizer extends LayoutCustomizer {
+    public NoLanguageCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
+                .setMoreKeysOf("w", "\u0175")
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
+                .setMoreKeysOf("e",
+                        "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0113", "\u0115", "\u0117",
+                        "\u0119", "\u011B")
+                // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
+                // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
+                // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+                .setMoreKeysOf("r", "\u0155", "\u0157", "\u0159")
+                // U+00FE: "þ" LATIN SMALL LETTER THORN
+                // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
+                // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+                // U+0167: "ŧ" LATIN SMALL LETTER T WITH STROKE
+                .setMoreKeysOf("t", "\u00FE", "\u0163", "\u0165", "\u0167")
+                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+                // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
+                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+                // U+0133: "ij" LATIN SMALL LIGATURE IJ
+                .setMoreKeysOf("y", "\u00FD", "\u0177", "\u00FF", "\u0133")
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                // U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE
+                // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+                // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+                // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+                .setMoreKeysOf("u",
+                        "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u0169", "\u016B", "\u016D",
+                        "\u016F", "\u0171", "\u0173")
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                // U+012D: "ĭ" LATIN SMALL LETTER I WITH BREVE
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+                // U+0133: "ij" LATIN SMALL LIGATURE IJ
+                .setMoreKeysOf("i",
+                        "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u0129", "\u012B", "\u012D",
+                        "\u012F", "\u0131", "\u0133")
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+014F: "ŏ" LATIN SMALL LETTER O WITH BREVE
+                // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setMoreKeysOf("o",
+                        "\u00F2", "\u00F3", "\u00F4", "\u00F5", "\u00F6", "\u00F8", "\u014D",
+                        "\u014F", "\u0151", "\u0153", "\u00BA")
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
+                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setMoreKeysOf("a",
+                        "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u00E4", "\u00E5", "\u00E6",
+                        "\u0101", "\u0103", "\u0105", "\u00AA")
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
+                // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                // U+017F: "ſ" LATIN SMALL LETTER LONG S
+                .setMoreKeysOf("s", "\u00DF", "\u015B", "\u015D", "\u015F", "\u0161", "\u017F")
+                // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+                // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+                // U+00F0: "ð" LATIN SMALL LETTER ETH
+                .setMoreKeysOf("d", "\u010F", "\u0111", "\u00F0")
+                // U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX
+                // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+                // U+0121: "ġ" LATIN SMALL LETTER G WITH DOT ABOVE
+                // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
+                .setMoreKeysOf("g", "\u011D", "\u011F", "\u0121", "\u0123")
+                // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
+                .setMoreKeysOf("h", "\u0125")
+                // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
+                .setMoreKeysOf("j", "\u0135")
+                // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
+                // U+0138: "ĸ" LATIN SMALL LETTER KRA
+                .setMoreKeysOf("k", "\u0137", "\u0138")
+                // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
+                // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
+                // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
+                // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT
+                // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+                .setMoreKeysOf("l", "\u013A", "\u013C", "\u013E", "\u0140", "\u0142")
+                // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+                // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                .setMoreKeysOf("z", "\u017A", "\u017C", "\u017E")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
+                // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u0109", "\u010B", "\u010D")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
+                // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+                // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+                // U+014B: "ŋ" LATIN SMALL LETTER ENG
+                .setMoreKeysOf("n", "\u00F1", "\u0144", "\u0146", "\u0148", "\u0149", "\u014B");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/NorwegianCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NorwegianCustomizer.java
new file mode 100644
index 0000000..6cc44e5
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/NorwegianCustomizer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class NorwegianCustomizer extends LayoutCustomizer {
+    public NorwegianCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
+
+    @Override
+    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_L9R; }
+
+    protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW2_10, "\u00F8")
+                .setMoreKeysOf("\u00F8", "\u00F6")
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u00E6")
+                .setMoreKeysOf("\u00E6", "\u00E4");
+    }
+
+    protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                .setMoreKeysOf("a", "\u00E4", "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u0101");
+    }
+
+    protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o", "\u00F6", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153",
+                        "\u014D");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setNordicKeys(builder);
+        setMoreKeysOfA(builder);
+        setMoreKeysOfO(builder);
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e",
+                        "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/PcQwertyCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/PcQwertyCustomizer.java
new file mode 100644
index 0000000..9a0f764
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/PcQwertyCustomizer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+public class PcQwertyCustomizer extends LayoutCustomizer {
+    public PcQwertyCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public int getNumberOfRows() { return 5; }
+
+    @Override
+    public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+        return joinKeys(SHIFT_KEY);
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return joinKeys(SHIFT_KEY);
+    }
+
+    @Override
+    public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
+        return joinKeys(SETTINGS_KEY);
+    }
+
+    @Override
+    public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+        return isPhone
+                ? joinKeys(key(ENTER_KEY, EMOJI_ACTION_KEY))
+                : joinKeys(EMOJI_NORMAL_KEY);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/PortugueseCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/PortugueseCustomizer.java
new file mode 100644
index 0000000..4fc64cc
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/PortugueseCustomizer.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class PortugueseCustomizer extends LayoutCustomizer {
+    public PortugueseCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                .setMoreKeysOf("e",
+                        "\u00E9", "\u00EA", "\u00E8", "\u0119", "\u0117", "\u0113", "\u00EB")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00F9", "\u00FB", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setMoreKeysOf("i", "\u00ED", "\u00EE", "\u00EC", "\u00EF", "\u012F", "\u012B")
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setMoreKeysOf("o",
+                        "\u00F3", "\u00F5", "\u00F4", "\u00F2", "\u00F6", "\u0153", "\u00F8",
+                        "\u014D", "\u00BA")
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setMoreKeysOf("a",
+                        "\u00E1", "\u00E3", "\u00E0", "\u00E2", "\u00E4", "\u00E5", "\u00E6",
+                        "\u00AA")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                .setMoreKeysOf("c", "\u00E7", "\u010D", "\u0107");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/SerbianLatinCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SerbianLatinCustomizer.java
new file mode 100644
index 0000000..4d03c8b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SerbianLatinCustomizer.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.SerbianQwertz;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class SerbianLatinCustomizer extends LayoutCustomizer {
+    public SerbianLatinCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    protected void setSerbianKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                .replaceKeyOfLabel(SerbianQwertz.ROW1_11, "\u0161")
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .replaceKeyOfLabel(SerbianQwertz.ROW2_10, "\u010D")
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                .replaceKeyOfLabel(SerbianQwertz.ROW2_11, "\u0107")
+                // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+                .replaceKeyOfLabel(SerbianQwertz.ROW3_8, "\u0111")
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                .replaceKeyOfLabel(SerbianQwertz.ROW3_9, "\u017E");
+    }
+
+    @SuppressWarnings("unused")
+    protected void setMoreKeysOfS(final ExpectedKeyboardBuilder builder) {
+        // Serbian QWERTZ has a dedicated "š" key.
+    }
+
+    @SuppressWarnings("unused")
+    protected void setMoreKeysOfC(final ExpectedKeyboardBuilder builder) {
+        // Serbian QWERTZ has a dedicated "č" and "ć" keys.
+    }
+
+    @SuppressWarnings("unused")
+    protected void setMoreKeysOfD(final ExpectedKeyboardBuilder builder) {
+        // Serbian QWERTZ has a dedicated "đ" key.
+    }
+
+    @SuppressWarnings("unused")
+    protected void setMoreKeysOfZ(final ExpectedKeyboardBuilder builder) {
+        // Serbian QWERTZ has a dedicated "ž" key.
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setSerbianKeys(builder);
+        setMoreKeysOfS(builder);
+        setMoreKeysOfC(builder);
+        setMoreKeysOfD(builder);
+        setMoreKeysOfZ(builder);
+        return builder
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                .setMoreKeysOf("e", "\u00E8")
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                .setMoreKeysOf("i", "\u00EC");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/SouthSlavicLayoutCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SouthSlavicLayoutCustomizer.java
new file mode 100644
index 0000000..bec8160
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SouthSlavicLayoutCustomizer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+public class SouthSlavicLayoutCustomizer extends LayoutCustomizer {
+    public SouthSlavicLayoutCustomizer(final Locale locale) {
+        super(locale);
+    }
+
+    @Override
+    public final ExpectedKey getAlphabetKey() { return SOUTH_SLAVIC_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0410: "А" CYRILLIC CAPITAL LETTER A
+    // U+0411: "Б" CYRILLIC CAPITAL LETTER BE
+    // U+0412: "В" CYRILLIC CAPITAL LETTER VE
+    private static final ExpectedKey SOUTH_SLAVIC_ALPHABET_KEY = key(
+            "\u0410\u0411\u0412", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/SpanishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SpanishCustomizer.java
new file mode 100644
index 0000000..1284f05
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SpanishCustomizer.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class SpanishCustomizer extends LayoutCustomizer {
+    public SpanishCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+        return isPhone ? SPANISH_PHONE_PUNCTUATION_MORE_KEYS : TABLET_PUNCTUATION_MORE_KEYS;
+    }
+
+    // Punctuation more keys for phone form factor.
+    private static final ExpectedKey[] SPANISH_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+            // U+00A1: "¡" INVERTED EXCLAMATION MARK
+            // U+00BF: "¿" INVERTED QUESTION MARK
+            ",", "?", "!", "#", ")", "(", "/", ";", "\u00A1",
+            "'", "@", ":", "-", "\"", "+", "%", "&", "\u00BF");
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
+                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
+                .setMoreKeysOf("e",
+                        "\u00E9", "\u00E8", "\u00EB", "\u00EA", "\u0119", "\u0117", "\u0113")
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00F9", "\u00FB", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setMoreKeysOf("i", "\u00ED", "\u00EF", "\u00EC", "\u00EE", "\u012F", "\u012B")
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
+                .setMoreKeysOf("o",
+                        "\u00F3", "\u00F2", "\u00F6", "\u00F4", "\u00F5", "\u00F8", "\u0153",
+                        "\u014D", "\u00BA")
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
+                .setMoreKeysOf("a",
+                        "\u00E1", "\u00E0", "\u00E4", "\u00E2", "\u00E3", "\u00E5", "\u0105",
+                        "\u00E6", "\u0101", "\u00AA")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                .replaceKeyOfLabel(Spanish.ROW2_10, "\u00F1")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                .setMoreKeysOf("n", "\u00F1", "\u0144");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/SwedishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SwedishCustomizer.java
new file mode 100644
index 0000000..f4ff594
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/SwedishCustomizer.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class SwedishCustomizer extends LayoutCustomizer {
+    private final LayoutCustomizer mEuroCustomizer;
+
+    public SwedishCustomizer(final Locale locale) {
+        super(locale);
+        mEuroCustomizer = new EuroCustomizer(locale);
+    }
+
+    @Override
+    public ExpectedKey getCurrencyKey() {
+        return mEuroCustomizer.getCurrencyKey();
+    }
+
+    @Override
+    public ExpectedKey[] getOtherCurrencyKeys() {
+        return mEuroCustomizer.getOtherCurrencyKeys();
+    }
+
+    @Override
+    public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
+
+    @Override
+    public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
+
+    protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                .replaceKeyOfLabel(Nordic.ROW2_10, "\u00F6")
+                .setMoreKeysOf("\u00F6", "\u00F8", "\u0153")
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u00E4")
+                .setMoreKeysOf("\u00E4", "\u00E6");
+    }
+
+    protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00E6: "æ" LATIN SMALL LETTER AE
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                .setMoreKeysOf("a", "\u00E6", "\u00E1", "\u00E0", "\u00E2", "\u0105", "\u00E3");
+    }
+
+    protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o", "\u00F8", "\u0153", "\u00F3", "\u00F2", "\u00F4", "\u00F5",
+                        "\u014D");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setNordicKeys(builder);
+        setMoreKeysOfA(builder);
+        setMoreKeysOfO(builder);
+        return builder
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
+                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
+                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
+                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119")
+                // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
+                .setMoreKeysOf("r", "\u0159")
+                // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
+                // U+00FE: "þ" LATIN SMALL LETTER THORN
+                .setMoreKeysOf("t", "\u0165", "\u00FE")
+                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
+                .setMoreKeysOf("y", "\u00FD", "\u00FF")
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FC", "\u00FA", "\u00F9", "\u00FB", "\u016B")
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                .setMoreKeysOf("i", "\u00ED", "\u00EC", "\u00EE", "\u00EF")
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                .setMoreKeysOf("s", "\u015B", "\u0161", "\u015F", "\u00DF")
+                // U+00F0: "ð" LATIN SMALL LETTER ETH
+                // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
+                .setMoreKeysOf("d", "\u00F0", "\u010F")
+                // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
+                .setMoreKeysOf("l", "\u0142")
+                // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
+                .setMoreKeysOf("z", "\u017A", "\u017E", "\u017C")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
+                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+                .setMoreKeysOf("n", "\u0144", "\u00F1", "\u0148");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/TamilCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/TamilCustomizer.java
new file mode 100644
index 0000000..de82aaf
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/TamilCustomizer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.Locale;
+
+public class TamilCustomizer extends LayoutCustomizer {
+    public TamilCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKey getAlphabetKey() { return TAMIL_ALPHABET_KEY; }
+
+    @Override
+    public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+        return EMPTY_KEYS;
+    }
+
+    @Override
+    public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+        return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+    }
+
+    // U+0BA4: "த" TAMIL LETTER TA
+    // U+0BAE/U+0BBF: "மி" TAMIL LETTER MA/TAMIL VOWEL SIGN I
+    // U+0BB4/U+0BCD: "ழ்" TAMIL LETTER LLLA/TAMIL SIGN VIRAMA
+    private static final ExpectedKey TAMIL_ALPHABET_KEY = key(
+            "\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/TurkicCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/TurkicCustomizer.java
new file mode 100644
index 0000000..3fd3aa2
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/TurkicCustomizer.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * Turkic languages layout customizer.
+ */
+public class TurkicCustomizer extends LayoutCustomizer {
+    public TurkicCustomizer(final Locale locale) { super(locale); }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        return builder
+                // U+0259: "ə" LATIN SMALL LETTER SCHWA
+                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
+                .setMoreKeysOf("e", "\u0259", "\u00E9")
+                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
+                .setMoreKeysOf("y", "\u00FD")
+                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
+                // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                .setMoreKeysOf("i",
+                        "\u0131", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
+                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                // U+0153: "œ" LATIN SMALL LIGATURE OE
+                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                .setMoreKeysOf("o",
+                        "\u00F6", "\u00F4", "\u0153", "\u00F2", "\u00F3", "\u00F5", "\u00F8",
+                        "\u014D")
+                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                .setMoreKeysOf("a", "\u00E2", "\u00E4", "\u00E1")
+                // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                .setMoreKeysOf("s", "\u015F", "\u00DF", "\u015B", "\u0161")
+                // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
+                .setMoreKeysOf("g", "\u011F")
+                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                .setMoreKeysOf("z", "\u017E")
+                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
+                // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+                .setMoreKeysOf("n", "\u0148", "\u00F1");
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/customizer/UzbekCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/customizer/UzbekCustomizer.java
new file mode 100644
index 0000000..9948616
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/customizer/UzbekCustomizer.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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.layout.customizer;
+
+import com.android.inputmethod.keyboard.layout.Nordic;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+public class UzbekCustomizer extends TurkicCustomizer {
+    public UzbekCustomizer(final Locale locale) { super(locale); }
+
+    protected void setUzbekKeys(final ExpectedKeyboardBuilder builder) {
+        builder
+                // U+006F/U+02BB: "oʻ" LATIN SMALL LETTER O/MODIFIER LETTER TURNED COMMA
+                .replaceKeyOfLabel(Nordic.ROW1_11, "o\u02BB")
+                // U+0067/U+02BB: "gʻ" LATIN SMALL LETTER G/MODIFIER LETTER TURNED COMMA
+                .replaceKeyOfLabel(Nordic.ROW2_10, "g\u02BB")
+                // U+02BC: "ʼ" MODIFIER LETTER APOSTROPHE
+                .replaceKeyOfLabel(Nordic.ROW2_11, "\u02BC");
+    }
+
+    @Override
+    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
+        setUzbekKeys(builder);
+        return super.setAccentedLetters(builder);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
index 3556cb4..2232548 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/AbstractLayoutBase.java
@@ -16,7 +16,9 @@
 
 package com.android.inputmethod.keyboard.layout.expected;
 
+import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey.ExpectedAdditionalMoreKey;
+import com.android.inputmethod.latin.common.Constants;
 
 /**
  * Base class to create an expected keyboard for unit test.
@@ -102,4 +104,75 @@
     public static ExpectedKey[] joinKeys(final Object ... keys) {
         return ExpectedKeyboardBuilder.joinKeys(keys);
     }
+
+    // Icon ids.
+    private static final int ICON_DELETE = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_DELETE_KEY);
+    private static final int ICON_SPACE = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_SPACE_KEY);
+    private static final int ICON_TAB = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_TAB_KEY);
+    private static final int ICON_SHORTCUT = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_SHORTCUT_KEY);
+    private static final int ICON_SETTINGS = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_SETTINGS_KEY);
+    private static final int ICON_LANGUAGE_SWITCH = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_LANGUAGE_SWITCH_KEY);
+    private static final int ICON_ENTER = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_ENTER_KEY);
+    private static final int ICON_EMOJI_ACTION = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_EMOJI_ACTION_KEY);
+    private static final int ICON_EMOJI_NORMAL = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY);
+    private static final int ICON_SHIFT = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_SHIFT_KEY);
+    private static final int ICON_SHIFTED_SHIFT = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_SHIFT_KEY_SHIFTED);
+    private static final int ICON_ZWNJ = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_ZWNJ_KEY);
+    private static final int ICON_ZWJ = KeyboardIconsSet.getIconId(
+            KeyboardIconsSet.NAME_ZWJ_KEY);
+
+    // Functional keys.
+    protected static final ExpectedKey DELETE_KEY = key(ICON_DELETE, Constants.CODE_DELETE);
+    protected static final ExpectedKey TAB_KEY = key(ICON_TAB, Constants.CODE_TAB);
+    protected static final ExpectedKey SHORTCUT_KEY = key(ICON_SHORTCUT, Constants.CODE_SHORTCUT);
+    protected static final ExpectedKey SETTINGS_KEY = key(ICON_SETTINGS, Constants.CODE_SETTINGS);
+    protected static final ExpectedKey LANGUAGE_SWITCH_KEY = key(
+            ICON_LANGUAGE_SWITCH, Constants.CODE_LANGUAGE_SWITCH);
+    protected static final ExpectedKey ENTER_KEY = key(ICON_ENTER, Constants.CODE_ENTER);
+    protected static final ExpectedKey EMOJI_ACTION_KEY = key(ICON_EMOJI_ACTION, Constants.CODE_EMOJI);
+    protected static final ExpectedKey EMOJI_NORMAL_KEY = key(ICON_EMOJI_NORMAL, Constants.CODE_EMOJI);
+    protected static final ExpectedKey SPACE_KEY = key(ICON_SPACE, Constants.CODE_SPACE);
+    protected static final ExpectedKey CAPSLOCK_MORE_KEY = key(" ", Constants.CODE_CAPSLOCK);
+    protected static final ExpectedKey SHIFT_KEY = key(ICON_SHIFT,
+            Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY);
+    protected static final ExpectedKey SHIFTED_SHIFT_KEY = key(ICON_SHIFTED_SHIFT,
+            Constants.CODE_SHIFT, CAPSLOCK_MORE_KEY);
+    protected static final ExpectedKey ALPHABET_KEY = key("ABC", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    protected static final ExpectedKey SYMBOLS_KEY = key("?123", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+    protected static final ExpectedKey BACK_TO_SYMBOLS_KEY = key("?123", Constants.CODE_SHIFT);
+    protected static final ExpectedKey SYMBOLS_SHIFT_KEY = key("= \\ <", Constants.CODE_SHIFT);
+    protected static final ExpectedKey TABLET_SYMBOLS_SHIFT_KEY = key("~ [ <", Constants.CODE_SHIFT);
+
+    // U+00A1: "¡" INVERTED EXCLAMATION MARK
+    // U+00BF: "¿" INVERTED QUESTION MARK
+    protected static final ExpectedKey[] EXCLAMATION_AND_QUESTION_MARKS = joinKeys(
+            key("!", moreKey("\u00A1")), key("?", moreKey("\u00BF")));
+    // U+200C: ZERO WIDTH NON-JOINER
+    // U+200D: ZERO WIDTH JOINER
+    protected static final ExpectedKey ZWNJ_KEY = key(ICON_ZWNJ, "\u200C");
+    protected static final ExpectedKey ZWJ_KEY = key(ICON_ZWJ, "\u200D");
+    // Domain key
+    protected static final ExpectedKey DOMAIN_KEY =
+            key(".com", joinMoreKeys(".net", ".org", ".gov", ".edu")).preserveCase();
+
+    // Punctuation more keys for phone form factor.
+    protected static final ExpectedKey[] PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+            ",", "?", "!", "#", ")", "(", "/", ";",
+            "'", "@", ":", "-", "\"", "+", "%", "&");
+    // Punctuation more keys for tablet form factor.
+    protected static final ExpectedKey[] TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
+            ",", "'", "#", ")", "(", "/", ";",
+            "@", ":", "-", "\"", "+", "%", "&");
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java
index 5614918..2a040f5 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ActualKeyboardBuilder.java
@@ -19,12 +19,15 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 /**
  * This class builds an actual keyboard for unit test.
  *
@@ -98,9 +101,13 @@
 
         @Override
         public String stringize(final MoreKeySpec spec) {
+            if (spec == null) {
+                return "null";
+            }
             return toString(spec.mLabel, spec.mIconId, spec.mOutputText, spec.mCode);
         }
 
+        @Nonnull
         static String toString(final String label, final int iconId, final String outputText,
                 final int code) {
             final String visual = (iconId != KeyboardIconsSet.ICON_UNDEFINED)
@@ -125,7 +132,7 @@
         static final KeyStringizer STRINGIZER = new KeyStringizer();
 
         @Override
-        public String stringize(final Key key) {
+        public String stringize(@Nullable final Key key) {
             if (key == null) {
                 return "NULL";
             }
@@ -150,7 +157,8 @@
      * @param key the key to be converted to string.
      * @return the human readable representation of <code>key</code>.
      */
-    public static String toString(final Key key) {
+    @Nonnull
+    public static String toString(@Nullable final Key key) {
         return KeyStringizer.STRINGIZER.stringize(key);
     }
 
@@ -159,7 +167,8 @@
      * @param keys the keyboard row to be converted to string.
      * @return the human readable representation of <code>keys</code>.
      */
-    public static String toString(final Key[] keys) {
+    @Nonnull
+    public static String toString(@Nullable final Key[] keys) {
         return KeyStringizer.STRINGIZER.join(keys);
     }
 
@@ -168,7 +177,7 @@
         static final KeyArrayStringizer STRINGIZER = new KeyArrayStringizer();
 
         @Override
-        public String stringize(final Key[] keyArray) {
+        public String stringize(@Nullable final Key[] keyArray) {
             return KeyStringizer.STRINGIZER.join(keyArray);
         }
     }
@@ -178,7 +187,8 @@
      * @param rows the keyboard to be converted to string.
      * @return the human readable representation of <code>rows</code>.
      */
-    public static String toString(final Key[][] rows) {
+    @Nonnull
+    public static String toString(@Nullable final Key[][] rows) {
         return KeyArrayStringizer.STRINGIZER.join(rows, "\n" /* delimiter */);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
index 2674a6a..5c147a3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
@@ -105,11 +105,11 @@
     // The expected output of this key.
     private final ExpectedKeyOutput mOutput;
 
-    public final ExpectedKeyVisual getVisual() {
+    protected final ExpectedKeyVisual getVisual() {
         return mVisual;
     }
 
-    public final ExpectedKeyOutput getOutput() {
+    protected final ExpectedKeyOutput getOutput() {
         return mOutput;
     }
 
@@ -162,18 +162,19 @@
 
     public boolean equalsTo(final Key key) {
         // This key has no "more keys".
-        return mVisual.equalsTo(key) && mOutput.equalsTo(key) && key.getMoreKeys() == null;
+        return mVisual.hasSameKeyVisual(key) && mOutput.hasSameKeyOutput(key)
+                && key.getMoreKeys() == null;
     }
 
     public boolean equalsTo(final MoreKeySpec moreKeySpec) {
-        return mVisual.equalsTo(moreKeySpec) && mOutput.equalsTo(moreKeySpec);
+        return mVisual.hasSameKeyVisual(moreKeySpec) && mOutput.hasSameKeyOutput(moreKeySpec);
     }
 
     @Override
     public boolean equals(final Object object) {
         if (object instanceof ExpectedKey) {
             final ExpectedKey key = (ExpectedKey) object;
-            return mVisual.equalsTo(key.mVisual) && mOutput.equalsTo(key.mOutput)
+            return mVisual.hasSameKeyVisual(key.mVisual) && mOutput.hasSameKeyOutput(key.mOutput)
                     && Arrays.equals(getMoreKeys(), key.getMoreKeys());
         }
         return false;
@@ -190,7 +191,7 @@
 
     @Override
     public String toString() {
-        if (mVisual.equalsTo(mOutput)) {
+        if (mVisual.hasSameKeyVisual(mOutput)) {
             return mVisual.toString();
         }
         return mVisual + "|" + mOutput;
@@ -274,7 +275,7 @@
 
         @Override
         public boolean equalsTo(final Key key) {
-            if (getVisual().equalsTo(key) && getOutput().equalsTo(key)) {
+            if (getVisual().hasSameKeyVisual(key) && getOutput().hasSameKeyOutput(key)) {
                 final MoreKeySpec[] moreKeySpecs = key.getMoreKeys();
                 final ExpectedKey[] moreKeys = getMoreKeys();
                 // This key should have at least one "more key".
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
index 8b2bb42..e7b0f09 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
@@ -18,8 +18,8 @@
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.Locale;
 
@@ -43,10 +43,10 @@
 
     abstract ExpectedKeyOutput toUpperCase(final Locale locale);
     abstract ExpectedKeyOutput preserveCase();
-    abstract boolean equalsTo(final String text);
-    abstract boolean equalsTo(final Key key);
-    abstract boolean equalsTo(final MoreKeySpec moreKeySpec);
-    abstract boolean equalsTo(final ExpectedKeyOutput output);
+    abstract boolean hasSameKeyOutput(final String text);
+    abstract boolean hasSameKeyOutput(final Key key);
+    abstract boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec);
+    abstract boolean hasSameKeyOutput(final ExpectedKeyOutput output);
 
     /**
      * This class represents an integer code point.
@@ -63,8 +63,7 @@
                 final String codeString = StringUtils.newSingleCodePointString(mCode);
                 // A letter may have an upper case counterpart that consists of multiple code
                 // points, for instance the upper case of "ß" is "SS".
-                return newInstance(StringUtils.toUpperCaseOfStringForLocale(
-                        codeString, true /* needsToUpperCase */, locale));
+                return newInstance(StringUtils.toTitleCaseOfKeyLabel(codeString, locale));
             }
             // A special negative value has no upper case.
             return this;
@@ -76,22 +75,22 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyOutput(final String text) {
             return StringUtils.codePointCount(text) == 1 && text.codePointAt(0) == mCode;
         }
 
         @Override
-        boolean equalsTo(final Key key) {
+        boolean hasSameKeyOutput(final Key key) {
             return mCode == key.getCode();
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
+        boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) {
             return mCode == moreKeySpec.mCode;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyOutput(final ExpectedKeyOutput output) {
             return (output instanceof Code) && mCode == ((Code)output).mCode;
         }
 
@@ -131,24 +130,24 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyOutput(final String text) {
             return text.equals(text);
         }
 
         @Override
-        boolean equalsTo(final Key key) {
+        boolean hasSameKeyOutput(final Key key) {
             return key.getCode() == Constants.CODE_OUTPUT_TEXT
                     && mText.equals(key.getOutputText());
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
+        boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) {
             return moreKeySpec.mCode == Constants.CODE_OUTPUT_TEXT
                     && mText.equals(moreKeySpec.mOutputText);
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyOutput(final ExpectedKeyOutput output) {
             return (output instanceof Text) && mText == ((Text)output).mText;
         }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
index 34024a5..3f9f12a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
@@ -19,7 +19,7 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 
 import java.util.Locale;
 
@@ -28,22 +28,24 @@
  *
  * There are two types of expected visual, an integer icon id and a string label.
  */
-abstract class ExpectedKeyVisual {
-    static ExpectedKeyVisual newInstance(final String label) {
+public abstract class ExpectedKeyVisual {
+    public static ExpectedKeyVisual newInstance(final String label) {
         return new Label(label);
     }
 
-    static ExpectedKeyVisual newInstance(final int iconId) {
+    public static ExpectedKeyVisual newInstance(final int iconId) {
         return new Icon(iconId);
     }
 
+    public abstract int getIconId();
+    public abstract String getLabel();
     abstract ExpectedKeyVisual toUpperCase(final Locale locale);
     abstract ExpectedKeyVisual preserveCase();
-    abstract boolean equalsTo(final String text);
-    abstract boolean equalsTo(final Key key);
-    abstract boolean equalsTo(final MoreKeySpec moreKeySpec);
-    abstract boolean equalsTo(final ExpectedKeyOutput output);
-    abstract boolean equalsTo(final ExpectedKeyVisual visual);
+    abstract boolean hasSameKeyVisual(final String text);
+    abstract boolean hasSameKeyVisual(final Key key);
+    abstract boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec);
+    abstract boolean hasSameKeyVisual(final ExpectedKeyOutput output);
+    abstract boolean hasSameKeyVisual(final ExpectedKeyVisual visual);
 
     /**
      * This class represents an integer icon id.
@@ -56,6 +58,16 @@
         }
 
         @Override
+        public int getIconId() {
+            return mIconId;
+        }
+
+        @Override
+        public String getLabel() {
+            return null;
+        }
+
+        @Override
         ExpectedKeyVisual toUpperCase(final Locale locale) {
             return this;
         }
@@ -66,27 +78,32 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyVisual(final String text) {
             return false;
         }
 
         @Override
-        boolean equalsTo(final Key key) {
-            return mIconId == key.getIconId();
+        boolean hasSameKeyVisual(final Key key) {
+            // If the actual key has an icon as its visual, a label has to be null.
+            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
+            return mIconId == key.getIconId() && key.getLabel() == null;
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
-            return mIconId == moreKeySpec.mIconId;
+        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
+            // If the actual more key has an icon as its visual, a label has to be null.
+            // See {@link KeySpecParser#getIconId(String)} and
+            // {@link KeySpecParser#getLabel(String)}.
+            return mIconId == moreKeySpec.mIconId && moreKeySpec.mLabel == null;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
             return false;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyVisual visual) {
+        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
             return (visual instanceof Icon) && mIconId == ((Icon)visual).mIconId;
         }
 
@@ -102,12 +119,23 @@
     private static class Label extends ExpectedKeyVisual {
         private final String mLabel;
 
-        Label(final String label) { mLabel = label; }
+        Label(final String label) {
+            mLabel = label;
+        }
+
+        @Override
+        public int getIconId() {
+            return KeyboardIconsSet.ICON_UNDEFINED;
+        }
+
+        @Override
+        public String getLabel() {
+            return mLabel;
+        }
 
         @Override
         ExpectedKeyVisual toUpperCase(final Locale locale) {
-            return new Label(StringUtils.toUpperCaseOfStringForLocale(
-                    mLabel, true /* needsToUpperCase */, locale));
+            return new Label(StringUtils.toTitleCaseOfKeyLabel(mLabel, locale));
         }
 
         @Override
@@ -116,27 +144,34 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyVisual(final String text) {
             return mLabel.equals(text);
         }
 
         @Override
-        boolean equalsTo(final Key key) {
-            return mLabel.equals(key.getLabel());
+        boolean hasSameKeyVisual(final Key key) {
+            // If the actual key has a label as its visual, an icon has to be undefined.
+            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
+            return mLabel.equals(key.getLabel())
+                    && key.getIconId() == KeyboardIconsSet.ICON_UNDEFINED;
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
-            return mLabel.equals(moreKeySpec.mLabel);
+        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
+            // If the actual more key has a label as its visual, an icon has to be undefined.
+            // See {@link KeySpecParser#getIconId(String)} and
+            // {@link KeySpecParser#getLabel(String)}.
+            return mLabel.equals(moreKeySpec.mLabel)
+                    && moreKeySpec.mIconId == KeyboardIconsSet.ICON_UNDEFINED;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
-            return output.equalsTo(mLabel);
+        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
+            return output.hasSameKeyOutput(mLabel);
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyVisual visual) {
+        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
             return (visual instanceof Label) && mLabel.equals(((Label)visual).mLabel);
         }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
index 9b7de88..f5531c9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
@@ -91,7 +91,7 @@
             ExpectedKey[] keys = getRowAt(row);
             for (int columnIndex = 0; columnIndex < keys.length; /* nothing */) {
                 final ExpectedKey currentKey = keys[columnIndex];
-                if (!currentKey.getVisual().equalsTo(visual)) {
+                if (!currentKey.getVisual().hasSameKeyVisual(visual)) {
                     columnIndex++;
                     continue;
                 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java
deleted file mode 100644
index 3e82f65..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/EnglishCustomizer.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class EnglishCustomizer extends LayoutCustomizer {
-    EnglishCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0113")
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setMoreKeysOf("u", "\u00FA", "\u00FB", "\u00FC", "\u00F9", "\u016B")
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                .setMoreKeysOf("i", "\u00ED", "\u00EE", "\u00EF", "\u012B", "\u00EC")
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                .setMoreKeysOf("o",
-                        "\u00F3", "\u00F4", "\u00F6", "\u00F2", "\u0153", "\u00F8", "\u014D",
-                        "\u00F5")
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                .setMoreKeysOf("a",
-                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
-                        "\u0101")
-                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                .setMoreKeysOf("s", "\u00DF")
-                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                .setMoreKeysOf("c", "\u00E7")
-                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                .setMoreKeysOf("n", "\u00F1");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/FrenchCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/FrenchCustomizer.java
deleted file mode 100644
index ab90267..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/FrenchCustomizer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class FrenchCustomizer extends LayoutCustomizer {
-    FrenchCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                .setAdditionalMoreKeysPositionOf("a", 3)
-                .setMoreKeysOf("a",
-                        "\u00E0", "\u00E2", "\u00E6", "\u00E1", "\u00E4", "\u00E3", "\u00E5",
-                        "\u0101", "\u00AA")
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                .setAdditionalMoreKeysPositionOf("e", 5)
-                .setMoreKeysOf("e",
-                        "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
-                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
-                .setMoreKeysOf("y", "\u00FF")
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setAdditionalMoreKeysPositionOf("u", 3)
-                .setMoreKeysOf("u", "\u00F9", "\u00FB", "\u00FC", "\u00FA", "\u016B")
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                .setAdditionalMoreKeysPositionOf("i", 2)
-                .setMoreKeysOf("i", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                .setAdditionalMoreKeysPositionOf("o", 3)
-                .setMoreKeysOf("o",
-                        "\u00F4", "\u0153", "\u00F6", "\u00F2", "\u00F3", "\u00F5", "\u00F8",
-                        "\u014D", "\u00BA")
-                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
-                .setAdditionalMoreKeysPositionOf("c", 2);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java
deleted file mode 100644
index 6d38937..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/GermanCustomizer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class GermanCustomizer extends LayoutCustomizer {
-    public GermanCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
-
-    @Override
-    public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
-
-    @Override
-    public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
-
-    @Override
-    public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0117")
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
-                .setAdditionalMoreKeysPositionOf("u", 2)
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                .setMoreKeysOf("o",
-                        "\u00F6", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153", "\u00F8",
-                        "\u014D")
-                .setAdditionalMoreKeysPositionOf("o", 2)
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                .setMoreKeysOf("a",
-                        "\u00E4", "\u00E2", "\u00E0", "\u00E1", "\u00E6", "\u00E3", "\u00E5",
-                        "\u0101")
-                .setAdditionalMoreKeysPositionOf("a", 2)
-                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                .setMoreKeysOf("s", "\u00DF", "\u015B", "\u0161")
-                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                .setMoreKeysOf("n", "\u00F1", "\u0144");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java
deleted file mode 100644
index 7350709..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/ItalianCustomizer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class ItalianCustomizer extends LayoutCustomizer {
-    public ItalianCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                .setMoreKeysOf("e",
-                        "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setMoreKeysOf("u", "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u016B")
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                .setMoreKeysOf("i", "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u012F", "\u012B")
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                .setMoreKeysOf("o",
-                        "\u00F2", "\u00F3", "\u00F4", "\u00F6", "\u00F5", "\u0153", "\u00F8",
-                        "\u014D", "\u00BA")
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                .setMoreKeysOf("a",
-                        "\u00E0", "\u00E1", "\u00E2", "\u00E4", "\u00E6", "\u00E3", "\u00E5",
-                        "\u0101", "\u00AA");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
new file mode 100644
index 0000000..87f2f30
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.KeyboardLayoutSetTestsBase;
+import com.android.inputmethod.keyboard.KeyboardTheme;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+
+@SmallTest
+public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
+    private static final int NUMBER_OF_SUBTYPES = 81;
+    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 49;
+    private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
+
+    @Override
+    protected int getKeyboardThemeForTests() {
+        return KeyboardTheme.THEME_ID_KLP;
+    }
+
+    private static String toString(final ArrayList<InputMethodSubtype> subtypeList) {
+        final StringBuilder sb = new StringBuilder();
+        for (int index = 0; index < subtypeList.size(); index++) {
+            final InputMethodSubtype subtype = subtypeList.get(index);
+            sb.append(index + ": ");
+            sb.append(SubtypeLocaleUtils.getSubtypeNameForLogging(subtype));
+            sb.append("\n");
+        }
+        return sb.toString();
+    }
+
+    public final void testAllSubtypesCount() {
+        final ArrayList<InputMethodSubtype> allSubtypesList = getAllSubtypesList();
+        assertEquals(toString(allSubtypesList), NUMBER_OF_SUBTYPES, allSubtypesList.size());
+    }
+
+    public final void testAsciiCapableSubtypesCount() {
+        final ArrayList<InputMethodSubtype> asciiCapableSubtypesList =
+                getSubtypesFilteredBy(FILTER_IS_ASCII_CAPABLE);
+        assertEquals(toString(asciiCapableSubtypesList),
+                NUMBER_OF_ASCII_CAPABLE_SUBTYPES, asciiCapableSubtypesList.size());
+    }
+
+    public final void testAdditionalSubtypesCount() {
+        final ArrayList<InputMethodSubtype> additionalSubtypesList =
+                getSubtypesFilteredBy(FILTER_IS_ADDITIONAL_SUBTYPE);
+        assertEquals(toString(additionalSubtypesList),
+                NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES, additionalSubtypesList.size());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
index a22ed60..27519ee 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/LayoutTestsBase.java
@@ -54,7 +54,8 @@
                 + (isPhone() ? "phone" : "tablet");
         // TODO: Test with language switch key enabled and disabled.
         mKeyboardLayoutSet = createKeyboardLayoutSet(mSubtype, null /* editorInfo */,
-                true /* voiceInputKeyEnabled */, true /* languageSwitchKeyEnabled */);
+                true /* voiceInputKeyEnabled */, true /* languageSwitchKeyEnabled */,
+                false /* splitLayoutEnabled */);
     }
 
     @Override
@@ -119,31 +120,13 @@
 
     // TODO: Add phone, phone symbols, number, number password layout tests.
 
-    public final void testAlphabet() {
+    public final void testLayouts() {
         doKeyboardTests(KeyboardId.ELEMENT_ALPHABET);
-    }
-
-    public final void testAlphabetAutomaticShifted() {
         doKeyboardTests(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);
-    }
-
-    public final void testAlphabetManualShifted() {
         doKeyboardTests(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED);
-    }
-
-    public final void testAlphabetShiftLocked() {
         doKeyboardTests(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED);
-    }
-
-    public final void testAlphabetShiftLockShifted() {
         doKeyboardTests(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED);
-    }
-
-    public final void testSymbols() {
         doKeyboardTests(KeyboardId.ELEMENT_SYMBOLS);
-    }
-
-    public final void testSymbolsShifted() {
         doKeyboardTests(KeyboardId.ELEMENT_SYMBOLS_SHIFTED);
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/NoLanguageCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/NoLanguageCustomizer.java
deleted file mode 100644
index 9edbcab..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/NoLanguageCustomizer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class NoLanguageCustomizer extends LayoutCustomizer {
-    NoLanguageCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX
-                .setMoreKeysOf("w", "\u0175")
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                // U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-                .setMoreKeysOf("e",
-                        "\u00E8", "\u00E9", "\u00EA", "\u00EB", "\u0113", "\u0115", "\u0117",
-                        "\u0119", "\u011B")
-                // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
-                // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
-                // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
-                .setMoreKeysOf("r", "\u0155", "\u0157", "\u0159")
-                // U+00FE: "þ" LATIN SMALL LETTER THORN
-                // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
-                // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
-                // U+0167: "ŧ" LATIN SMALL LETTER T WITH STROKE
-                .setMoreKeysOf("t", "\u00FE", "\u0163", "\u0165", "\u0167")
-                // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
-                // U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX
-                // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
-                // U+0133: "ij" LATIN SMALL LIGATURE IJ
-                .setMoreKeysOf("y", "\u00FD", "\u0177", "\u00FF", "\u0133")
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+0169: "ũ" LATIN SMALL LETTER U WITH TILDE
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                // U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE
-                // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
-                // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
-                // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
-                .setMoreKeysOf("u",
-                        "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u0169", "\u016B", "\u016D",
-                        "\u016F", "\u0171", "\u0173")
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                // U+012D: "ĭ" LATIN SMALL LETTER I WITH BREVE
-                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-                // U+0133: "ij" LATIN SMALL LIGATURE IJ
-                .setMoreKeysOf("i",
-                        "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u0129", "\u012B", "\u012D",
-                        "\u012F", "\u0131", "\u0133")
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+014F: "ŏ" LATIN SMALL LETTER O WITH BREVE
-                // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                .setMoreKeysOf("o",
-                        "\u00F2", "\u00F3", "\u00F4", "\u00F5", "\u00F6", "\u00F8", "\u014D",
-                        "\u014F", "\u0151", "\u0153", "\u00BA")
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
-                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
-                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                .setMoreKeysOf("a",
-                        "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u00E4", "\u00E5", "\u00E6",
-                        "\u0101", "\u0103", "\u0105", "\u00AA")
-                // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                // U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX
-                // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
-                // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                // U+017F: "ſ" LATIN SMALL LETTER LONG S
-                .setMoreKeysOf("s", "\u00DF", "\u015B", "\u015D", "\u015F", "\u0161", "\u017F")
-                // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-                // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
-                // U+00F0: "ð" LATIN SMALL LETTER ETH
-                .setMoreKeysOf("d", "\u010F", "\u0111", "\u00F0")
-                // U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX
-                // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
-                // U+0121: "ġ" LATIN SMALL LETTER G WITH DOT ABOVE
-                // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
-                .setMoreKeysOf("g", "\u011D", "\u011F", "\u0121", "\u0123")
-                // U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX
-                .setMoreKeysOf("h", "\u0125")
-                // U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX
-                .setMoreKeysOf("j", "\u0135")
-                // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
-                // U+0138: "ĸ" LATIN SMALL LETTER KRA
-                .setMoreKeysOf("k", "\u0137", "\u0138")
-                // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
-                // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
-                // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
-                // U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT
-                // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
-                .setMoreKeysOf("l", "\u013A", "\u013C", "\u013E", "\u0140", "\u0142")
-                // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
-                // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
-                // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
-                .setMoreKeysOf("z", "\u017A", "\u017C", "\u017E")
-                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                // U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX
-                // U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE
-                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u0109", "\u010B", "\u010D")
-                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
-                // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
-                // U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
-                // U+014B: "ŋ" LATIN SMALL LETTER ENG
-                .setMoreKeysOf("n", "\u00F1", "\u0144", "\u0146", "\u0148", "\u0149", "\u014B");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/PortugueseCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/PortugueseCustomizer.java
deleted file mode 100644
index 629e8cb..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/PortugueseCustomizer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class PortugueseCustomizer extends LayoutCustomizer {
-    PortugueseCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                .setMoreKeysOf("e",
-                        "\u00E9", "\u00EA", "\u00E8", "\u0119", "\u0117", "\u0113", "\u00EB")
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00F9", "\u00FB", "\u016B")
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                .setMoreKeysOf("i", "\u00ED", "\u00EE", "\u00EC", "\u00EF", "\u012F", "\u012B")
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                .setMoreKeysOf("o",
-                        "\u00F3", "\u00F5", "\u00F4", "\u00F2", "\u00F6", "\u0153", "\u00F8",
-                        "\u014D", "\u00BA")
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                .setMoreKeysOf("a",
-                        "\u00E1", "\u00E3", "\u00E0", "\u00E2", "\u00E4", "\u00E5", "\u00E6",
-                        "\u00AA")
-                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                .setMoreKeysOf("c", "\u00E7", "\u010D", "\u0107");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/SpanishCustomizer.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/SpanishCustomizer.java
deleted file mode 100644
index 8974ad6..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/SpanishCustomizer.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
-import com.android.inputmethod.keyboard.layout.Spanish;
-import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-
-import java.util.Locale;
-
-class SpanishCustomizer extends LayoutCustomizer {
-    SpanishCustomizer(final Locale locale) { super(locale); }
-
-    @Override
-    public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-        return isPhone ? PHONE_PUNCTUATION_MORE_KEYS
-                : LayoutBase.TABLET_PUNCTUATION_MORE_KEYS;
-    }
-
-    // Punctuation more keys for phone form factor.
-    private static final ExpectedKey[] PHONE_PUNCTUATION_MORE_KEYS = AbstractLayoutBase.joinKeys(
-            // U+00A1: "¡" INVERTED EXCLAMATION MARK
-            // U+00BF: "¿" INVERTED QUESTION MARK
-            ",", "?", "!", "#", ")", "(", "/", ";", "\u00A1",
-            "'", "@", ":", "-", "\"", "+", "%", "&", "\u00BF");
-
-    @Override
-    public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-        return builder
-                // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                .setMoreKeysOf("e",
-                        "\u00E9", "\u00E8", "\u00EB", "\u00EA", "\u0119", "\u0117", "\u0113")
-                // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00F9", "\u00FB", "\u016B")
-                // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                .setMoreKeysOf("i", "\u00ED", "\u00EF", "\u00EC", "\u00EE", "\u012F", "\u012B")
-                // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                // U+0153: "œ" LATIN SMALL LIGATURE OE
-                // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                // U+00BA: "º" MASCULINE ORDINAL INDICATOR
-                .setMoreKeysOf("o",
-                        "\u00F3", "\u00F2", "\u00F6", "\u00F4", "\u00F5", "\u00F8", "\u0153",
-                        "\u014D", "\u00BA")
-                // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
-                // U+00E6: "æ" LATIN SMALL LETTER AE
-                // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                // U+00AA: "ª" FEMININE ORDINAL INDICATOR
-                .setMoreKeysOf("a",
-                        "\u00E1", "\u00E0", "\u00E4", "\u00E2", "\u00E3", "\u00E5", "\u0105",
-                        "\u00E6", "\u0101", "\u00AA")
-                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                .replaceKeyOfLabel(Spanish.ROW2_10, "\u00F1")
-                // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
-                // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                .setMoreKeysOf("n", "\u00F1", "\u0144");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAfrikaans.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAfrikaans.java
index cd22598..f534cd6 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAfrikaans.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAfrikaans.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArabic.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArabic.java
index fd76708..a9be163 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArabic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArabic.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Arabic;
-import com.android.inputmethod.keyboard.layout.Arabic.ArabicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public class TestsArabic extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ar");
-    private static final LayoutBase LAYOUT = new Arabic(new ArabicCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Arabic(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArmenianAMPhonetic.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArmenianAMPhonetic.java
index 327e943..8ef97d2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArmenianAMPhonetic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsArmenianAMPhonetic.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.ArmenianPhonetic;
-import com.android.inputmethod.keyboard.layout.ArmenianPhonetic.ArmenianPhoneticCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,8 +29,7 @@
 @SmallTest
 public final class TestsArmenianAMPhonetic extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("hy", "AM");
-    private static final LayoutBase LAYOUT = new ArmenianPhonetic(
-            new ArmenianPhoneticCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new ArmenianPhonetic(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAzerbaijaniAZ.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAzerbaijaniAZ.java
index f5317e2..a10023c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAzerbaijaniAZ.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsAzerbaijaniAZ.java
@@ -19,9 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.TurkicCustomizer;
 
 import java.util.Locale;
 
@@ -31,58 +30,8 @@
 @SmallTest
 public final class TestsAzerbaijaniAZ extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("az", "AZ");
-    private static final LayoutBase LAYOUT = new Qwerty(new AzerbaijaniAZCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Qwerty(new TurkicCustomizer(LOCALE));
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static final class AzerbaijaniAZCustomizer extends LayoutCustomizer {
-        public AzerbaijaniAZCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+0259: "ə" LATIN SMALL LETTER SCHWA
-                    .setMoreKeysOf("e", "\u0259")
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
-                    // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                    .setMoreKeysOf("i",
-                            "\u0131", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o",
-                            "\u00F6", "\u00F4", "\u0153", "\u00F2", "\u00F3", "\u00F5", "\u00F8",
-                            "\u014D")
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    .setMoreKeysOf("a", "\u00E2")
-                    // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    .setMoreKeysOf("s", "\u015F", "\u00DF", "\u015B", "\u0161")
-                    // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                    // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                    // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                    .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
-                    // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
-                    .setMoreKeysOf("g", "\u011F");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBasqueES.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBasqueES.java
index bef18c5..103fac1 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBasqueES.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBasqueES.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class BasqueESCustomizer extends EuroCustomizer {
         private final SpanishCustomizer mSpanishCustomizer;
 
-        public BasqueESCustomizer(final Locale locale) {
+        BasqueESCustomizer(final Locale locale) {
             super(locale);
             mSpanishCustomizer = new SpanishCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBelarusianBY.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBelarusianBY.java
index c5238d5..0b23933 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBelarusianBY.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBelarusianBY.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.EastSlavic;
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class BelarusianBYCustomizer extends EastSlavicCustomizer {
-        public BelarusianBYCustomizer(final Locale locale) { super(locale); }
+        BelarusianBYCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
new file mode 100644
index 0000000..2d38c87
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliBD.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.BengaliAkkhor;
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.BengaliCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+/**
+ * bn_BD: Bengali (Bangladesh)/bengali_akkhor
+ */
+@SmallTest
+public final class TestsBengaliBD extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("bn", "BD");
+    private static final LayoutBase LAYOUT = new BengaliAkkhor(new BengaliBDCustomzier(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class BengaliBDCustomzier extends BengaliCustomizer {
+        BengaliBDCustomzier(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+        }
+
+        @Override
+        public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
+            return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY, key(ZWNJ_KEY, ZWJ_KEY));
+        }
+
+        @Override
+        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+        // U+09F3: "৳" BENGALI RUPEE SIGN
+        private static final ExpectedKey CURRENCY_RUPEE = key("\u09F3",
+                Symbols.CURRENCY_GENERIC_MORE_KEYS);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
index d642632..022b085 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBengaliIN.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Bengali;
-import com.android.inputmethod.keyboard.layout.Bengali.BengaliCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.BengaliCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -38,7 +38,10 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class BengaliINCustomzier extends BengaliCustomizer {
-        public BengaliINCustomzier(final Locale locale) { super(locale); }
+        BengaliINCustomzier(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) { return EMPTY_KEYS; }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarian.java
index ded8d72..1530827 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarian.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Bulgarian;
-import com.android.inputmethod.keyboard.layout.Bulgarian.BulgarianCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsBulgarian extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("bg");
-    private static final LayoutBase LAYOUT = new Bulgarian(new BulgarianCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Bulgarian(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarianBds.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarianBds.java
index 22b2011..558b1d4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarianBds.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsBulgarianBds.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.BulgarianBds;
-import com.android.inputmethod.keyboard.layout.BulgarianBds.BulgarianBdsCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsBulgarianBds extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("bg");
-    private static final LayoutBase LAYOUT = new BulgarianBds(new BulgarianBdsCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new BulgarianBds(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCatalan.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCatalan.java
index 151a0a6..a323ffd 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCatalan.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCatalan.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -38,20 +38,20 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class CatalanCustomizer extends EuroCustomizer {
-        public CatalanCustomizer(final Locale locale) { super(locale); }
+        CatalanCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? PHONE_PUNCTUATION_MORE_KEYS
-                    : TABLET_PUNCTUATION_MORE_KEYS;
+            return isPhone ? CATALAN_PHONE_PUNCTUATION_MORE_KEYS
+                    : CATALAN_TABLET_PUNCTUATION_MORE_KEYS;
         }
 
         // U+00B7: "·" MIDDLE DOT
-        private static final ExpectedKey[] PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+        private static final ExpectedKey[] CATALAN_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
                 ",", "?", "!", "\u00B7", "#", ")", "(", "/", ";",
                 "'", "@", ":", "-", "\"", "+", "%", "&");
 
-        private static final ExpectedKey[] TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
+        private static final ExpectedKey[] CATALAN_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
                 ",", "'", "\u00B7", "#", ")", "(", "/", ";",
                 "@", ":", "-", "\"", "+", "%", "&");
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCroatian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCroatian.java
index 8575ef2..d8af75b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCroatian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCroatian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwertz;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class CroatianCustomizer extends LayoutCustomizer {
-        public CroatianCustomizer(final Locale locale) { super(locale); }
+        CroatianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCzech.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCzech.java
index f479470..f05b8eb 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCzech.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsCzech.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwertz;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class CzechCustomizer extends LayoutCustomizer {
-        public CzechCustomizer(final Locale locale) { super(locale); }
+        CzechCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanish.java
index 85c63a1..fb7338d 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanish.java
@@ -19,11 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Nordic;
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.DanishCustomizer;
 
 import java.util.Locale;
 
@@ -37,73 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static class DanishCustomizer extends EuroCustomizer {
-        public DanishCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
-
-        @Override
-        public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
-
-        @Override
-        public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
-
-        @Override
-        public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    .setMoreKeysOf("e", "\u00E9", "\u00EB")
-                    // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
-                    // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
-                    .setMoreKeysOf("y", "\u00FD", "\u00FF")
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00FB", "\u00F9", "\u016B")
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    .setMoreKeysOf("i", "\u00ED", "\u00EF")
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o", "\u00F3", "\u00F4", "\u00F2", "\u00F5", "\u0153", "\u014D")
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW2_10, key("\u00E6", moreKey("\u00E4")))
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW2_11, key("\u00F8", moreKey("\u00F6")))
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    .setMoreKeysOf("a", "\u00E1", "\u00E4", "\u00E0", "\u00E2", "\u00E3", "\u0101")
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    .setMoreKeysOf("s", "\u00DF", "\u015B", "\u0161")
-                    // U+00F0: "ð" LATIN SMALL LETTER ETH
-                    .setMoreKeysOf("d", "\u00F0")
-                    // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
-                    .setMoreKeysOf("l", "\u0142")
-                    // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                    // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                    .setMoreKeysOf("n", "\u00F1", "\u0144");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanishQwertz.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanishQwertz.java
new file mode 100644
index 0000000..718bf8a
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDanishQwertz.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwertz;
+import com.android.inputmethod.keyboard.layout.customizer.DanishCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * da: Danish/qwertz
+ */
+@SmallTest
+public final class TestsDanishQwertz extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("da");
+    private static final LayoutBase LAYOUT = new Qwertz(new DanishQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class DanishQwertyCustomizer extends DanishCustomizer {
+        DanishQwertyCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTZ layout doesn't have Nordic keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                    // U+00E6: "æ" LATIN SMALL LETTER AE
+                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                    .setMoreKeysOf("a", "\u00E5", "\u00E6", "\u00E1", "\u00E4", "\u00E0", "\u00E2",
+                            "\u00E3", "\u0101");
+        }
+
+        @Override
+        protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                    // U+0153: "œ" LATIN SMALL LIGATURE OE
+                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                    .setMoreKeysOf("o", "\u00F8", "\u00F6", "\u00F3", "\u00F4", "\u00F2", "\u00F5",
+                            "\u0153", "\u014D");
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutch.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutch.java
index 1730f66..12bd1b1 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutch.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutch.java
@@ -19,11 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.DutchCustomizer;
 
 import java.util.Locale;
 
@@ -37,70 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    static class DutchCustomizer extends EuroCustomizer {
-        public DutchCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
-
-        @Override
-        public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_L9R; }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    .setMoreKeysOf("a",
-                            "\u00E1", "\u00E4", "\u00E2", "\u00E0", "\u00E6", "\u00E3", "\u00E5",
-                            "\u0101")
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                    // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                    // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                    // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                    .setMoreKeysOf("e",
-                            "\u00E9", "\u00EB", "\u00EA", "\u00E8", "\u0119", "\u0117", "\u0113")
-                    // U+0133: "ij" LATIN SMALL LIGATURE IJ
-                    .setMoreKeysOf("y", "\u0133")
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FA", "\u00FC", "\u00FB", "\u00F9", "\u016B")
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                    // U+0133: "ij" LATIN SMALL LIGATURE IJ
-                    .setMoreKeysOf("i",
-                            "\u00ED", "\u00EF", "\u00EC", "\u00EE", "\u012F", "\u012B", "\u0133")
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o",
-                            "\u00F3", "\u00F6", "\u00F4", "\u00F2", "\u00F5", "\u0153", "\u00F8",
-                            "\u014D")
-                    // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                    // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                    .setMoreKeysOf("n", "\u00F1", "\u0144");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutchBE.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutchBE.java
index 31adf7a..1464118 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutchBE.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDutchBE.java
@@ -20,7 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.Azerty;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.tests.TestsDutch.DutchCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.DutchCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakEmail.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakEmail.java
index 37ca092..3966ebc 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakEmail.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakEmail.java
@@ -25,8 +25,9 @@
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.keyboard.layout.Dvorak;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer.EnglishDvorakCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.tests.TestsEnglishDvorak.EnglishDvorakCustomizer;
 
 import java.util.Locale;
 
@@ -44,12 +45,13 @@
     @Override
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
-            final boolean languageSwitchKeyEnabled) {
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
         final EditorInfo emailField = new EditorInfo();
         emailField.inputType =
                 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
         return super.createKeyboardLayoutSet(
-                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled);
+                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled,
+                splitLayoutEnabled);
     }
 
     private static class DvorakEmailCustomizer extends EnglishDvorakCustomizer {
@@ -59,23 +61,23 @@
 
         @Override
         public ExpectedKey getEnterKey(final boolean isPhone) {
-            return isPhone ? LayoutBase.ENTER_KEY : super.getEnterKey(isPhone);
+            return isPhone ? ENTER_KEY : super.getEnterKey(isPhone);
         }
 
         @Override
         public ExpectedKey getEmojiKey(final boolean isPhone) {
-            return LayoutBase.DOMAIN_KEY;
+            return DOMAIN_KEY;
         }
 
         @Override
         public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
             return isPhone ? super.getKeysLeftToSpacebar(isPhone)
-                    : joinKeys(key("@", LayoutBase.SETTINGS_KEY));
+                    : joinKeys(key("@", SETTINGS_KEY));
         }
     }
 
     private static class DvorakEmail extends Dvorak {
-        public DvorakEmail(final LayoutCustomizer customizer) {
+        DvorakEmail(final LayoutCustomizer customizer) {
             super(customizer);
         }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakUrl.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakUrl.java
index 3bcae0c..67e0d91 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakUrl.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsDvorakUrl.java
@@ -25,8 +25,9 @@
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.keyboard.layout.Dvorak;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer.EnglishDvorakCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.tests.TestsEnglishDvorak.EnglishDvorakCustomizer;
 
 import java.util.Locale;
 
@@ -44,40 +45,37 @@
     @Override
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
-            final boolean languageSwitchKeyEnabled) {
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
         final EditorInfo emailField = new EditorInfo();
         emailField.inputType =
                 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
         return super.createKeyboardLayoutSet(
-                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled);
+                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled,
+                splitLayoutEnabled);
     }
 
     private static class DvorakUrlCustomizer extends EnglishDvorakCustomizer {
-        DvorakUrlCustomizer(final Locale locale) {
-            super(locale);
-        }
+        DvorakUrlCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getEnterKey(final boolean isPhone) {
-            return isPhone ? LayoutBase.ENTER_KEY : super.getEnterKey(isPhone);
+            return isPhone ? ENTER_KEY : super.getEnterKey(isPhone);
         }
 
         @Override
         public ExpectedKey getEmojiKey(final boolean isPhone) {
-            return LayoutBase.DOMAIN_KEY;
+            return DOMAIN_KEY;
         }
 
         @Override
         public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
             return isPhone ? super.getKeysLeftToSpacebar(isPhone)
-                    : joinKeys(key("/", LayoutBase.SETTINGS_KEY));
+                    : joinKeys(key("/", SETTINGS_KEY));
         }
     }
 
     private static class DvorakEmail extends Dvorak {
-        public DvorakEmail(final LayoutCustomizer customizer) {
-            super(customizer);
-        }
+        DvorakEmail(final LayoutCustomizer customizer) { super(customizer); }
 
         @Override
         protected ExpectedKey getRow1_1Key(final boolean isPhone, final int elementId) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishDvorak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishDvorak.java
index e647f8a..2b25f81 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishDvorak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishDvorak.java
@@ -19,9 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Dvorak;
-import com.android.inputmethod.keyboard.layout.Dvorak.DvorakCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer.EnglishDvorakCustomizer;
 
 import java.util.Locale;
 
@@ -35,18 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    public static class EnglishDvorakCustomizer extends DvorakCustomizer {
-        private final EnglishCustomizer mEnglishCustomizer;
-
-        EnglishDvorakCustomizer(final Locale locale) {
-            super(locale);
-            mEnglishCustomizer = new EnglishCustomizer(locale);
-        }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return mEnglishCustomizer.setAccentedLetters(builder);
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishIN.java
index c80b250..54759ce 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishIN.java
@@ -22,6 +22,7 @@
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -38,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class EnglishINCustomizer extends EnglishCustomizer {
-        public EnglishINCustomizer(final Locale locale) { super(locale); }
+        EnglishINCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUK.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUK.java
index c0dcbdc..714a600 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUK.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUK.java
@@ -21,6 +21,7 @@
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -37,7 +38,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class EnglishUKCustomizer extends EnglishCustomizer {
-        public EnglishUKCustomizer(final Locale locale) { super(locale); }
+        EnglishUKCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_POUND; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
index 6ea8f60..570ee9d 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEnglishUS.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEsperanto.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEsperanto.java
index 6a44187..a6792e2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEsperanto.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEsperanto.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -37,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class EsperantoCustomizer extends LayoutCustomizer {
-        public EsperantoCustomizer(final Locale locale) { super(locale); }
+        EsperantoCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEE.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEE.java
index 865e9ea..8cb67e2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEE.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEE.java
@@ -19,11 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Nordic;
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.EstonianEECustomizer;
 
 import java.util.Locale;
 
@@ -37,121 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static class EstonianEECustomizer extends EuroCustomizer {
-        public EstonianEECustomizer(final Locale locale) {
-            super(locale);
-        }
-
-        @Override
-        public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
-
-        @Override
-        public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_R9L; }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                    // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                    // U+011B: "ě" LATIN SMALL LETTER E WITH CARON
-                    .setMoreKeysOf("e",
-                            "\u0113", "\u00E8", "\u0117", "\u00E9", "\u00EA", "\u00EB", "\u0119",
-                            "\u011B")
-                    // U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA
-                    // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
-                    // U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE
-                    .setMoreKeysOf("r", "\u0157", "\u0159", "\u0155")
-                    // U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA
-                    // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
-                    .setMoreKeysOf("t", "\u0163", "\u0165")
-                    // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
-                    // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
-                    .setMoreKeysOf("y", "\u00FD", "\u00FF")
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
-                    // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
-                    .setMoreKeysOf("u",
-                            "\u00FC", "\u016B", "\u0173", "\u00F9", "\u00FA", "\u00FB", "\u016F",
-                            "\u0171")
-                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-                    .setMoreKeysOf("i",
-                            "\u012B", "\u00EC", "\u012F", "\u00ED", "\u00EE", "\u00EF", "\u0131")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    .setMoreKeysOf("o",
-                            "\u00F6", "\u00F5", "\u00F2", "\u00F3", "\u00F4", "\u0153", "\u0151",
-                            "\u00F8")
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW1_11, "\u00FC")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    .replaceKeyOfLabel(Nordic.ROW2_10, key("\u00F6", moreKey("\u00F5")))
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW2_11, "\u00E4")
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
-                    .setMoreKeysOf("a",
-                            "\u00E4", "\u0101", "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u00E5",
-                            "\u00E6", "\u0105")
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
-                    .setMoreKeysOf("s", "\u0161", "\u00DF", "\u015B", "\u015F")
-                    // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-                    .setMoreKeysOf("d", "\u010F")
-                    // U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA
-                    // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
-                    .setMoreKeysOf("g", "\u0123", "\u011F")
-                    // U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA
-                    .setMoreKeysOf("k", "\u0137")
-                    // U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA
-                    // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
-                    // U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE
-                    // U+013E: "ľ" LATIN SMALL LETTER L WITH CARON
-                    .setMoreKeysOf("l", "\u013C", "\u0142", "\u013A", "\u013E")
-                    // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
-                    // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
-                    // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
-                    .setMoreKeysOf("z", "\u017E", "\u017C", "\u017A")
-                    // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                    // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                    // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                    .setMoreKeysOf("c", "\u010D", "\u00E7", "\u0107")
-                    // U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA
-                    // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                    // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                    .setMoreKeysOf("n", "\u0146", "\u00F1", "\u0144");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEEQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEEQwerty.java
new file mode 100644
index 0000000..fb7c243
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsEstonianEEQwerty.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EstonianEECustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * et_EE: Estonian (Estonia)/qwerty
+ */
+@SmallTest
+public final class TestsEstonianEEQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("et", "EE");
+    private static final LayoutBase LAYOUT = new Qwerty(new EstonianEEQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class EstonianEEQwertyCustomizer extends EstonianEECustomizer {
+        EstonianEEQwertyCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTY layout doesn't have Nordic keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                    // U+00E6: "æ" LATIN SMALL LETTER AE
+                    // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                    .setMoreKeysOf("a", "\u00E4", "\u0101", "\u00E0", "\u00E1", "\u00E2", "\u00E3",
+                            "\u00E5", "\u00E6", "\u0105");
+        }
+
+        @Override
+        protected void setMoreKeysOfI(final ExpectedKeyboardBuilder builder, final int elementId) {
+            // TODO: The upper-case letter of "ı" in Estonian locale is "I". It should be omitted
+            // from the more keys of "I".
+            builder
+                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
+                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+                    // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+                    .setMoreKeysOf("i",
+                            "\u012B", "\u00EC", "\u012F", "\u00ED", "\u00EE", "\u00EF", "\u0131");
+        }
+
+        @Override
+        protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                    // U+0153: "œ" LATIN SMALL LIGATURE OE
+                    // U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE
+                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                    .setMoreKeysOf("o", "\u00F6", "\u00F5", "\u00F2", "\u00F3", "\u00F4", "\u0153",
+                            "\u0151", "\u00F8");
+        }
+
+        @Override
+        protected void setMoreKeysOfU(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+                    // U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK
+                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+                    // U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE
+                    // U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE
+                    .setMoreKeysOf("u", "\u00FC", "\u016B", "\u0173", "\u00F9", "\u00FA", "\u00FB",
+                            "\u016F", "\u0171");
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnish.java
index ff32da1..3d42f30 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnish.java
@@ -19,9 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Nordic;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.FinnishCustomizer;
 
 import java.util.Locale;
 
@@ -35,47 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static class FinnishCustomizer extends EuroCustomizer {
-        public FinnishCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    .setMoreKeysOf("u", "\u00FC")
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o",
-                            "\u00F8", "\u00F4", "\u00F2", "\u00F3", "\u00F5", "\u0153", "\u014D")
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    .replaceKeyOfLabel(Nordic.ROW2_10, key("\u00F6", moreKey("\u00F8")))
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    .replaceKeyOfLabel(Nordic.ROW2_11, key("\u00E4", moreKey("\u00E6")))
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    .setMoreKeysOf("a", "\u00E6", "\u00E0", "\u00E1", "\u00E2", "\u00E3", "\u0101")
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    .setMoreKeysOf("s", "\u0161", "\u00DF", "\u015B")
-                    // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
-                    // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
-                    // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
-                    .setMoreKeysOf("z", "\u017E", "\u017A", "\u017C");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnishQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnishQwerty.java
new file mode 100644
index 0000000..c81b2a2
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFinnishQwerty.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.FinnishCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * fi: Finnish/qwerty
+ */
+@SmallTest
+public final class TestsFinnishQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("fi");
+    private static final LayoutBase LAYOUT = new Qwerty(new FinnishQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class FinnishQwertyCustomizer extends FinnishCustomizer {
+        FinnishQwertyCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTY layout doesn't have Nordic keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                    // U+00E6: "æ" LATIN SMALL LETTER AE
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                    .setMoreKeysOf("a", "\u00E4", "\u00E5", "\u00E6", "\u00E0", "\u00E1", "\u00E2",
+                            "\u00E3", "\u0101");
+        }
+
+        @Override
+        protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                    // U+0153: "œ" LATIN SMALL LIGATURE OE
+                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                    .setMoreKeysOf("o", "\u00F6", "\u00F8", "\u00F4", "\u00F2", "\u00F3", "\u00F5",
+                            "\u0153", "\u014D");
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrench.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrench.java
index 7ced1fb..ca663f4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrench.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrench.java
@@ -20,8 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.Azerty;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.customizer.FrenchCustomizer.FrenchEuroCustomizer;
 
 import java.util.Locale;
 
@@ -35,21 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    static final class FrenchEuroCustomizer extends FrenchCustomizer {
-        private final EuroCustomizer mEuroCustomizer;
-
-        public FrenchEuroCustomizer(final Locale locale) {
-            super(locale);
-            mEuroCustomizer = new EuroCustomizer(locale);
-        }
-
-        @Override
-        public final ExpectedKey getCurrencyKey() { return mEuroCustomizer.getCurrencyKey(); }
-
-        @Override
-        public final ExpectedKey[] getOtherCurrencyKeys() {
-            return mEuroCustomizer.getOtherCurrencyKeys();
-        }
-    }
-}
\ No newline at end of file
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCA.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCA.java
index 9b3cd1e..12c94b1 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCA.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCA.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.FrenchCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCH.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCH.java
index 2598aa3..2461157 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCH.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchCH.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Swiss;
+import com.android.inputmethod.keyboard.layout.customizer.FrenchCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -36,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class FrenchCHCustomizer extends FrenchCustomizer {
-        public FrenchCHCustomizer(final Locale locale) { super(locale); }
+        FrenchCHCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchDvorak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchDvorak.java
index 33d1445..4053063 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchDvorak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchDvorak.java
@@ -19,11 +19,11 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Dvorak;
-import com.android.inputmethod.keyboard.layout.Dvorak.DvorakCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.FrenchCustomizer.FrenchEuroCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
-import com.android.inputmethod.keyboard.layout.tests.TestsFrench.FrenchEuroCustomizer;
 
 import java.util.Locale;
 
@@ -41,7 +41,7 @@
     private static class FrenchDvorakCustomizer extends DvorakCustomizer {
         private final FrenchEuroCustomizer mFrenchEuroCustomizer;
 
-        public FrenchDvorakCustomizer(final Locale locale) {
+        FrenchDvorakCustomizer(final Locale locale) {
             super(locale);
             mFrenchEuroCustomizer = new FrenchEuroCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchQwertz.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchQwertz.java
index 6ab2870..67edace 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchQwertz.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsFrenchQwertz.java
@@ -20,7 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwertz;
-import com.android.inputmethod.keyboard.layout.tests.TestsFrench.FrenchEuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.FrenchCustomizer.FrenchEuroCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGalicianES.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGalicianES.java
index 1472828..c37fff2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGalicianES.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGalicianES.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class GalicianESCustomizer extends EuroCustomizer {
         private final SpanishCustomizer mSpanishCustomizer;
 
-        public GalicianESCustomizer(final Locale locale) {
+        GalicianESCustomizer(final Locale locale) {
             super(locale);
             mSpanishCustomizer = new SpanishCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGeorgianGE.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGeorgianGE.java
index f25942f..f6e3080 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGeorgianGE.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGeorgianGE.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Georgian;
-import com.android.inputmethod.keyboard.layout.Georgian.GeorgianCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsGeorgianGE extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ka", "GE");
-    private static final LayoutBase LAYOUT = new Georgian(new GeorgianCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Georgian(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGerman.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGerman.java
index 6f75711..52c5a06 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGerman.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGerman.java
@@ -19,9 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwertz;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.customizer.GermanCustomizer.GermanEuroCustomizer;
 
 import java.util.Locale;
 
@@ -35,21 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    static class GermanEuroCustomizer extends GermanCustomizer {
-        final EuroCustomizer mEuroCustomizer;
-
-        public GermanEuroCustomizer(final Locale locale) {
-            super(locale);
-            mEuroCustomizer = new EuroCustomizer(locale);
-        }
-
-        @Override
-        public ExpectedKey getCurrencyKey() { return mEuroCustomizer.getCurrencyKey(); }
-
-        @Override
-        public ExpectedKey[] getOtherCurrencyKeys() {
-            return mEuroCustomizer.getOtherCurrencyKeys();
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanCH.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanCH.java
index 7deb00b..10981d9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanCH.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanCH.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Swiss;
+import com.android.inputmethod.keyboard.layout.customizer.GermanCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -36,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class GermanCHCustomizer extends GermanCustomizer {
-        public GermanCHCustomizer(final Locale locale) { super(locale); }
+        GermanCHCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanDvorak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanDvorak.java
index b28d5cf..36d1cb8 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanDvorak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanDvorak.java
@@ -19,10 +19,11 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Dvorak;
-import com.android.inputmethod.keyboard.layout.Dvorak.DvorakCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.GermanCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,10 +40,10 @@
     @Override
     LayoutBase getLayout() { return LAYOUT; }
 
-    static class GermanDvorakCustomizer extends DvorakCustomizer {
-        final GermanCustomizer mGermanCustomizer;
+    private static class GermanDvorakCustomizer extends DvorakCustomizer {
+        private final GermanCustomizer mGermanCustomizer;
 
-        public GermanDvorakCustomizer(final Locale locale) {
+        GermanDvorakCustomizer(final Locale locale) {
             super(locale);
             mGermanCustomizer = new GermanCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanQwerty.java
index 19ae5a3..6db942f 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGermanQwerty.java
@@ -20,7 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
-import com.android.inputmethod.keyboard.layout.tests.TestsGerman.GermanEuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.GermanCustomizer.GermanEuroCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGreek.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGreek.java
index 4acb119..fd21d52 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGreek.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsGreek.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Greek;
-import com.android.inputmethod.keyboard.layout.Greek.GreekCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public class TestsGreek extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("el");
-    private static final LayoutBase LAYOUT = new Greek(new GreekCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Greek(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java
index c0243a8..cc63048 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Hebrew;
-import com.android.inputmethod.keyboard.layout.Hebrew.HebrewCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public class TestsHebrew extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("iw");
-    private static final LayoutBase LAYOUT = new Hebrew(new HebrewCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Hebrew(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
index 84053b5..53652fc 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindi.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Hindi;
-import com.android.inputmethod.keyboard.layout.Hindi.HindiCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.HindiCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindiCompact.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindiCompact.java
index 2e676df..cfe3e9e 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindiCompact.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHindiCompact.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.HindiCompact;
-import com.android.inputmethod.keyboard.layout.HindiCompact.HindiCompactCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsHindiCompact extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("hi");
-    private static final LayoutBase LAYOUT = new HindiCompact(new HindiCompactCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new HindiCompact(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
new file mode 100644
index 0000000..a8e8723
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.Suppress;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+/*
+ * hi_ZZ: Hinglish/qwerty
+ */
+@Suppress
+public final class TestsHinglish extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("hi", "ZZ");
+    private static final LayoutBase LAYOUT = new Qwerty(new HinglishCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class HinglishCustomizer extends LayoutCustomizer {
+        HinglishCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
+
+        @Override
+        public ExpectedKey[] getOtherCurrencyKeys() {
+            return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+        }
+
+        // U+20B9: "₹" INDIAN RUPEE SIGN
+        private static final ExpectedKey CURRENCY_RUPEE = key("\u20B9",
+                Symbols.CURRENCY_GENERIC_MORE_KEYS);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHungarian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHungarian.java
index efc95dc..a32e2b5 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHungarian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHungarian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwertz;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class HungarianCustomizer extends LayoutCustomizer {
-        public HungarianCustomizer(final Locale locale) { super(locale); }
+        HungarianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIcelandic.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIcelandic.java
index 62b111e..8eabf18 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIcelandic.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIcelandic.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class IcelandicCustomizer extends LayoutCustomizer {
-        public IcelandicCustomizer(final Locale locale) { super(locale); }
+        IcelandicCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIndonesian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIndonesian.java
index 9b23bfe..8371171 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIndonesian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsIndonesian.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
index f3c610c..2acc967 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalian.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.ItalianCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class ItalianITCustomizer extends EuroCustomizer {
         private final ItalianCustomizer mItalianCustomizer;
 
-        public ItalianITCustomizer(final Locale locale) {
+        ItalianITCustomizer(final Locale locale) {
             super(locale);
             mItalianCustomizer = new ItalianCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java
index d32f9e9..f98545a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsItalianCH.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Swiss;
+import com.android.inputmethod.keyboard.layout.customizer.ItalianCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -36,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class ItalianCHCustomizer extends ItalianCustomizer {
-        public ItalianCHCustomizer(final Locale locale) { super(locale); }
+        ItalianCHCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKannadaIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKannadaIN.java
index d1866e8..a0ff1d0 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKannadaIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKannadaIN.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Kannada;
-import com.android.inputmethod.keyboard.layout.Kannada.KannadaCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsKannadaIN extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("kn", "IN");
-    private static final LayoutBase LAYOUT = new Kannada(new KannadaCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Kannada(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKazakh.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKazakh.java
index d255a0f..66ece29 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKazakh.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKazakh.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.EastSlavic;
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -37,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class KazakhCustomizer extends EastSlavicCustomizer {
-        public KazakhCustomizer(final Locale locale) { super(locale); }
+        KazakhCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKhmerKH.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKhmerKH.java
index df2f40d..dde9b87 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKhmerKH.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKhmerKH.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Khmer;
-import com.android.inputmethod.keyboard.layout.Khmer.KhmerCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsKhmerKH extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("km", "KH");
-    private static final LayoutBase LAYOUT = new Khmer(new KhmerCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Khmer(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKyrgyz.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKyrgyz.java
index 9797b4b..3faf2f6 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKyrgyz.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsKyrgyz.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.EastSlavic;
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -37,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class KyrgyzCustomizer extends EastSlavicCustomizer {
-        public KyrgyzCustomizer(final Locale locale) { super(locale); }
+        KyrgyzCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLaoLA.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLaoLA.java
index 34ad1fb..ffa3372 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLaoLA.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLaoLA.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Lao;
-import com.android.inputmethod.keyboard.layout.Lao.LaoCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsLaoLA extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("lo", "LA");
-    private static final LayoutBase LAYOUT = new Lao(new LaoCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Lao(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLatvian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLatvian.java
index dc1736c..dbab16a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLatvian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLatvian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class LatvianCustomizer extends LayoutCustomizer {
-        public LatvianCustomizer(final Locale locale) { super(locale); }
+        LatvianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLithuanian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLithuanian.java
index 55ac37a..248014a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLithuanian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsLithuanian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class LithuanianCustomizer extends LayoutCustomizer {
-        public LithuanianCustomizer(final Locale locale) { super(locale); }
+        LithuanianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMacedonian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMacedonian.java
index 1d7d856..46b1c39 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMacedonian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMacedonian.java
@@ -20,8 +20,8 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.SouthSlavic;
-import com.android.inputmethod.keyboard.layout.SouthSlavic.SouthSlavicLayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.SouthSlavicLayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class MacedonianCustomizer extends SouthSlavicLayoutCustomizer {
-        public MacedonianCustomizer(final Locale locale) { super(locale); }
+        MacedonianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayMY.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayMY.java
index 9792af9..a6e6cd5 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayMY.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayMY.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
index b494ad3..e3fcb53 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMalayalamIN.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Malayalam;
-import com.android.inputmethod.keyboard.layout.Malayalam.MalayalamCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsMalayalamIN extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ml", "IN");
-    private static final LayoutBase LAYOUT = new Malayalam(new MalayalamCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Malayalam(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMarathiIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMarathiIN.java
index b937629..3e54f6e 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMarathiIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMarathiIN.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Marathi;
-import com.android.inputmethod.keyboard.layout.Marathi.MarathiCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsMarathiIN extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("mr", "IN");
-    private static final LayoutBase LAYOUT = new Marathi(new MarathiCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Marathi(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMongolianMN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMongolianMN.java
index e28e962..6dafe77 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMongolianMN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMongolianMN.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Mongolian;
-import com.android.inputmethod.keyboard.layout.Mongolian.MongolianMNCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsMongolianMN extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("mn", "MN");
-    private static final LayoutBase LAYOUT = new Mongolian(new MongolianMNCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Mongolian(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java
deleted file mode 100644
index a0bd50c..0000000
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsMyanmarMM.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2014 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.layout.tests;
-
-import android.test.suitebuilder.annotation.Suppress;
-
-import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.Myanmar;
-import com.android.inputmethod.keyboard.layout.Myanmar.MyanmarCustomizer;
-
-import java.util.Locale;
-
-/**
- * my_MM: Myanmar (Myanmar)/myanmar
- */
-@Suppress
-public final class TestsMyanmarMM extends LayoutTestsBase {
-    private static final Locale LOCALE = new Locale("my", "MM");
-    private static final LayoutBase LAYOUT = new Myanmar(new MyanmarCustomizer(LOCALE));
-
-    @Override
-    LayoutBase getLayout() { return LAYOUT; }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliRomanized.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliRomanized.java
index 971976a..f646db3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliRomanized.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliRomanized.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.NepaliRomanized;
-import com.android.inputmethod.keyboard.layout.NepaliRomanized.NepaliRomanizedCustomizer;
 
 import java.util.Locale;
 
@@ -30,8 +29,7 @@
 @SmallTest
 public final class TestsNepaliRomanized extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ne", "NP");
-    private static final LayoutBase LAYOUT = new NepaliRomanized(
-            new NepaliRomanizedCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new NepaliRomanized(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliTraditional.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliTraditional.java
index 724c430..99d87b1 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliTraditional.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNepaliTraditional.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.NepaliTraditional;
-import com.android.inputmethod.keyboard.layout.NepaliTraditional.NepaliTraditionalCustomizer;
 
 import java.util.Locale;
 
@@ -30,8 +29,7 @@
 @SmallTest
 public final class TestsNepaliTraditional extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("ne", "NP");
-    private static final LayoutBase LAYOUT = new NepaliTraditional(
-            new NepaliTraditionalCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new NepaliTraditional(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguage.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguage.java
index 3ed6315..149d520 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguage.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguage.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.NoLanguageCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageColemak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageColemak.java
index 8d627e3..979947f 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageColemak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageColemak.java
@@ -20,7 +20,8 @@
 
 import com.android.inputmethod.keyboard.layout.Colemak;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.NoLanguageCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class NoLanguageColemakCustomizer extends LayoutCustomizer {
         private final NoLanguageCustomizer mNoLanguageCustomizer;
 
-        public NoLanguageColemakCustomizer(final Locale locale) {
+        NoLanguageColemakCustomizer(final Locale locale) {
             super(locale);
             mNoLanguageCustomizer = new NoLanguageCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageDvorak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageDvorak.java
index 9bf47ed..5423193 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageDvorak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguageDvorak.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Dvorak;
-import com.android.inputmethod.keyboard.layout.Dvorak.DvorakCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.DvorakCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.NoLanguageCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class NoLanguageDvorakCustomizer extends DvorakCustomizer {
         private final NoLanguageCustomizer mNoLanguageCustomizer;
 
-        public NoLanguageDvorakCustomizer(final Locale locale) {
+        NoLanguageDvorakCustomizer(final Locale locale) {
             super(locale);
             mNoLanguageCustomizer = new NoLanguageCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguagePcQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguagePcQwerty.java
index cd8d43c..20b587b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguagePcQwerty.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNoLanguagePcQwerty.java
@@ -20,7 +20,8 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.PcQwerty;
-import com.android.inputmethod.keyboard.layout.PcQwerty.PcQwertyCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.NoLanguageCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.PcQwertyCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class NoLanguagePcQwertyCustomizer extends PcQwertyCustomizer {
         private final NoLanguageCustomizer mNoLanguageCustomizer;
 
-        public NoLanguagePcQwertyCustomizer(final Locale locale) {
+        NoLanguagePcQwertyCustomizer(final Locale locale) {
             super(locale);
             mNoLanguageCustomizer = new NoLanguageCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegian.java
index 5d220df..910512c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegian.java
@@ -19,11 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Nordic;
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.NorwegianCustomizer;
 
 import java.util.Locale;
 
@@ -37,58 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static class NorwegianCustomizer extends LayoutCustomizer {
-        public NorwegianCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
-
-        @Override
-        public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_L9R; }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                    // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                    // U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
-                    // U+0113: "ē" LATIN SMALL LETTER E WITH MACRON
-                    .setMoreKeysOf("e",
-                            "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119", "\u0117", "\u0113")
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o",
-                            "\u00F4", "\u00F2", "\u00F3", "\u00F6", "\u00F5", "\u0153", "\u014D")
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW2_10, key("\u00F8", moreKey("\u00F6")))
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    .replaceKeyOfLabel(Nordic.ROW2_11, key("\u00E6", moreKey("\u00E4")))
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
-                    .setMoreKeysOf("a", "\u00E0", "\u00E4", "\u00E1", "\u00E2", "\u00E3", "\u0101");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegianColemak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegianColemak.java
new file mode 100644
index 0000000..689c38e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsNorwegianColemak.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.Colemak;
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.customizer.NorwegianCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * nb: Norwegian Bokmål/colemak
+ */
+@SmallTest
+public final class TestsNorwegianColemak extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("nb");
+    private static final LayoutBase LAYOUT = new Colemak(new NorwegianColemakCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class NorwegianColemakCustomizer extends NorwegianCustomizer {
+        NorwegianColemakCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+            // Colemak layout doesn't have Nordic keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                    // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
+                    .setMoreKeysOf("a", "\u00E5", "\u00E6", "\u00E4", "\u00E0", "\u00E1", "\u00E2",
+                            "\u00E3", "\u0101");
+        }
+
+        @Override
+        protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                    // U+0153: "œ" LATIN SMALL LIGATURE OE
+                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                    .setMoreKeysOf("o", "\u00F8", "\u00F6", "\u00F4", "\u00F2", "\u00F3", "\u00F5",
+                            "\u0153", "\u014D");
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPersian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPersian.java
index b7d75c9..8ea8075 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPersian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPersian.java
@@ -19,7 +19,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.Farsi;
-import com.android.inputmethod.keyboard.layout.Farsi.FarsiCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 
 import java.util.Locale;
@@ -30,7 +29,7 @@
 @SmallTest
 public class TestsPersian extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("fa");
-    private static final LayoutBase LAYOUT = new Farsi(new FarsiCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Farsi(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPolish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPolish.java
index 04f88c3..4f1170a 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPolish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPolish.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class PolishCustomizer extends LayoutCustomizer {
-        public PolishCustomizer(final Locale locale) { super(locale); }
+        PolishCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortugueseBR.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortugueseBR.java
index 8a984a7..7fadaac 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortugueseBR.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortugueseBR.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.PortugueseCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortuguesePT.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortuguesePT.java
index e15e811..5936e8d 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortuguesePT.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsPortuguesePT.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.PortugueseCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class PortuguesePTCustomizer extends PortugueseCustomizer {
         private final EuroCustomizer mEuroCustomizer;
 
-        public PortuguesePTCustomizer(final Locale locale) {
+        PortuguesePTCustomizer(final Locale locale) {
             super(locale);
             mEuroCustomizer = new EuroCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyEmail.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyEmail.java
index 8563d69..cc204de 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyEmail.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyEmail.java
@@ -24,6 +24,7 @@
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -42,32 +43,31 @@
     @Override
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
-            final boolean languageSwitchKeyEnabled) {
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
         final EditorInfo emailField = new EditorInfo();
         emailField.inputType =
                 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
         return super.createKeyboardLayoutSet(
-                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled);
+                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled,
+                splitLayoutEnabled);
     }
 
     private static class EnglishEmailCustomizer extends EnglishCustomizer {
-        EnglishEmailCustomizer(final Locale locale) {
-            super(locale);
-        }
+        EnglishEmailCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getEnterKey(final boolean isPhone) {
-            return isPhone ? LayoutBase.ENTER_KEY : super.getEnterKey(isPhone);
+            return isPhone ? ENTER_KEY : super.getEnterKey(isPhone);
         }
 
         @Override
         public ExpectedKey getEmojiKey(final boolean isPhone) {
-            return LayoutBase.DOMAIN_KEY;
+            return DOMAIN_KEY;
         }
 
         @Override
         public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            return joinKeys(key("@", LayoutBase.SETTINGS_KEY));
+            return joinKeys(key("@", SETTINGS_KEY));
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyUrl.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyUrl.java
index 1c1a2bb..acd09d2 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyUrl.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsQwertyUrl.java
@@ -24,6 +24,7 @@
 import com.android.inputmethod.keyboard.KeyboardLayoutSet;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -42,32 +43,31 @@
     @Override
     protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
             final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
-            final boolean languageSwitchKeyEnabled) {
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
         final EditorInfo emailField = new EditorInfo();
         emailField.inputType =
                 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
         return super.createKeyboardLayoutSet(
-                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled);
+                subtype, emailField, voiceInputKeyEnabled, languageSwitchKeyEnabled,
+                splitLayoutEnabled);
     }
 
     private static class EnglishUrlCustomizer extends EnglishCustomizer {
-        EnglishUrlCustomizer(final Locale locale) {
-            super(locale);
-        }
+        EnglishUrlCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getEnterKey(final boolean isPhone) {
-            return isPhone ? LayoutBase.ENTER_KEY : super.getEnterKey(isPhone);
+            return isPhone ? ENTER_KEY : super.getEnterKey(isPhone);
         }
 
         @Override
         public ExpectedKey getEmojiKey(final boolean isPhone) {
-            return LayoutBase.DOMAIN_KEY;
+            return DOMAIN_KEY;
         }
 
         @Override
         public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
-            return joinKeys(key("/", LayoutBase.SETTINGS_KEY));
+            return joinKeys(key("/", SETTINGS_KEY));
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRomanian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRomanian.java
index 0207f1c..af4fbca 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRomanian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRomanian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class RomanianCustomizer extends LayoutCustomizer {
-        public RomanianCustomizer(final Locale locale) { super(locale); }
+        RomanianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_L9R; }
@@ -59,9 +59,9 @@
                     // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
                     // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
                     .setMoreKeysOf("i", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
+                    // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
                     // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
                     // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    // U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
                     // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
                     // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
                     // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
@@ -69,7 +69,7 @@
                     // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
                     // U+0101: "ā" LATIN SMALL LETTER A WITH MACRON
                     .setMoreKeysOf("a",
-                            "\u00E2", "\u00E3", "\u0103", "\u00E0", "\u00E1", "\u00E4", "\u00E6",
+                            "\u0103", "\u00E2", "\u00E3", "\u00E0", "\u00E1", "\u00E4", "\u00E6",
                             "\u00E5", "\u0101")
                     // U+0219: "ș" LATIN SMALL LETTER S WITH COMMA BELOW
                     // U+00DF: "ß" LATIN SMALL LETTER SHARP S
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRussian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRussian.java
index 9919207..75ef481 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRussian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsRussian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.EastSlavic;
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class RussianCustomizer extends EastSlavicCustomizer {
-        public RussianCustomizer(final Locale locale) { super(locale); }
+        RussianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbian.java
index 41f1690..9495706 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbian.java
@@ -20,8 +20,8 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.SouthSlavic;
-import com.android.inputmethod.keyboard.layout.SouthSlavic.SouthSlavicLayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.SouthSlavicLayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class SerbianCustomizer extends SouthSlavicLayoutCustomizer {
-        public SerbianCustomizer(final Locale locale) { super(locale); }
+        SerbianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java
new file mode 100644
index 0000000..7490d30
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatin.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.SerbianQwertz;
+import com.android.inputmethod.keyboard.layout.customizer.SerbianLatinCustomizer;
+
+import java.util.Locale;
+
+/**
+ * sr_ZZ: Serbian (Latin)/serbian_qwertz
+ */
+@SmallTest
+public final class TestsSerbianLatin extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("sr", "ZZ");
+    private static final LayoutBase LAYOUT = new SerbianQwertz(new SerbianLatinCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java
new file mode 100644
index 0000000..6d9351c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSerbianLatinQwerty.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.SerbianLatinCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * sr_ZZ: Serbian (Latin)/qwerty
+ */
+@SmallTest
+public final class TestsSerbianLatinQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("sr", "ZZ");
+    private static final LayoutBase LAYOUT = new Qwerty(new SerbianLatinQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class SerbianLatinQwertyCustomizer extends SerbianLatinCustomizer {
+        SerbianLatinQwertyCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return isPhone ? EMPTY_KEYS
+                    : joinKeys(EXCLAMATION_AND_QUESTION_MARKS, SHIFT_KEY);
+        }
+
+        @Override
+        protected void setSerbianKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTY layout doesn't have Serbian Latin Keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfS(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+                    .setMoreKeysOf("s", "\u0161")
+                    .setAdditionalMoreKeysPositionOf("s", 2);
+        }
+
+        @Override
+        protected void setMoreKeysOfC(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+010D: "č" LATIN SMALL LETTER C WITH CARON
+                    // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+                    .setMoreKeysOf("c", "\u010D", "\u0107")
+                    .setAdditionalMoreKeysPositionOf("c", 3);
+        }
+
+        @Override
+        protected void setMoreKeysOfD(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+0111: "đ" LATIN SMALL LETTER D WITH STROKE
+                    .setMoreKeysOf("d", "\u0111")
+                    .setAdditionalMoreKeysPositionOf("d", 2);
+        }
+
+        @Override
+        protected void setMoreKeysOfZ(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
+                    .setMoreKeysOf("z", "\u017E")
+                    .setAdditionalMoreKeysPositionOf("z", 2);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSinhalaLK.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSinhalaLK.java
index 8b86135..c55c17c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSinhalaLK.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSinhalaLK.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Sinhala;
-import com.android.inputmethod.keyboard.layout.Sinhala.SinhalaCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @Suppress
 public final class TestsSinhalaLK extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("si", "LK");
-    private static final LayoutBase LAYOUT = new Sinhala(new SinhalaCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Sinhala(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovak.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovak.java
index bdaf0ca..c944716 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovak.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovak.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class SlovakCustomizer extends EuroCustomizer {
-        public SlovakCustomizer(final Locale locale) { super(locale); }
+        SlovakCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovenian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovenian.java
index cdb1bee..e49a27b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovenian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSlovenian.java
@@ -19,9 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class SlovenianCustomizer extends EuroCustomizer {
-        public SlovenianCustomizer(final Locale locale) { super(locale); }
+        SlovenianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_R9L; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish.java
index 12e8676..6c86931 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -39,7 +40,7 @@
     private static class SpanishESCustomizer extends SpanishCustomizer {
         private final EuroCustomizer mEuroCustomizer;
 
-        public SpanishESCustomizer(final Locale locale) {
+        SpanishESCustomizer(final Locale locale) {
             super(locale);
             mEuroCustomizer = new EuroCustomizer(locale);
         }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish419.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish419.java
index 75aad13..828f4c4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish419.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanish419.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanishUS.java
index c3ac0a0..b5bfbe4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanishUS.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSpanishUS.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSplitLayoutQwertyEnglishUS.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSplitLayoutQwertyEnglishUS.java
new file mode 100644
index 0000000..c401d3d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSplitLayoutQwertyEnglishUS.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+
+import java.util.Locale;
+
+/**
+ * en_US: English (United States)/qwerty - split layout
+ */
+@SmallTest
+public class TestsSplitLayoutQwertyEnglishUS extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("en", "US");
+    private static final LayoutBase LAYOUT = new Qwerty(new EnglishSplitCustomizer(LOCALE));
+
+    @Override
+    protected KeyboardLayoutSet createKeyboardLayoutSet(final InputMethodSubtype subtype,
+            final EditorInfo editorInfo, final boolean voiceInputKeyEnabled,
+            final boolean languageSwitchKeyEnabled, final boolean splitLayoutEnabled) {
+        return super.createKeyboardLayoutSet(subtype, editorInfo, voiceInputKeyEnabled,
+            languageSwitchKeyEnabled, true /* splitLayoutEnabled */);
+    }
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class EnglishSplitCustomizer extends EnglishCustomizer {
+        EnglishSplitCustomizer(Locale locale) { super(locale); }
+
+        @Override
+        public ExpectedKey[] getSpaceKeys(final boolean isPhone) {
+            if (isPhone) {
+                return super.getSpaceKeys(isPhone);
+            }
+            return joinKeys(LANGUAGE_SWITCH_KEY, SPACE_KEY, SPACE_KEY);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwahili.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwahili.java
index 13b9741..a8ab966 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwahili.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwahili.java
@@ -19,8 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -37,7 +37,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class SwahiliCustomizer extends LayoutCustomizer {
-        public SwahiliCustomizer(final Locale locale) { super(locale); }
+        SwahiliCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedish.java
index 9b58914..061001d 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedish.java
@@ -19,11 +19,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Nordic;
-import com.android.inputmethod.keyboard.layout.Symbols;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
-import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.keyboard.layout.customizer.SwedishCustomizer;
 
 import java.util.Locale;
 
@@ -37,88 +34,4 @@
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
-
-    private static class SwedishCustomizer extends EuroCustomizer {
-        public SwedishCustomizer(final Locale locale) { super(locale); }
-
-        @Override
-        public ExpectedKey[] getDoubleAngleQuoteKeys() { return Symbols.DOUBLE_ANGLE_QUOTES_RL; }
-
-        @Override
-        public ExpectedKey[] getSingleAngleQuoteKeys() { return Symbols.SINGLE_ANGLE_QUOTES_RL; }
-
-        @Override
-        public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
-                    // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-                    // U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
-                    // U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS
-                    // U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK
-                    .setMoreKeysOf("e", "\u00E9", "\u00E8", "\u00EA", "\u00EB", "\u0119")
-                    // U+0159: "ř" LATIN SMALL LETTER R WITH CARON
-                    .setMoreKeysOf("r", "\u0159")
-                    // U+0165: "ť" LATIN SMALL LETTER T WITH CARON
-                    // U+00FE: "þ" LATIN SMALL LETTER THORN
-                    .setMoreKeysOf("t", "\u0165", "\u00FE")
-                    // U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE
-                    // U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS
-                    .setMoreKeysOf("y", "\u00FD", "\u00FF")
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FC", "\u00FA", "\u00F9", "\u00FB", "\u016B")
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    .setMoreKeysOf("i", "\u00ED", "\u00EC", "\u00EE", "\u00EF")
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o", "\u00F3", "\u00F2", "\u00F4", "\u00F5", "\u014D")
-                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
-                    .replaceKeyOfLabel(Nordic.ROW1_11, "\u00E5")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    .replaceKeyOfLabel(Nordic.ROW2_10,
-                            key("\u00F6", joinMoreKeys("\u00F8", "\u0153")))
-                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
-                    // U+00E6: "æ" LATIN SMALL LETTER AE
-                    .replaceKeyOfLabel(Nordic.ROW2_11, key("\u00E4", moreKey("\u00E6")))
-                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
-                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
-                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-                    .setMoreKeysOf("a", "\u00E1", "\u00E0", "\u00E2", "\u0105", "\u00E3")
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    .setMoreKeysOf("s", "\u015B", "\u0161", "\u015F", "\u00DF")
-                    // U+00F0: "ð" LATIN SMALL LETTER ETH
-                    // U+010F: "ď" LATIN SMALL LETTER D WITH CARON
-                    .setMoreKeysOf("d", "\u00F0", "\u010F")
-                    // U+0142: "ł" LATIN SMALL LETTER L WITH STROKE
-                    .setMoreKeysOf("l", "\u0142")
-                    // U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE
-                    // U+017E: "ž" LATIN SMALL LETTER Z WITH CARON
-                    // U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE
-                    .setMoreKeysOf("z", "\u017A", "\u017E", "\u017C")
-                    // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                    // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                    // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                    .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D")
-                    // U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE
-                    // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-                    // U+0148: "ň" LATIN SMALL LETTER N WITH CARON
-                    .setMoreKeysOf("n", "\u0144", "\u00F1", "\u0148");
-        }
-    }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedishPcQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedishPcQwerty.java
new file mode 100644
index 0000000..dc3d831
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsSwedishPcQwerty.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.PcQwerty;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.PcQwertyCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.SwedishCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * sv: Swedish/pcqwerty
+ */
+@SmallTest
+public final class TestsSwedishPcQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("sv");
+    private static final LayoutBase LAYOUT = new PcQwerty(new SwedishPcQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class SwedishPcQwertyCustomizer extends SwedishCustomizer {
+        private final LayoutCustomizer mPcQwertyCustomizer;
+
+        SwedishPcQwertyCustomizer(final Locale locale) {
+            super(locale);
+            mPcQwertyCustomizer = new PcQwertyCustomizer(locale);
+        }
+
+        @Override
+        public ExpectedKey getCurrencyKey() {
+            return mPcQwertyCustomizer.getCurrencyKey();
+        }
+
+        @Override
+        public ExpectedKey[] getOtherCurrencyKeys() {
+            return mPcQwertyCustomizer.getOtherCurrencyKeys();
+        }
+
+        @Override
+        public int getNumberOfRows() {
+            return mPcQwertyCustomizer.getNumberOfRows();
+        }
+
+        @Override
+        public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+            return mPcQwertyCustomizer.getLeftShiftKeys(isPhone);
+        }
+
+        @Override
+        public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+            return mPcQwertyCustomizer.getRightShiftKeys(isPhone);
+        }
+
+        @Override
+        public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
+            return mPcQwertyCustomizer.getKeysLeftToSpacebar(isPhone);
+        }
+
+        @Override
+        public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
+            return mPcQwertyCustomizer.getKeysRightToSpacebar(isPhone);
+        }
+
+        @Override
+        protected void setNordicKeys(final ExpectedKeyboardBuilder builder) {
+            // PC QWERTY layout doesn't have Nordic keys.
+        }
+
+        @Override
+        protected void setMoreKeysOfA(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+                    // U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+                    // U+00E6: "æ" LATIN SMALL LETTER AE
+                    // U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+                    // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+                    // U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
+                    // U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
+                    .setMoreKeysOf("a", "\u00E4", "\u00E5", "\u00E6", "\u00E1", "\u00E0", "\u00E2",
+                            "\u0105", "\u00E3");
+        }
+
+        @Override
+        protected void setMoreKeysOfO(final ExpectedKeyboardBuilder builder) {
+            builder
+                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+                    // U+0153: "œ" LATIN SMALL LIGATURE OE
+                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
+                    .setMoreKeysOf("o", "\u00F6", "\u00F8", "\u0153", "\u00F3", "\u00F2", "\u00F4",
+                            "\u00F5", "\u014D");
+        }
+
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTagalog.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTagalog.java
index 38d5364..ecef2d7 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTagalog.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTagalog.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Spanish;
+import com.android.inputmethod.keyboard.layout.customizer.SpanishCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -36,15 +37,11 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class TagalogCustomizer extends SpanishCustomizer {
-
-        public TagalogCustomizer(final Locale locale) {
-            super(locale);
-        }
+        TagalogCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
-            return isPhone ? LayoutBase.PHONE_PUNCTUATION_MORE_KEYS
-                    : LayoutBase.TABLET_PUNCTUATION_MORE_KEYS;
+            return isPhone ? PHONE_PUNCTUATION_MORE_KEYS : TABLET_PUNCTUATION_MORE_KEYS;
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilIN.java
index 31df53c..3297d39 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilIN.java
@@ -22,7 +22,7 @@
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
 import com.android.inputmethod.keyboard.layout.Tamil;
-import com.android.inputmethod.keyboard.layout.Tamil.TamilCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.TamilCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class TamilINCustomizer extends TamilCustomizer {
-        public TamilINCustomizer(final Locale locale) { super(locale); }
+        TamilINCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
index 65ec0b0..72872ba 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilLK.java
@@ -22,7 +22,7 @@
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
 import com.android.inputmethod.keyboard.layout.Tamil;
-import com.android.inputmethod.keyboard.layout.Tamil.TamilCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.TamilCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 
 import java.util.Locale;
@@ -39,7 +39,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class TamilLKCustomizer extends TamilCustomizer {
-        public TamilLKCustomizer(final Locale locale) { super(locale); }
+        TamilLKCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_RUPEE; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilSG.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilSG.java
index ade7aba..a7a041b 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilSG.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTamilSG.java
@@ -20,7 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Tamil;
-import com.android.inputmethod.keyboard.layout.Tamil.TamilCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.TamilCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTeluguIN.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTeluguIN.java
index 04996d9..2b202a9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTeluguIN.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTeluguIN.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Telugu;
-import com.android.inputmethod.keyboard.layout.Telugu.TeluguCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsTeluguIN extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("te", "IN");
-    private static final LayoutBase LAYOUT = new Telugu(new TeluguCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Telugu(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsThai.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsThai.java
index 3c87272..2c1a29e 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsThai.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsThai.java
@@ -20,7 +20,6 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Thai;
-import com.android.inputmethod.keyboard.layout.Thai.ThaiCustomizer;
 
 import java.util.Locale;
 
@@ -30,7 +29,7 @@
 @SmallTest
 public final class TestsThai extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("th");
-    private static final LayoutBase LAYOUT = new Thai(new ThaiCustomizer(LOCALE));
+    private static final LayoutBase LAYOUT = new Thai(LOCALE);
 
     @Override
     LayoutBase getLayout() { return LAYOUT; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTurkish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTurkish.java
index b35f885..95f86e4 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTurkish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsTurkish.java
@@ -19,8 +19,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.EuroCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EuroCustomizer;
+import com.android.inputmethod.keyboard.layout.customizer.TurkicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
 import java.util.Locale;
@@ -37,50 +38,16 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class TurkishCustomizer extends EuroCustomizer {
-        public TurkishCustomizer(final Locale locale) { super(locale); }
+        private final TurkicCustomizer mTurkicCustomizer;
+
+        TurkishCustomizer(final Locale locale) {
+            super(locale);
+            mTurkicCustomizer = new TurkicCustomizer(locale);
+        }
 
         @Override
         public ExpectedKeyboardBuilder setAccentedLetters(final ExpectedKeyboardBuilder builder) {
-            return builder
-                    // U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
-                    // U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
-                    // U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
-                    // U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
-                    // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-                    .setMoreKeysOf("u", "\u00FC", "\u00FB", "\u00F9", "\u00FA", "\u016B")
-                    // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-                    // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-                    // U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
-                    // U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
-                    // U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
-                    // U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
-                    // U+012B: "ī" LATIN SMALL LETTER I WITH MACRON
-                    .setMoreKeysOf("i",
-                            "\u0131", "\u00EE", "\u00EF", "\u00EC", "\u00ED", "\u012F", "\u012B")
-                    // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-                    // U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
-                    // U+0153: "œ" LATIN SMALL LIGATURE OE
-                    // U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
-                    // U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-                    // U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
-                    // U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
-                    // U+014D: "ō" LATIN SMALL LETTER O WITH MACRON
-                    .setMoreKeysOf("o",
-                            "\u00F6", "\u00F4", "\u0153", "\u00F2", "\u00F3", "\u00F5", "\u00F8",
-                            "\u014D")
-                    // U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
-                    .setMoreKeysOf("a", "\u00E2")
-                    // U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
-                    // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-                    // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-                    // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-                    .setMoreKeysOf("s", "\u015F", "\u00DF", "\u015B", "\u0161")
-                    // U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE
-                    .setMoreKeysOf("g", "\u011F")
-                    // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-                    // U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
-                    // U+010D: "č" LATIN SMALL LETTER C WITH CARON
-                    .setMoreKeysOf("c", "\u00E7", "\u0107", "\u010D");
+            return mTurkicCustomizer.setAccentedLetters(builder);
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUkrainian.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUkrainian.java
index a6bcacc..da93d6c 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUkrainian.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUkrainian.java
@@ -19,10 +19,10 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.EastSlavic;
-import com.android.inputmethod.keyboard.layout.EastSlavic.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.EastSlavicCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -40,7 +40,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class UkrainianCustomizer extends EastSlavicCustomizer {
-        public UkrainianCustomizer(final Locale locale) { super(locale); }
+        UkrainianCustomizer(final Locale locale) { super(locale); }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_HRYVNIA; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
new file mode 100644
index 0000000..fd12a6a
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbek.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Uzbek;
+import com.android.inputmethod.keyboard.layout.customizer.UzbekCustomizer;
+
+import java.util.Locale;
+
+/**
+ * uz_UZ: Uzbek (Uzbekistan)/uzbek
+ */
+@SmallTest
+public final class TestsUzbek extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("uz", "UZ");
+    private static final LayoutBase LAYOUT = new Uzbek(new UzbekCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
new file mode 100644
index 0000000..4c33a8c
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsUzbekQwerty.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.UzbekCustomizer;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+
+import java.util.Locale;
+
+/**
+ * uz_UZ: Uzbek (Uzbekistan)/qwerty
+ */
+@SmallTest
+public final class TestsUzbekQwerty extends LayoutTestsBase {
+    private static final Locale LOCALE = new Locale("uz", "UZ");
+    private static final LayoutBase LAYOUT = new Qwerty(new UzbekQwertyCustomizer(LOCALE));
+
+    @Override
+    LayoutBase getLayout() { return LAYOUT; }
+
+    private static class UzbekQwertyCustomizer extends UzbekCustomizer {
+        UzbekQwertyCustomizer(final Locale locale) { super(locale); }
+
+        @Override
+        protected void setUzbekKeys(final ExpectedKeyboardBuilder builder) {
+            // QWERTY layout doesn't have Uzebk keys.
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsVietnamese.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsVietnamese.java
index 83d86ac..356b042 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsVietnamese.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsVietnamese.java
@@ -19,10 +19,10 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
-import com.android.inputmethod.keyboard.layout.LayoutBase.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.Qwerty;
 import com.android.inputmethod.keyboard.layout.Symbols;
 import com.android.inputmethod.keyboard.layout.SymbolsShifted;
+import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
 
@@ -40,9 +40,7 @@
     LayoutBase getLayout() { return LAYOUT; }
 
     private static class VietnameseCustomizer extends LayoutCustomizer {
-        public VietnameseCustomizer(final Locale locale) {
-            super(locale);
-        }
+        VietnameseCustomizer(final Locale locale) { super(locale);  }
 
         @Override
         public ExpectedKey getCurrencyKey() { return CURRENCY_DONG; }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsZulu.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsZulu.java
index e048e92..abf3cad 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsZulu.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsZulu.java
@@ -20,6 +20,7 @@
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
+import com.android.inputmethod.keyboard.layout.customizer.EnglishCustomizer;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
deleted file mode 100644
index ae18426..0000000
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java
+++ /dev/null
@@ -1,692 +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;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Pair;
-
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
-import com.android.inputmethod.latin.makedict.DictDecoder;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.makedict.FormatSpec;
-import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.TimeUnit;
-
-@LargeTest
-public class BinaryDictionaryDecayingTests extends AndroidTestCase {
-    private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-    private static final String TEST_LOCALE = "test";
-    private static final int DUMMY_PROBABILITY = 0;
-    private static final int[] DICT_FORMAT_VERSIONS =
-            new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
-
-    private int mCurrentTime = 0;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mCurrentTime = 0;
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        stopTestModeInNativeCode();
-        super.tearDown();
-    }
-
-    private static boolean supportsBeginningOfSentence(final int formatVersion) {
-        return formatVersion > FormatSpec.VERSION401;
-    }
-
-    private void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
-            final int probability) {
-        binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
-                BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
-                false /* isBeginningOfSentence */, false /* isNotAWord */,
-                false /* isBlacklisted */, mCurrentTime /* timestamp */);
-    }
-
-    private void addBigramWords(final BinaryDictionary binaryDictionary, final String word0,
-            final String word1, final int probability) {
-        binaryDictionary.addNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1, probability,
-                mCurrentTime /* timestamp */);
-    }
-
-    private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
-            final String word0, final String word1) {
-        return binaryDictionary.isValidNgram(new PrevWordsInfo(new WordInfo(word0)), word1);
-    }
-
-    private void forcePassingShortTime(final BinaryDictionary binaryDictionary) {
-        // 30 days.
-        final int timeToElapse = (int)TimeUnit.SECONDS.convert(30, TimeUnit.DAYS);
-        mCurrentTime += timeToElapse;
-        setCurrentTimeForTestMode(mCurrentTime);
-        binaryDictionary.flushWithGC();
-    }
-
-    private void forcePassingLongTime(final BinaryDictionary binaryDictionary) {
-        // 365 days.
-        final int timeToElapse = (int)TimeUnit.SECONDS.convert(365, TimeUnit.DAYS);
-        mCurrentTime += timeToElapse;
-        setCurrentTimeForTestMode(mCurrentTime);
-        binaryDictionary.flushWithGC();
-    }
-
-    private File createEmptyDictionaryAndGetFile(final String dictId,
-            final int formatVersion) throws IOException {
-        if (formatVersion == FormatSpec.VERSION4
-                || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
-                || formatVersion == FormatSpec.VERSION4_DEV) {
-            return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
-        } else {
-            throw new IOException("Dictionary format version " + formatVersion
-                    + " is not supported.");
-        }
-    }
-
-    private File createEmptyVer4DictionaryAndGetFile(final String dictId, final int formatVersion)
-            throws IOException {
-        final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
-                getContext().getCacheDir());
-        FileUtils.deleteRecursively(file);
-        Map<String, String> attributeMap = new HashMap<>();
-        attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId);
-        attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
-                String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
-        attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
-                LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
-            return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created. Foramt version: " + formatVersion);
-        }
-    }
-
-    private static int setCurrentTimeForTestMode(final int currentTime) {
-        return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime);
-    }
-
-    private static int stopTestModeInNativeCode() {
-        return BinaryDictionaryUtils.setCurrentTimeForTest(-1);
-    }
-
-    public void testReadDictInJavaSide() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testReadDictInJavaSide(formatVersion);
-        }
-    }
-
-    private void testReadDictInJavaSide(final int formatVersion) {
-        setCurrentTimeForTestMode(mCurrentTime);
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "ab", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "aaa", DUMMY_PROBABILITY);
-        binaryDictionary.flushWithGC();
-        binaryDictionary.close();
-
-        final DictDecoder dictDecoder =
-                BinaryDictIOUtils.getDictDecoder(dictFile, 0, dictFile.length());
-        try {
-            final FusionDictionary dict =
-                    dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
-            PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "a");
-            assertNotNull(ptNode);
-            assertTrue(ptNode.isTerminal());
-            assertNotNull(ptNode.getBigram("aaa"));
-            ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "ab");
-            assertNotNull(ptNode);
-            assertTrue(ptNode.isTerminal());
-            ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa");
-            assertNotNull(ptNode);
-            assertTrue(ptNode.isTerminal());
-        } catch (IOException e) {
-            fail("IOException while reading dictionary: " + e);
-        } catch (UnsupportedFormatException e) {
-            fail("Unsupported format: " + e);
-        }
-        dictFile.delete();
-    }
-
-    public void testControlCurrentTime() {
-        final int TEST_COUNT = 1000;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-        final int startTime = stopTestModeInNativeCode();
-        for (int i = 0; i < TEST_COUNT; i++) {
-            final int currentTime = random.nextInt(Integer.MAX_VALUE);
-            final int currentTimeInNativeCode = setCurrentTimeForTestMode(currentTime);
-            assertEquals(currentTime, currentTimeInNativeCode);
-        }
-        final int endTime = stopTestModeInNativeCode();
-        final int MAX_ALLOWED_ELAPSED_TIME = 10;
-        assertTrue(startTime <= endTime && endTime <= startTime + MAX_ALLOWED_ELAPSED_TIME);
-    }
-
-    public void testAddValidAndInvalidWords() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddValidAndInvalidWords(formatVersion);
-        }
-    }
-
-    private void testAddValidAndInvalidWords(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
-        assertFalse(binaryDictionary.isValidWord("a"));
-        addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
-        addUnigramWord(binaryDictionary, "a", Dictionary.NOT_A_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("a"));
-
-        addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("b"));
-
-        addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
-        assertFalse(isValidBigram(binaryDictionary, "a", "b"));
-        addBigramWords(binaryDictionary, "a", "b", Dictionary.NOT_A_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "a", "b"));
-
-        addUnigramWord(binaryDictionary, "c", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "c", DUMMY_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "a", "c"));
-
-        // Add bigrams of not valid unigrams.
-        addBigramWords(binaryDictionary, "x", "y", Dictionary.NOT_A_PROBABILITY);
-        assertFalse(isValidBigram(binaryDictionary, "x", "y"));
-        addBigramWords(binaryDictionary, "x", "y", DUMMY_PROBABILITY);
-        assertFalse(isValidBigram(binaryDictionary, "x", "y"));
-
-        binaryDictionary.close();
-        dictFile.delete();
-    }
-
-    public void testDecayingProbability() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testDecayingProbability(formatVersion);
-        }
-    }
-
-    private void testDecayingProbability(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("a"));
-        forcePassingShortTime(binaryDictionary);
-        assertFalse(binaryDictionary.isValidWord("a"));
-
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("a"));
-        forcePassingShortTime(binaryDictionary);
-        assertTrue(binaryDictionary.isValidWord("a"));
-        forcePassingLongTime(binaryDictionary);
-        assertFalse(binaryDictionary.isValidWord("a"));
-
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "a", "b"));
-        forcePassingShortTime(binaryDictionary);
-        assertFalse(isValidBigram(binaryDictionary, "a", "b"));
-
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "a", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "b", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "a", "b", DUMMY_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "a", "b"));
-        forcePassingShortTime(binaryDictionary);
-        assertTrue(isValidBigram(binaryDictionary, "a", "b"));
-        forcePassingLongTime(binaryDictionary);
-        assertFalse(isValidBigram(binaryDictionary, "a", "b"));
-
-        binaryDictionary.close();
-        dictFile.delete();
-    }
-
-    public void testAddManyUnigramsToDecayingDict() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddManyUnigramsToDecayingDict(formatVersion);
-        }
-    }
-
-    private void testAddManyUnigramsToDecayingDict(final int formatVersion) {
-        final int unigramCount = 30000;
-        final int unigramTypedCount = 100000;
-        final int codePointSetSize = 50;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        setCurrentTimeForTestMode(mCurrentTime);
-
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-        final ArrayList<String> words = new ArrayList<>();
-
-        for (int i = 0; i < unigramCount; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            words.add(word);
-        }
-
-        final int maxUnigramCount = Integer.parseInt(
-                binaryDictionary.getPropertyForTest(BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY));
-        for (int i = 0; i < unigramTypedCount; i++) {
-            final String word = words.get(random.nextInt(words.size()));
-            addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
-
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                final int unigramCountBeforeGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.UNIGRAM_COUNT_QUERY));
-                while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                    forcePassingShortTime(binaryDictionary);
-                }
-                final int unigramCountAfterGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.UNIGRAM_COUNT_QUERY));
-                assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
-            }
-        }
-
-        assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.UNIGRAM_COUNT_QUERY)) > 0);
-        assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.UNIGRAM_COUNT_QUERY)) <= maxUnigramCount);
-        forcePassingLongTime(binaryDictionary);
-        assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.UNIGRAM_COUNT_QUERY)));
-    }
-
-    public void testOverflowUnigrams() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testOverflowUnigrams(formatVersion);
-        }
-    }
-
-    private void testOverflowUnigrams(final int formatVersion) {
-        final int unigramCount = 20000;
-        final int eachUnigramTypedCount = 2;
-        final int strongUnigramTypedCount = 20;
-        final int weakUnigramTypedCount = 1;
-        final int codePointSetSize = 50;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        setCurrentTimeForTestMode(mCurrentTime);
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        final String strong = "strong";
-        final String weak = "weak";
-        for (int j = 0; j < strongUnigramTypedCount; j++) {
-            addUnigramWord(binaryDictionary, strong, DUMMY_PROBABILITY);
-        }
-        for (int j = 0; j < weakUnigramTypedCount; j++) {
-            addUnigramWord(binaryDictionary, weak, DUMMY_PROBABILITY);
-        }
-        assertTrue(binaryDictionary.isValidWord(strong));
-        assertTrue(binaryDictionary.isValidWord(weak));
-
-        for (int i = 0; i < unigramCount; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            for (int j = 0; j < eachUnigramTypedCount; j++) {
-                addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
-            }
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                final int unigramCountBeforeGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.UNIGRAM_COUNT_QUERY));
-                assertTrue(binaryDictionary.isValidWord(strong));
-                assertTrue(binaryDictionary.isValidWord(weak));
-                binaryDictionary.flushWithGC();
-                final int unigramCountAfterGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.UNIGRAM_COUNT_QUERY));
-                assertTrue(unigramCountBeforeGC > unigramCountAfterGC);
-                assertFalse(binaryDictionary.isValidWord(weak));
-                assertTrue(binaryDictionary.isValidWord(strong));
-                break;
-            }
-        }
-    }
-
-    public void testAddManyBigramsToDecayingDict() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddManyBigramsToDecayingDict(formatVersion);
-        }
-    }
-
-    private void testAddManyBigramsToDecayingDict(final int formatVersion) {
-        final int unigramCount = 5000;
-        final int bigramCount = 30000;
-        final int bigramTypedCount = 100000;
-        final int codePointSetSize = 50;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        setCurrentTimeForTestMode(mCurrentTime);
-
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-        final ArrayList<String> words = new ArrayList<>();
-        final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
-
-        for (int i = 0; i < unigramCount; ++i) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            words.add(word);
-        }
-        for (int i = 0; i < bigramCount; ++i) {
-            final int word0Index = random.nextInt(words.size());
-            int word1Index = random.nextInt(words.size() - 1);
-            if (word1Index >= word0Index) {
-                word1Index += 1;
-            }
-            final String word0 = words.get(word0Index);
-            final String word1 = words.get(word1Index);
-            final Pair<String, String> bigram = new Pair<>(word0, word1);
-            bigrams.add(bigram);
-        }
-
-        final int maxBigramCount = Integer.parseInt(
-                binaryDictionary.getPropertyForTest(BinaryDictionary.MAX_BIGRAM_COUNT_QUERY));
-        for (int i = 0; i < bigramTypedCount; ++i) {
-            final Pair<String, String> bigram = bigrams.get(random.nextInt(bigrams.size()));
-            addUnigramWord(binaryDictionary, bigram.first, DUMMY_PROBABILITY);
-            addUnigramWord(binaryDictionary, bigram.second, DUMMY_PROBABILITY);
-            addBigramWords(binaryDictionary, bigram.first, bigram.second, DUMMY_PROBABILITY);
-
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                final int bigramCountBeforeGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.BIGRAM_COUNT_QUERY));
-                while (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                    forcePassingShortTime(binaryDictionary);
-                }
-                final int bigramCountAfterGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.BIGRAM_COUNT_QUERY));
-                assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
-            }
-        }
-
-        assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.BIGRAM_COUNT_QUERY)) > 0);
-        assertTrue(Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.BIGRAM_COUNT_QUERY)) <= maxBigramCount);
-        forcePassingLongTime(binaryDictionary);
-        assertEquals(0, Integer.parseInt(binaryDictionary.getPropertyForTest(
-                BinaryDictionary.BIGRAM_COUNT_QUERY)));
-    }
-
-    public void testOverflowBigrams() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testOverflowBigrams(formatVersion);
-        }
-    }
-
-    private void testOverflowBigrams(final int formatVersion) {
-        final int bigramCount = 20000;
-        final int unigramCount = 1000;
-        final int unigramTypedCount = 20;
-        final int eachBigramTypedCount = 2;
-        final int strongBigramTypedCount = 20;
-        final int weakBigramTypedCount = 1;
-        final int codePointSetSize = 50;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        setCurrentTimeForTestMode(mCurrentTime);
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        final ArrayList<String> words = new ArrayList<>();
-        for (int i = 0; i < unigramCount; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            words.add(word);
-            for (int j = 0; j < unigramTypedCount; j++) {
-                addUnigramWord(binaryDictionary, word, DUMMY_PROBABILITY);
-            }
-        }
-        final String strong = "strong";
-        final String weak = "weak";
-        final String target = "target";
-        for (int j = 0; j < unigramTypedCount; j++) {
-            addUnigramWord(binaryDictionary, strong, DUMMY_PROBABILITY);
-            addUnigramWord(binaryDictionary, weak, DUMMY_PROBABILITY);
-            addUnigramWord(binaryDictionary, target, DUMMY_PROBABILITY);
-        }
-        binaryDictionary.flushWithGC();
-        for (int j = 0; j < strongBigramTypedCount; j++) {
-            addBigramWords(binaryDictionary, strong, target, DUMMY_PROBABILITY);
-        }
-        for (int j = 0; j < weakBigramTypedCount; j++) {
-            addBigramWords(binaryDictionary, weak, target, DUMMY_PROBABILITY);
-        }
-        assertTrue(isValidBigram(binaryDictionary, strong, target));
-        assertTrue(isValidBigram(binaryDictionary, weak, target));
-
-        for (int i = 0; i < bigramCount; i++) {
-            final int word0Index = random.nextInt(words.size());
-            final String word0 = words.get(word0Index);
-            final int index = random.nextInt(words.size() - 1);
-            final int word1Index = (index >= word0Index) ? index + 1 : index;
-            final String word1 = words.get(word1Index);
-
-            for (int j = 0; j < eachBigramTypedCount; j++) {
-                addBigramWords(binaryDictionary, word0, word1, DUMMY_PROBABILITY);
-            }
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                final int bigramCountBeforeGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.BIGRAM_COUNT_QUERY));
-                binaryDictionary.flushWithGC();
-                final int bigramCountAfterGC =
-                        Integer.parseInt(binaryDictionary.getPropertyForTest(
-                                BinaryDictionary.BIGRAM_COUNT_QUERY));
-                assertTrue(bigramCountBeforeGC > bigramCountAfterGC);
-                assertTrue(isValidBigram(binaryDictionary, strong, target));
-                assertFalse(isValidBigram(binaryDictionary, weak, target));
-                break;
-            }
-        }
-    }
-
-    public void testDictMigration() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
-        }
-    }
-
-    private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
-        setCurrentTimeForTestMode(mCurrentTime);
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("aaa"));
-        addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
-        assertFalse(binaryDictionary.isValidWord("bbb"));
-        addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "ccc", DUMMY_PROBABILITY);
-        addUnigramWord(binaryDictionary, "abc", DUMMY_PROBABILITY);
-        addBigramWords(binaryDictionary, "aaa", "abc", DUMMY_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "abc"));
-        addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
-        assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb"));
-
-        assertEquals(fromFormatVersion, binaryDictionary.getFormatVersion());
-        assertTrue(binaryDictionary.migrateTo(toFormatVersion));
-        assertTrue(binaryDictionary.isValidDictionary());
-        assertEquals(toFormatVersion, binaryDictionary.getFormatVersion());
-        assertTrue(binaryDictionary.isValidWord("aaa"));
-        assertFalse(binaryDictionary.isValidWord("bbb"));
-        assertTrue(binaryDictionary.getFrequency("aaa") < binaryDictionary.getFrequency("ccc"));
-        addUnigramWord(binaryDictionary, "bbb", Dictionary.NOT_A_PROBABILITY);
-        assertTrue(binaryDictionary.isValidWord("bbb"));
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "abc"));
-        assertFalse(isValidBigram(binaryDictionary, "aaa", "bbb"));
-        addBigramWords(binaryDictionary, "aaa", "bbb", Dictionary.NOT_A_PROBABILITY);
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
-        binaryDictionary.close();
-        dictFile.delete();
-    }
-
-    public void testBeginningOfSentence() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            if (supportsBeginningOfSentence(formatVersion)) {
-                testBeginningOfSentence(formatVersion);
-            }
-        }
-    }
-
-    private void testBeginningOfSentence(final int formatVersion) {
-        setCurrentTimeForTestMode(mCurrentTime);
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        binaryDictionary.addUnigramEntry("", DUMMY_PROBABILITY, "" /* shortcutTarget */,
-                BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
-                true /* isBeginningOfSentence */, true /* isNotAWord */, false /* isBlacklisted */,
-                mCurrentTime);
-        final PrevWordsInfo prevWordsInfoStartOfSentence = PrevWordsInfo.BEGINNING_OF_SENTENCE;
-        addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
-        binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
-                mCurrentTime);
-        assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
-        binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
-                mCurrentTime);
-        addUnigramWord(binaryDictionary, "bbb", DUMMY_PROBABILITY);
-        binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "bbb", DUMMY_PROBABILITY,
-                mCurrentTime);
-        assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
-        assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
-
-        forcePassingLongTime(binaryDictionary);
-        assertFalse(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
-        assertFalse(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
-
-        addUnigramWord(binaryDictionary, "aaa", DUMMY_PROBABILITY);
-        binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "aaa", DUMMY_PROBABILITY,
-                mCurrentTime);
-        addUnigramWord(binaryDictionary, "bbb", DUMMY_PROBABILITY);
-        binaryDictionary.addNgramEntry(prevWordsInfoStartOfSentence, "bbb", DUMMY_PROBABILITY,
-                mCurrentTime);
-        assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "aaa"));
-        assertTrue(binaryDictionary.isValidNgram(prevWordsInfoStartOfSentence, "bbb"));
-        binaryDictionary.close();
-        dictFile.delete();
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index 6ba18d6..e96c934 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -21,14 +21,14 @@
 import android.text.TextUtils;
 import android.util.Pair;
 
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.CodePointUtils;
+import com.android.inputmethod.latin.common.FileUtils;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.WeightedString;
 import com.android.inputmethod.latin.makedict.WordProperty;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.FileUtils;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
 
 import java.io.File;
 import java.io.IOException;
@@ -36,103 +36,100 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Random;
 
-// TODO Use the seed passed as an argument for makedict test.
 @LargeTest
 public class BinaryDictionaryTests extends AndroidTestCase {
     private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
     private static final String TEST_LOCALE = "test";
-    private static final int[] DICT_FORMAT_VERSIONS =
-            new int[] { FormatSpec.VERSION4, FormatSpec.VERSION4_DEV };
+    private static final String DICTIONARY_ID = "TestBinaryDictionary";
 
-    private static boolean canCheckBigramProbability(final int formatVersion) {
-        return formatVersion > FormatSpec.VERSION401;
+    private HashSet<File> mDictFilesToBeDeleted = new HashSet<>();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDictFilesToBeDeleted.clear();
     }
 
-    private static boolean supportsBeginningOfSentence(final int formatVersion) {
-        return formatVersion > FormatSpec.VERSION401;
-    }
-
-    private File createEmptyDictionaryAndGetFile(final String dictId,
-            final int formatVersion) throws IOException {
-        if (formatVersion == FormatSpec.VERSION4
-                || formatVersion == FormatSpec.VERSION4_ONLY_FOR_TESTING
-                || formatVersion == FormatSpec.VERSION4_DEV) {
-            return createEmptyVer4DictionaryAndGetFile(dictId, formatVersion);
-        } else {
-            throw new IOException("Dictionary format version " + formatVersion
-                    + " is not supported.");
+    @Override
+    protected void tearDown() throws Exception {
+        for (final File dictFile : mDictFilesToBeDeleted) {
+            dictFile.delete();
         }
+        mDictFilesToBeDeleted.clear();
+        super.tearDown();
     }
 
-    private File createEmptyVer4DictionaryAndGetFile(final String dictId,
-            final int formatVersion) throws IOException {
-        final File file = File.createTempFile(dictId, TEST_DICT_FILE_EXTENSION,
+    private File createEmptyDictionaryAndGetFile(final int formatVersion) {
+        return createEmptyDictionaryWithAttributesAndGetFile(formatVersion,
+                new HashMap<String, String>());
+    }
+
+    private File createEmptyDictionaryWithAttributesAndGetFile(final int formatVersion,
+            final HashMap<String, String> attributeMap) {
+        try {
+            final File dictFile = createEmptyVer4DictionaryAndGetFile(formatVersion,
+                    attributeMap);
+            mDictFilesToBeDeleted.add(dictFile);
+            return dictFile;
+        } catch (final IOException e) {
+            fail(e.toString());
+        }
+        return null;
+    }
+
+    private File createEmptyVer4DictionaryAndGetFile(final int formatVersion,
+            final HashMap<String, String> attributeMap) throws IOException {
+        final File file = File.createTempFile(DICTIONARY_ID, TEST_DICT_FILE_EXTENSION,
                 getContext().getCacheDir());
         file.delete();
         file.mkdir();
-        Map<String, String> attributeMap = new HashMap<>();
         if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), formatVersion,
                 Locale.ENGLISH, attributeMap)) {
             return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created. Format version: " + formatVersion);
         }
+        throw new IOException("Empty dictionary " + file.getAbsolutePath()
+                + " cannot be created. Format version: " + formatVersion);
+    }
+
+    private static BinaryDictionary getBinaryDictionary(final File dictFile) {
+        return new BinaryDictionary(dictFile.getAbsolutePath(),
+                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+    }
+
+    private BinaryDictionary getEmptyBinaryDictionary(final int formatVersion) {
+        final File dictFile = createEmptyDictionaryAndGetFile(formatVersion);
+        return new BinaryDictionary(dictFile.getAbsolutePath(),
+                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
+                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
     }
 
     public void testIsValidDictionary() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testIsValidDictionary(formatVersion);
-        }
-    }
-
-    private void testIsValidDictionary(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+        BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
         assertTrue("binaryDictionary must be valid for existing valid dictionary file.",
                 binaryDictionary.isValidDictionary());
         binaryDictionary.close();
         assertFalse("binaryDictionary must be invalid after closing.",
                 binaryDictionary.isValidDictionary());
         FileUtils.deleteRecursively(dictFile);
-        binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), 0 /* offset */,
-                dictFile.length(), true /* useFullEditDistance */, Locale.getDefault(),
-                TEST_LOCALE, true /* isUpdatable */);
+        binaryDictionary = getBinaryDictionary(dictFile);
         assertFalse("binaryDictionary must be invalid for not existing dictionary file.",
                 binaryDictionary.isValidDictionary());
         binaryDictionary.close();
     }
 
     public void testConstructingDictionaryOnMemory() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testConstructingDictionaryOnMemory(formatVersion);
-        }
-    }
-
-    private void testConstructingDictionaryOnMemory(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
         FileUtils.deleteRecursively(dictFile);
         assertFalse(dictFile.exists());
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE, formatVersion,
-                new HashMap<String, String>());
+        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
+                true /* useFullEditDistance */, Locale.getDefault(), TEST_LOCALE,
+                FormatSpec.VERSION403, new HashMap<String, String>());
         assertTrue(binaryDictionary.isValidDictionary());
-        assertEquals(formatVersion, binaryDictionary.getFormatVersion());
+        assertEquals(FormatSpec.VERSION403, binaryDictionary.getFormatVersion());
         final int probability = 100;
         addUnigramWord(binaryDictionary, "word", probability);
         assertEquals(probability, binaryDictionary.getFrequency("word"));
@@ -140,31 +137,15 @@
         binaryDictionary.flush();
         assertTrue(dictFile.exists());
         assertTrue(binaryDictionary.isValidDictionary());
-        assertEquals(formatVersion, binaryDictionary.getFormatVersion());
+        assertEquals(FormatSpec.VERSION403, binaryDictionary.getFormatVersion());
         assertEquals(probability, binaryDictionary.getFrequency("word"));
         binaryDictionary.close();
-        dictFile.delete();
     }
 
     public void testAddTooLongWord() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddTooLongWord(formatVersion);
-        }
-    }
-
-    private void testAddTooLongWord(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
         final StringBuffer stringBuilder = new StringBuffer();
-        for (int i = 0; i < Constants.DICTIONARY_MAX_WORD_LENGTH; i++) {
+        for (int i = 0; i < BinaryDictionary.DICTIONARY_MAX_WORD_LENGTH; i++) {
             stringBuilder.append('a');
         }
         final String validLongWord = stringBuilder.toString();
@@ -175,9 +156,8 @@
         addUnigramWord(binaryDictionary, validLongWord, probability);
         addUnigramWord(binaryDictionary, invalidLongWord, probability);
         // Too long short cut.
-        binaryDictionary.addUnigramEntry("a", probability, invalidLongWord,
-                10 /* shortcutProbability */, false /* isBeginningOfSentence */,
-                false /* isNotAWord */, false /* isBlacklisted */,
+        binaryDictionary.addUnigramEntry("a", probability, false /* isBeginningOfSentence */,
+                false /* isNotAWord */, false /* isPossiblyOffensive */,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP);
         addUnigramWord(binaryDictionary, "abc", probability);
         final int updatedProbability = 200;
@@ -188,58 +168,49 @@
 
         assertEquals(probability, binaryDictionary.getFrequency("aaa"));
         assertEquals(updatedProbability, binaryDictionary.getFrequency(validLongWord));
-        assertEquals(BinaryDictionary.NOT_A_PROBABILITY,
-                binaryDictionary.getFrequency(invalidLongWord));
+        assertEquals(Dictionary.NOT_A_PROBABILITY, binaryDictionary.getFrequency(invalidLongWord));
         assertEquals(updatedProbability, binaryDictionary.getFrequency("abc"));
-        dictFile.delete();
     }
 
     private static void addUnigramWord(final BinaryDictionary binaryDictionary, final String word,
             final int probability) {
-        binaryDictionary.addUnigramEntry(word, probability, "" /* shortcutTarget */,
-                BinaryDictionary.NOT_A_PROBABILITY /* shortcutProbability */,
+        binaryDictionary.addUnigramEntry(word, probability,
                 false /* isBeginningOfSentence */, false /* isNotAWord */,
-                false /* isBlacklisted */, BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
+                false /* isPossiblyOffensive */,
+                BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
     }
 
     private static void addBigramWords(final BinaryDictionary binaryDictionary, final String word0,
             final String word1, final int probability) {
-        binaryDictionary.addNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1, probability,
+        binaryDictionary.addNgramEntry(new NgramContext(new WordInfo(word0)), word1, probability,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
     }
 
+    private static void addTrigramEntry(final BinaryDictionary binaryDictionary, final String word0,
+            final String word1, final String word2, final int probability) {
+        binaryDictionary.addNgramEntry(
+                new NgramContext(new WordInfo(word1), new WordInfo(word0)), word2,
+                probability, BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
+    }
+
     private static boolean isValidBigram(final BinaryDictionary binaryDictionary,
             final String word0, final String word1) {
-        return binaryDictionary.isValidNgram(new PrevWordsInfo(new WordInfo(word0)), word1);
-    }
-
-    private static void removeBigramEntry(final BinaryDictionary binaryDictionary,
-            final String word0, final String word1) {
-        binaryDictionary.removeNgramEntry(new PrevWordsInfo(new WordInfo(word0)), word1);
+        return binaryDictionary.isValidNgram(new NgramContext(new WordInfo(word0)), word1);
     }
 
     private static int getBigramProbability(final BinaryDictionary binaryDictionary,
             final String word0,  final String word1) {
-        return binaryDictionary.getNgramProbability(new PrevWordsInfo(new WordInfo(word0)), word1);
+        return binaryDictionary.getNgramProbability(new NgramContext(new WordInfo(word0)), word1);
+    }
+
+    private static int getTrigramProbability(final BinaryDictionary binaryDictionary,
+            final String word0, final String word1, final String word2) {
+        return binaryDictionary.getNgramProbability(
+                new NgramContext(new WordInfo(word1), new WordInfo(word0)), word2);
     }
 
     public void testAddUnigramWord() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddUnigramWord(formatVersion);
-        }
-    }
-
-    private void testAddUnigramWord(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
         final int probability = 100;
         addUnigramWord(binaryDictionary, "aaa", probability);
         // Reallocate and create.
@@ -263,30 +234,13 @@
         assertEquals(probability, binaryDictionary.getFrequency("aaaa"));
         assertEquals(probability, binaryDictionary.getFrequency("a"));
         assertEquals(updatedProbability, binaryDictionary.getFrequency("aaa"));
-
-        dictFile.delete();
     }
 
     public void testRandomlyAddUnigramWord() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testRandomlyAddUnigramWord(formatVersion);
-        }
-    }
-
-    private void testRandomlyAddUnigramWord(final int formatVersion) {
         final int wordCount = 1000;
         final int codePointSetSize = 50;
         final long seed = System.currentTimeMillis();
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
 
         final HashMap<String, Integer> probabilityMap = new HashMap<>();
         // Test a word that isn't contained within the dictionary.
@@ -302,25 +256,10 @@
         for (String word : probabilityMap.keySet()) {
             assertEquals(word, (int)probabilityMap.get(word), binaryDictionary.getFrequency(word));
         }
-        dictFile.delete();
     }
 
     public void testAddBigramWords() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddBigramWords(formatVersion);
-        }
-    }
-
-    private void testAddBigramWords(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
 
         final int unigramProbability = 100;
         final int bigramProbability = 150;
@@ -337,18 +276,14 @@
         assertTrue(isValidBigram(binaryDictionary, "aaa", "bcc"));
         assertTrue(isValidBigram(binaryDictionary, "abb", "aaa"));
         assertTrue(isValidBigram(binaryDictionary, "abb", "bcc"));
-        if (canCheckBigramProbability(formatVersion)) {
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
-        }
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
 
         addBigramWords(binaryDictionary, "aaa", "abb", updatedBigramProbability);
-        if (canCheckBigramProbability(formatVersion)) {
-            assertEquals(updatedBigramProbability,
-                    getBigramProbability(binaryDictionary, "aaa", "abb"));
-        }
+        assertEquals(updatedBigramProbability,
+                getBigramProbability(binaryDictionary, "aaa", "abb"));
 
         assertFalse(isValidBigram(binaryDictionary, "bcc", "aaa"));
         assertFalse(isValidBigram(binaryDictionary, "bcc", "bbc"));
@@ -368,43 +303,21 @@
         addUnigramWord(binaryDictionary, "abc", unigramProbability);
         addUnigramWord(binaryDictionary, "f", unigramProbability);
 
-        if (canCheckBigramProbability(formatVersion)) {
-            assertEquals(bigramProbability,
-                    getBigramProbability(binaryDictionary, "abcde", "fghij"));
-        }
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abcde", "fghij"));
         assertEquals(Dictionary.NOT_A_PROBABILITY,
                 getBigramProbability(binaryDictionary, "abcde", "fgh"));
         addBigramWords(binaryDictionary, "abcde", "fghij", updatedBigramProbability);
-        if (canCheckBigramProbability(formatVersion)) {
-            assertEquals(updatedBigramProbability,
-                    getBigramProbability(binaryDictionary, "abcde", "fghij"));
-        }
-
-        dictFile.delete();
+        assertEquals(updatedBigramProbability,
+                getBigramProbability(binaryDictionary, "abcde", "fghij"));
     }
 
     public void testRandomlyAddBigramWords() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testRandomlyAddBigramWords(formatVersion);
-        }
-    }
-
-    private void testRandomlyAddBigramWords(final int formatVersion) {
         final int wordCount = 100;
         final int bigramCount = 1000;
         final int codePointSetSize = 50;
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
 
         final ArrayList<String> words = new ArrayList<>();
         final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -439,83 +352,40 @@
             final int bigramProbability = bigramProbabilities.get(bigram);
             assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
                     isValidBigram(binaryDictionary, bigram.first, bigram.second));
-            if (canCheckBigramProbability(formatVersion)) {
-                assertEquals(bigramProbability,
-                        getBigramProbability(binaryDictionary, bigram.first, bigram.second));
-            }
-        }
-
-        dictFile.delete();
-    }
-
-    public void testRemoveBigramWords() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testRemoveBigramWords(formatVersion);
+            assertEquals(bigramProbability,
+                    getBigramProbability(binaryDictionary, bigram.first, bigram.second));
         }
     }
 
-    private void testRemoveBigramWords(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+    public void testAddTrigramWords() {
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
         final int unigramProbability = 100;
-        final int bigramProbability = 150;
+        final int trigramProbability = 150;
+        final int updatedTrigramProbability = 200;
         addUnigramWord(binaryDictionary, "aaa", unigramProbability);
         addUnigramWord(binaryDictionary, "abb", unigramProbability);
         addUnigramWord(binaryDictionary, "bcc", unigramProbability);
-        addBigramWords(binaryDictionary, "aaa", "abb", bigramProbability);
-        addBigramWords(binaryDictionary, "aaa", "bcc", bigramProbability);
-        addBigramWords(binaryDictionary, "abb", "aaa", bigramProbability);
-        addBigramWords(binaryDictionary, "abb", "bcc", bigramProbability);
 
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "abb"));
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "bcc"));
-        assertTrue(isValidBigram(binaryDictionary, "abb", "aaa"));
-        assertTrue(isValidBigram(binaryDictionary, "abb", "bcc"));
+        addBigramWords(binaryDictionary, "abb", "bcc", 10);
+        addBigramWords(binaryDictionary, "abb", "aaa", 10);
 
-        removeBigramEntry(binaryDictionary, "aaa", "abb");
+        addTrigramEntry(binaryDictionary, "aaa", "abb", "bcc", trigramProbability);
+        addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", trigramProbability);
+
+        assertEquals(trigramProbability,
+                getTrigramProbability(binaryDictionary, "aaa", "abb", "bcc"));
+        assertEquals(trigramProbability,
+                getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
         assertFalse(isValidBigram(binaryDictionary, "aaa", "abb"));
-        addBigramWords(binaryDictionary, "aaa", "abb", bigramProbability);
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "abb"));
 
-
-        removeBigramEntry(binaryDictionary, "aaa", "bcc");
-        assertFalse(isValidBigram(binaryDictionary, "aaa", "bcc"));
-        removeBigramEntry(binaryDictionary, "abb", "aaa");
-        assertFalse(isValidBigram(binaryDictionary, "abb", "aaa"));
-        removeBigramEntry(binaryDictionary, "abb", "bcc");
-        assertFalse(isValidBigram(binaryDictionary, "abb", "bcc"));
-
-        removeBigramEntry(binaryDictionary, "aaa", "abb");
-        // Test remove non-existing bigram operation.
-        removeBigramEntry(binaryDictionary, "aaa", "abb");
-        removeBigramEntry(binaryDictionary, "bcc", "aaa");
-
-        dictFile.delete();
+        addTrigramEntry(binaryDictionary, "bcc", "abb", "aaa", updatedTrigramProbability);
+        assertEquals(updatedTrigramProbability,
+                getTrigramProbability(binaryDictionary, "bcc", "abb", "aaa"));
     }
 
     public void testFlushDictionary() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testFlushDictionary(formatVersion);
-        }
-    }
-
-    private void testFlushDictionary(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+        BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
         final int probability = 100;
         addUnigramWord(binaryDictionary, "aaa", probability);
@@ -535,42 +405,21 @@
         binaryDictionary.flush();
         binaryDictionary.close();
 
-        binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+        binaryDictionary = getBinaryDictionary(dictFile);
         assertEquals(probability, binaryDictionary.getFrequency("aaa"));
         assertEquals(probability, binaryDictionary.getFrequency("abcd"));
         addUnigramWord(binaryDictionary, "bcde", probability);
         binaryDictionary.flush();
         binaryDictionary.close();
 
-        binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        binaryDictionary = getBinaryDictionary(dictFile);
         assertEquals(probability, binaryDictionary.getFrequency("bcde"));
         binaryDictionary.close();
-
-        dictFile.delete();
     }
 
     public void testFlushWithGCDictionary() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testFlushWithGCDictionary(formatVersion);
-        }
-    }
-
-    private void testFlushWithGCDictionary(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+        BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
         final int unigramProbability = 100;
         final int bigramProbability = 150;
         addUnigramWord(binaryDictionary, "aaa", unigramProbability);
@@ -583,51 +432,30 @@
         binaryDictionary.flushWithGC();
         binaryDictionary.close();
 
-        binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        binaryDictionary = getBinaryDictionary(dictFile);
         assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
         assertEquals(unigramProbability, binaryDictionary.getFrequency("abb"));
         assertEquals(unigramProbability, binaryDictionary.getFrequency("bcc"));
-        if (canCheckBigramProbability(formatVersion)) {
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
-        }
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "abb"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bcc"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "aaa"));
+        assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "abb", "bcc"));
         assertFalse(isValidBigram(binaryDictionary, "bcc", "aaa"));
         assertFalse(isValidBigram(binaryDictionary, "bcc", "bbc"));
         assertFalse(isValidBigram(binaryDictionary, "aaa", "aaa"));
         binaryDictionary.flushWithGC();
         binaryDictionary.close();
-
-        dictFile.delete();
     }
 
     public void testAddBigramWordsAndFlashWithGC() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddBigramWordsAndFlashWithGC(formatVersion);
-        }
-    }
-
-    // TODO: Evaluate performance of GC
-    private void testAddBigramWordsAndFlashWithGC(final int formatVersion) {
         final int wordCount = 100;
         final int bigramCount = 1000;
         final int codePointSetSize = 30;
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
 
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+        BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
         final ArrayList<String> words = new ArrayList<>();
         final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
@@ -660,52 +488,37 @@
 
         binaryDictionary.flushWithGC();
         binaryDictionary.close();
-        binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
+        binaryDictionary = getBinaryDictionary(dictFile);
 
         for (final Pair<String, String> bigram : bigramWords) {
             final int bigramProbability = bigramProbabilities.get(bigram);
             assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
                     isValidBigram(binaryDictionary, bigram.first, bigram.second));
-            if (canCheckBigramProbability(formatVersion)) {
-                assertEquals(bigramProbability,
-                        getBigramProbability(binaryDictionary, bigram.first, bigram.second));
-            }
+            assertEquals(bigramProbability,
+                    getBigramProbability(binaryDictionary, bigram.first, bigram.second));
         }
-
-        dictFile.delete();
     }
 
     public void testRandomOperationsAndFlashWithGC() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testRandomOperationsAndFlashWithGC(formatVersion);
-        }
-    }
+        final int maxUnigramCount = 5000;
+        final int maxBigramCount = 10000;
+        final HashMap<String, String> attributeMap = new HashMap<>();
+        attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY, String.valueOf(maxUnigramCount));
+        attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY, String.valueOf(maxBigramCount));
 
-    private void testRandomOperationsAndFlashWithGC(final int formatVersion) {
         final int flashWithGCIterationCount = 50;
         final int operationCountInEachIteration = 200;
         final int initialUnigramCount = 100;
         final float addUnigramProb = 0.5f;
         final float addBigramProb = 0.8f;
-        final float removeBigramProb = 0.2f;
         final int codePointSetSize = 30;
 
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
+        final File dictFile = createEmptyDictionaryWithAttributesAndGetFile(FormatSpec.VERSION403,
+                attributeMap);
+        BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
         final ArrayList<String> words = new ArrayList<>();
         final ArrayList<Pair<String, String>> bigramWords = new ArrayList<>();
         final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
@@ -722,9 +535,7 @@
         binaryDictionary.close();
 
         for (int gcCount = 0; gcCount < flashWithGCIterationCount; gcCount++) {
-            binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                    0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                    Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+            binaryDictionary = getBinaryDictionary(dictFile);
             for (int opCount = 0; opCount < operationCountInEachIteration; opCount++) {
                 // Add unigram.
                 if (random.nextFloat() < addUnigramProb) {
@@ -754,14 +565,6 @@
                     bigramProbabilities.put(bigram, bigramProbability);
                     addBigramWords(binaryDictionary, word0, word1, bigramProbability);
                 }
-                // Remove bigram.
-                if (random.nextFloat() < removeBigramProb && !bigramWords.isEmpty()) {
-                    final int bigramIndex = random.nextInt(bigramWords.size());
-                    final Pair<String, String> bigram = bigramWords.get(bigramIndex);
-                    bigramWords.remove(bigramIndex);
-                    bigramProbabilities.remove(bigram);
-                    removeBigramEntry(binaryDictionary, bigram.first, bigram.second);
-                }
             }
 
             // Test whether the all unigram operations are collectlly handled.
@@ -775,45 +578,29 @@
                 final Pair<String, String> bigram = bigramWords.get(i);
                 final int probability;
                 if (bigramProbabilities.containsKey(bigram)) {
-                    final int bigramProbability = bigramProbabilities.get(bigram);
-                    probability = bigramProbability;
+                    probability = bigramProbabilities.get(bigram);
                 } else {
                     probability = Dictionary.NOT_A_PROBABILITY;
                 }
 
-                if (canCheckBigramProbability(formatVersion)) {
-                    assertEquals(probability,
-                            getBigramProbability(binaryDictionary, bigram.first, bigram.second));
-                }
+                assertEquals(probability,
+                        getBigramProbability(binaryDictionary, bigram.first, bigram.second));
                 assertEquals(probability != Dictionary.NOT_A_PROBABILITY,
                         isValidBigram(binaryDictionary, bigram.first, bigram.second));
             }
             binaryDictionary.flushWithGC();
             binaryDictionary.close();
         }
-
-        dictFile.delete();
     }
 
     public void testAddManyUnigramsAndFlushWithGC() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddManyUnigramsAndFlushWithGC(formatVersion);
-        }
-    }
-
-    private void testAddManyUnigramsAndFlushWithGC(final int formatVersion) {
         final int flashWithGCIterationCount = 3;
         final int codePointSetSize = 50;
 
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
 
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
 
         final ArrayList<String> words = new ArrayList<>();
         final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
@@ -821,9 +608,7 @@
 
         BinaryDictionary binaryDictionary;
         for (int i = 0; i < flashWithGCIterationCount; i++) {
-            binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                    0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                    Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+            binaryDictionary = getBinaryDictionary(dictFile);
             while(!binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
                 final String word = CodePointUtils.generateWord(random, codePointSet);
                 words.add(word);
@@ -841,30 +626,23 @@
             binaryDictionary.flushWithGC();
             binaryDictionary.close();
         }
-
-        dictFile.delete();
     }
 
     public void testUnigramAndBigramCount() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testUnigramAndBigramCount(formatVersion);
-        }
-    }
+        final int maxUnigramCount = 5000;
+        final int maxBigramCount = 10000;
+        final HashMap<String, String> attributeMap = new HashMap<>();
+        attributeMap.put(DictionaryHeader.MAX_UNIGRAM_COUNT_KEY, String.valueOf(maxUnigramCount));
+        attributeMap.put(DictionaryHeader.MAX_BIGRAM_COUNT_KEY, String.valueOf(maxBigramCount));
 
-    private void testUnigramAndBigramCount(final int formatVersion) {
         final int flashWithGCIterationCount = 10;
         final int codePointSetSize = 50;
         final int unigramCountPerIteration = 1000;
         final int bigramCountPerIteration = 2000;
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
+        final File dictFile = createEmptyDictionaryWithAttributesAndGetFile(FormatSpec.VERSION403,
+                attributeMap);
 
         final ArrayList<String> words = new ArrayList<>();
         final HashSet<Pair<String, String>> bigrams = new HashSet<>();
@@ -872,9 +650,7 @@
 
         BinaryDictionary binaryDictionary;
         for (int i = 0; i < flashWithGCIterationCount; i++) {
-            binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                    0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                    Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+            binaryDictionary = getBinaryDictionary(dictFile);
             for (int j = 0; j < unigramCountPerIteration; j++) {
                 final String word = CodePointUtils.generateWord(random, codePointSet);
                 words.add(word);
@@ -892,108 +668,31 @@
                 addBigramWords(binaryDictionary, word0, word1, bigramProbability);
             }
             assertEquals(new HashSet<>(words).size(), Integer.parseInt(
-                    binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+                    binaryDictionary.getPropertyForGettingStats(
+                            BinaryDictionary.UNIGRAM_COUNT_QUERY)));
             assertEquals(new HashSet<>(bigrams).size(), Integer.parseInt(
-                    binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+                    binaryDictionary.getPropertyForGettingStats(
+                            BinaryDictionary.BIGRAM_COUNT_QUERY)));
             binaryDictionary.flushWithGC();
             assertEquals(new HashSet<>(words).size(), Integer.parseInt(
-                    binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
+                    binaryDictionary.getPropertyForGettingStats(
+                            BinaryDictionary.UNIGRAM_COUNT_QUERY)));
             assertEquals(new HashSet<>(bigrams).size(), Integer.parseInt(
-                    binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+                    binaryDictionary.getPropertyForGettingStats(
+                            BinaryDictionary.BIGRAM_COUNT_QUERY)));
             binaryDictionary.close();
         }
-
-        dictFile.delete();
-    }
-
-    public void testAddMultipleDictionaryEntries() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddMultipleDictionaryEntries(formatVersion);
-        }
-    }
-
-    private void testAddMultipleDictionaryEntries(final int formatVersion) {
-        final int codePointSetSize = 20;
-        final int lmParamCount = 1000;
-        final double bigramContinueRate = 0.9;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-        final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
-        final HashMap<Pair<String, String>, Integer> bigramProbabilities = new HashMap<>();
-
-        final LanguageModelParam[] languageModelParams = new LanguageModelParam[lmParamCount];
-        String prevWord = null;
-        for (int i = 0; i < languageModelParams.length; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            final int probability = random.nextInt(0xFF);
-            final int bigramProbability = probability + random.nextInt(0xFF - probability);
-            unigramProbabilities.put(word, probability);
-            if (prevWord == null) {
-                languageModelParams[i] = new LanguageModelParam(word, probability,
-                        BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-            } else {
-                languageModelParams[i] = new LanguageModelParam(prevWord, word, probability,
-                        bigramProbability, BinaryDictionary.NOT_A_VALID_TIMESTAMP);
-                bigramProbabilities.put(new Pair<>(prevWord, word),
-                        bigramProbability);
-            }
-            prevWord = (random.nextDouble() < bigramContinueRate) ? word : null;
-        }
-
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        binaryDictionary.addMultipleDictionaryEntries(languageModelParams);
-
-        for (Map.Entry<String, Integer> entry : unigramProbabilities.entrySet()) {
-            assertEquals((int)entry.getValue(), binaryDictionary.getFrequency(entry.getKey()));
-        }
-
-        for (Map.Entry<Pair<String, String>, Integer> entry : bigramProbabilities.entrySet()) {
-            final String word0 = entry.getKey().first;
-            final String word1 = entry.getKey().second;
-            final int bigramProbability = entry.getValue();
-            assertEquals(bigramProbability != Dictionary.NOT_A_PROBABILITY,
-                    isValidBigram(binaryDictionary, word0, word1));
-            if (canCheckBigramProbability(formatVersion)) {
-                assertEquals(bigramProbability,
-                        getBigramProbability(binaryDictionary, word0, word1));
-            }
-        }
     }
 
     public void testGetWordProperties() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testGetWordProperties(formatVersion);
-        }
-    }
-
-    private void testGetWordProperties(final int formatVersion) {
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
         final int UNIGRAM_COUNT = 1000;
         final int BIGRAM_COUNT = 1000;
         final int codePointSetSize = 20;
         final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final File dictFile = createEmptyDictionaryAndGetFile(FormatSpec.VERSION403);
+        final BinaryDictionary binaryDictionary = getBinaryDictionary(dictFile);
 
         final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
                 false /* isBeginningOfSentence */);
@@ -1008,11 +707,10 @@
             final String word = CodePointUtils.generateWord(random, codePointSet);
             final int unigramProbability = random.nextInt(0xFF);
             final boolean isNotAWord = random.nextBoolean();
-            final boolean isBlacklisted = random.nextBoolean();
+            final boolean isPossiblyOffensive = random.nextBoolean();
             // TODO: Add tests for historical info.
             binaryDictionary.addUnigramEntry(word, unigramProbability,
-                    null /* shortcutTarget */, BinaryDictionary.NOT_A_PROBABILITY,
-                    false /* isBeginningOfSentence */, isNotAWord, isBlacklisted,
+                    false /* isBeginningOfSentence */, isNotAWord, isPossiblyOffensive,
                     BinaryDictionary.NOT_A_VALID_TIMESTAMP);
             if (binaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) {
                 binaryDictionary.flushWithGC();
@@ -1024,11 +722,9 @@
             assertEquals(word, wordProperty.mWord);
             assertTrue(wordProperty.isValid());
             assertEquals(isNotAWord, wordProperty.mIsNotAWord);
-            assertEquals(isBlacklisted, wordProperty.mIsBlacklistEntry);
-            assertEquals(false, wordProperty.mHasBigrams);
-            assertEquals(false, wordProperty.mHasShortcuts);
+            assertEquals(isPossiblyOffensive, wordProperty.mIsPossiblyOffensive);
+            assertEquals(false, wordProperty.mHasNgrams);
             assertEquals(unigramProbability, wordProperty.mProbabilityInfo.mProbability);
-            assertTrue(wordProperty.mShortcutTargets.isEmpty());
         }
 
         for (int i = 0; i < BIGRAM_COUNT; i++) {
@@ -1062,41 +758,25 @@
             final HashSet<String> bigramWord1s = bigrams.get(word0);
             final WordProperty wordProperty = binaryDictionary.getWordProperty(word0,
                     false /* isBeginningOfSentence */);
-            assertEquals(bigramWord1s.size(), wordProperty.mBigrams.size());
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
+            assertEquals(bigramWord1s.size(), wordProperty.mNgrams.size());
+            // TODO: Support ngram.
+            for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+                final String word1 = bigramTarget.mWord;
                 assertTrue(bigramWord1s.contains(word1));
-                if (canCheckBigramProbability(formatVersion)) {
-                    final int bigramProbability = bigramProbabilities.get(new Pair<>(word0, word1));
-                    assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
-                }
+                final int bigramProbability = bigramProbabilities.get(new Pair<>(word0, word1));
+                assertEquals(bigramProbability, bigramTarget.getProbability());
             }
         }
     }
 
     public void testIterateAllWords() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testIterateAllWords(formatVersion);
-        }
-    }
-
-    private void testIterateAllWords(final int formatVersion) {
         final long seed = System.currentTimeMillis();
         final Random random = new Random(seed);
         final int UNIGRAM_COUNT = 1000;
         final int BIGRAM_COUNT = 1000;
         final int codePointSetSize = 20;
         final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
 
         final WordProperty invalidWordProperty = binaryDictionary.getWordProperty("dummyWord",
                 false /* isBeginningOfSentence */);
@@ -1155,15 +835,16 @@
                     wordProperty.mProbabilityInfo.mProbability);
             wordSet.remove(word0);
             final HashSet<String> bigramWord1s = bigrams.get(word0);
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
-                assertTrue(bigramWord1s.contains(word1));
-                final Pair<String, String> bigram = new Pair<>(word0, word1);
-                if (canCheckBigramProbability(formatVersion)) {
+            // TODO: Support ngram.
+            if (wordProperty.mHasNgrams) {
+                for (final WeightedString bigramTarget : wordProperty.getBigrams()) {
+                    final String word1 = bigramTarget.mWord;
+                    assertTrue(bigramWord1s.contains(word1));
+                    final Pair<String, String> bigram = new Pair<>(word0, word1);
                     final int bigramProbability = bigramProbabilitiesToCheckLater.get(bigram);
-                    assertEquals(bigramProbability, wordProperty.mBigrams.get(j).getProbability());
+                    assertEquals(bigramProbability, bigramTarget.getProbability());
+                    bigramSet.remove(bigram);
                 }
-                bigramSet.remove(bigram);
             }
             token = result.mNextToken;
         } while (token != 0);
@@ -1171,346 +852,33 @@
         assertTrue(bigramSet.isEmpty());
     }
 
-    public void testAddShortcuts() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddShortcuts(formatVersion);
-        }
-    }
-
-    private void testAddShortcuts(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        final int unigramProbability = 100;
-        final int shortcutProbability = 10;
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
-                shortcutProbability, false /* isBeginningOfSentence */,
-                false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
-        WordProperty wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
-        assertEquals(shortcutProbability, wordProperty.mShortcutTargets.get(0).getProbability());
-        final int updatedShortcutProbability = 2;
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "zzz",
-                updatedShortcutProbability, false /* isBeginningOfSentence */,
-                false /* isNotAWord */, false /* isBlacklisted */, 0 /* timestamp */);
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("zzz", wordProperty.mShortcutTargets.get(0).mWord);
-        assertEquals(updatedShortcutProbability,
-                wordProperty.mShortcutTargets.get(0).getProbability());
-        binaryDictionary.addUnigramEntry("aaa", unigramProbability, "yyy",
-                shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
-                false /* isBlacklisted */, 0 /* timestamp */);
-        final HashMap<String, Integer> shortcutTargets = new HashMap<>();
-        shortcutTargets.put("zzz", updatedShortcutProbability);
-        shortcutTargets.put("yyy", shortcutProbability);
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(2, wordProperty.mShortcutTargets.size());
-        for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-            assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
-            assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
-                    shortcutTarget.getProbability());
-            shortcutTargets.remove(shortcutTarget.mWord);
-        }
-        shortcutTargets.put("zzz", updatedShortcutProbability);
-        shortcutTargets.put("yyy", shortcutProbability);
-        binaryDictionary.flushWithGC();
-        wordProperty = binaryDictionary.getWordProperty("aaa",
-                false /* isBeginningOfSentence */);
-        assertEquals(2, wordProperty.mShortcutTargets.size());
-        for (WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-            assertTrue(shortcutTargets.containsKey(shortcutTarget.mWord));
-            assertEquals((int)shortcutTargets.get(shortcutTarget.mWord),
-                    shortcutTarget.getProbability());
-            shortcutTargets.remove(shortcutTarget.mWord);
-        }
-    }
-
-    public void testAddManyShortcuts() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testAddManyShortcuts(formatVersion);
-        }
-    }
-
-    private void testAddManyShortcuts(final int formatVersion) {
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-        final int UNIGRAM_COUNT = 1000;
-        final int SHORTCUT_COUNT = 10000;
-        final int codePointSetSize = 20;
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-
-        final ArrayList<String> words = new ArrayList<>();
-        final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
-        final HashMap<String, HashMap<String, Integer>> shortcutTargets = new HashMap<>();
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        for (int i = 0; i < UNIGRAM_COUNT; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            final int unigramProbability = random.nextInt(0xFF);
-            addUnigramWord(binaryDictionary, word, unigramProbability);
-            words.add(word);
-            unigramProbabilities.put(word, unigramProbability);
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-        }
-        for (int i = 0; i < SHORTCUT_COUNT; i++) {
-            final String shortcutTarget = CodePointUtils.generateWord(random, codePointSet);
-            final int shortcutProbability = random.nextInt(0xF);
-            final String word = words.get(random.nextInt(words.size()));
-            final int unigramProbability = unigramProbabilities.get(word);
-            binaryDictionary.addUnigramEntry(word, unigramProbability, shortcutTarget,
-                    shortcutProbability, false /* isBeginningOfSentence */, false /* isNotAWord */,
-                    false /* isBlacklisted */, 0 /* timestamp */);
-            if (shortcutTargets.containsKey(word)) {
-                final HashMap<String, Integer> shortcutTargetsOfWord = shortcutTargets.get(word);
-                shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
-            } else {
-                final HashMap<String, Integer> shortcutTargetsOfWord = new HashMap<>();
-                shortcutTargetsOfWord.put(shortcutTarget, shortcutProbability);
-                shortcutTargets.put(word, shortcutTargetsOfWord);
-            }
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-        }
-
-        for (final String word : words) {
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
-                    false /* isBeginningOfSentence */);
-            assertEquals((int)unigramProbabilities.get(word),
-                    wordProperty.mProbabilityInfo.mProbability);
-            if (!shortcutTargets.containsKey(word)) {
-                // The word does not have shortcut targets.
-                continue;
-            }
-            assertEquals(shortcutTargets.get(word).size(), wordProperty.mShortcutTargets.size());
-            for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                final String targetCodePonts = shortcutTarget.mWord;
-                assertEquals((int)shortcutTargets.get(word).get(targetCodePonts),
-                        shortcutTarget.getProbability());
-            }
-        }
-    }
-
-    public void testDictMigration() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
-        }
-    }
-
-    private void testDictMigration(final int fromFormatVersion, final int toFormatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        final int unigramProbability = 100;
-        addUnigramWord(binaryDictionary, "aaa", unigramProbability);
-        addUnigramWord(binaryDictionary, "bbb", unigramProbability);
-        final int bigramProbability = 150;
-        addBigramWords(binaryDictionary, "aaa", "bbb", bigramProbability);
-        final int shortcutProbability = 10;
-        binaryDictionary.addUnigramEntry("ccc", unigramProbability, "xxx", shortcutProbability,
-                false /* isBeginningOfSentence */, false /* isNotAWord */,
-                false /* isBlacklisted */, 0 /* timestamp */);
-        binaryDictionary.addUnigramEntry("ddd", unigramProbability, null /* shortcutTarget */,
-                Dictionary.NOT_A_PROBABILITY, false /* isBeginningOfSentence */,
-                true /* isNotAWord */, true /* isBlacklisted */, 0 /* timestamp */);
-        binaryDictionary.addNgramEntry(PrevWordsInfo.BEGINNING_OF_SENTENCE,
-                "aaa", bigramProbability, 0 /* timestamp */);
-        assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
-        assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
-        assertEquals(fromFormatVersion, binaryDictionary.getFormatVersion());
-        assertTrue(binaryDictionary.migrateTo(toFormatVersion));
-        assertTrue(binaryDictionary.isValidDictionary());
-        assertEquals(toFormatVersion, binaryDictionary.getFormatVersion());
-        assertEquals(unigramProbability, binaryDictionary.getFrequency("aaa"));
-        assertEquals(unigramProbability, binaryDictionary.getFrequency("bbb"));
-        if (canCheckBigramProbability(toFormatVersion)) {
-            assertEquals(bigramProbability, getBigramProbability(binaryDictionary, "aaa", "bbb"));
-            assertEquals(bigramProbability, binaryDictionary.getNgramProbability(
-                    PrevWordsInfo.BEGINNING_OF_SENTENCE, "aaa"));
-        }
-        assertTrue(isValidBigram(binaryDictionary, "aaa", "bbb"));
-        WordProperty wordProperty = binaryDictionary.getWordProperty("ccc",
-                false /* isBeginningOfSentence */);
-        assertEquals(1, wordProperty.mShortcutTargets.size());
-        assertEquals("xxx", wordProperty.mShortcutTargets.get(0).mWord);
-        wordProperty = binaryDictionary.getWordProperty("ddd",
-                false /* isBeginningOfSentence */);
-        assertTrue(wordProperty.mIsBlacklistEntry);
-        assertTrue(wordProperty.mIsNotAWord);
-    }
-
-    public void testLargeDictMigration() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testLargeDictMigration(FormatSpec.VERSION4_ONLY_FOR_TESTING, formatVersion);
-        }
-    }
-
-    private void testLargeDictMigration(final int fromFormatVersion, final int toFormatVersion) {
-        final int UNIGRAM_COUNT = 3000;
-        final int BIGRAM_COUNT = 3000;
-        final int codePointSetSize = 50;
-        final long seed = System.currentTimeMillis();
-        final Random random = new Random(seed);
-
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", fromFormatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-
-        final ArrayList<String> words = new ArrayList<>();
-        final ArrayList<Pair<String, String>> bigrams = new ArrayList<>();
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(codePointSetSize, random);
-        final HashMap<String, Integer> unigramProbabilities = new HashMap<>();
-        final HashMap<Pair<String, String>, Integer> bigramProbabilities = new HashMap<>();
-
-        for (int i = 0; i < UNIGRAM_COUNT; i++) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            final int unigramProbability = random.nextInt(0xFF);
-            addUnigramWord(binaryDictionary, word, unigramProbability);
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-            words.add(word);
-            unigramProbabilities.put(word, unigramProbability);
-        }
-
-        for (int i = 0; i < BIGRAM_COUNT; i++) {
-            final int word0Index = random.nextInt(words.size());
-            final int word1Index = random.nextInt(words.size());
-            if (word0Index == word1Index) {
-                continue;
-            }
-            final String word0 = words.get(word0Index);
-            final String word1 = words.get(word1Index);
-            final int unigramProbability = unigramProbabilities.get(word1);
-            final int bigramProbability =
-                    random.nextInt(0xFF - unigramProbability) + unigramProbability;
-            addBigramWords(binaryDictionary, word0, word1, bigramProbability);
-            if (binaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
-                binaryDictionary.flushWithGC();
-            }
-            final Pair<String, String> bigram = new Pair<>(word0, word1);
-            bigrams.add(bigram);
-            bigramProbabilities.put(bigram, bigramProbability);
-        }
-        assertTrue(binaryDictionary.migrateTo(toFormatVersion));
-
-        for (final String word : words) {
-            assertEquals((int)unigramProbabilities.get(word), binaryDictionary.getFrequency(word));
-        }
-        assertEquals(unigramProbabilities.size(), Integer.parseInt(
-                binaryDictionary.getPropertyForTest(BinaryDictionary.UNIGRAM_COUNT_QUERY)));
-
-        for (final Pair<String, String> bigram : bigrams) {
-            if (canCheckBigramProbability(toFormatVersion)) {
-                assertEquals((int)bigramProbabilities.get(bigram),
-                        getBigramProbability(binaryDictionary, bigram.first, bigram.second));
-            }
-            assertTrue(isValidBigram(binaryDictionary, bigram.first, bigram.second));
-        }
-        assertEquals(bigramProbabilities.size(), Integer.parseInt(
-                binaryDictionary.getPropertyForTest(BinaryDictionary.BIGRAM_COUNT_QUERY)));
+    public void testPossiblyOffensiveAttributeMaintained() {
+        final BinaryDictionary binaryDictionary =
+                getEmptyBinaryDictionary(FormatSpec.VERSION403);
+        binaryDictionary.addUnigramEntry("ddd", 100, false, true, true, 0);
+        WordProperty wordProperty = binaryDictionary.getWordProperty("ddd", false);
+        assertEquals(true, wordProperty.mIsPossiblyOffensive);
     }
 
     public void testBeginningOfSentence() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            if (supportsBeginningOfSentence(formatVersion)) {
-                testBeginningOfSentence(formatVersion);
-            }
-        }
-    }
-
-    private void testBeginningOfSentence(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
+        final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(FormatSpec.VERSION403);
         final int dummyProbability = 0;
-        final PrevWordsInfo prevWordsInfoBeginningOfSentence = PrevWordsInfo.BEGINNING_OF_SENTENCE;
+        final NgramContext beginningOfSentenceContext = NgramContext.BEGINNING_OF_SENTENCE;
         final int bigramProbability = 200;
         addUnigramWord(binaryDictionary, "aaa", dummyProbability);
-        binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "aaa", bigramProbability,
+        binaryDictionary.addNgramEntry(beginningOfSentenceContext, "aaa", bigramProbability,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
         assertEquals(bigramProbability,
-                binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "aaa"));
-        binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "aaa", bigramProbability,
+                binaryDictionary.getNgramProbability(beginningOfSentenceContext, "aaa"));
+        binaryDictionary.addNgramEntry(beginningOfSentenceContext, "aaa", bigramProbability,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
         addUnigramWord(binaryDictionary, "bbb", dummyProbability);
-        binaryDictionary.addNgramEntry(prevWordsInfoBeginningOfSentence, "bbb", bigramProbability,
+        binaryDictionary.addNgramEntry(beginningOfSentenceContext, "bbb", bigramProbability,
                 BinaryDictionary.NOT_A_VALID_TIMESTAMP /* timestamp */);
         binaryDictionary.flushWithGC();
         assertEquals(bigramProbability,
-                binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "aaa"));
+                binaryDictionary.getNgramProbability(beginningOfSentenceContext, "aaa"));
         assertEquals(bigramProbability,
-                binaryDictionary.getNgramProbability(prevWordsInfoBeginningOfSentence, "bbb"));
-    }
-
-    public void testGetMaxFrequencyOfExactMatches() {
-        for (final int formatVersion : DICT_FORMAT_VERSIONS) {
-            testGetMaxFrequencyOfExactMatches(formatVersion);
-        }
-    }
-
-    private void testGetMaxFrequencyOfExactMatches(final int formatVersion) {
-        File dictFile = null;
-        try {
-            dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, dictFile.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        addUnigramWord(binaryDictionary, "abc", 10);
-        addUnigramWord(binaryDictionary, "aBc", 15);
-        assertEquals(15, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
-        addUnigramWord(binaryDictionary, "ab'c", 20);
-        assertEquals(20, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
-        addUnigramWord(binaryDictionary, "a-b-c", 25);
-        assertEquals(25, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
-        addUnigramWord(binaryDictionary, "ab-'-'-'-c", 30);
-        assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
-        addUnigramWord(binaryDictionary, "ab c", 255);
-        assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
+                binaryDictionary.getNgramProbability(beginningOfSentenceContext, "bbb"));
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 6e894de..afb94ef 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -20,6 +20,8 @@
 import android.text.style.SuggestionSpan;
 import android.text.style.UnderlineSpan;
 
+import com.android.inputmethod.latin.common.Constants;
+
 @LargeTest
 public class BlueUnderlineTests extends InputTestsBase {
 
@@ -28,7 +30,7 @@
         final int EXPECTED_SPAN_START = 0;
         final int EXPECTED_SPAN_END = 4;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertEquals("show blue underline, span start", EXPECTED_SPAN_START, span.mStart);
@@ -37,12 +39,12 @@
     }
 
     public void testBlueUnderlineDisappears() {
-        final String STRING_1_TO_TYPE = "tgis";
-        final String STRING_2_TO_TYPE = "q";
+        final String STRING_1_TO_TYPE = "tqis";
+        final String STRING_2_TO_TYPE = "g";
         final int EXPECTED_SPAN_START = 0;
         final int EXPECTED_SPAN_END = 5;
         type(STRING_1_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(STRING_2_TO_TYPE);
         // We haven't have time to look into the dictionary yet, so the line should still be
@@ -51,7 +53,7 @@
         assertEquals("extend blue underline, span start", EXPECTED_SPAN_START, spanBefore.mStart);
         assertEquals("extend blue underline, span end", EXPECTED_SPAN_END, spanBefore.mEnd);
         assertTrue("extend blue underline, span color", spanBefore.isAutoCorrectionIndicator());
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         // Now we have been able to re-evaluate the word, there shouldn't be an auto-correction span
         final SpanGetter spanAfter = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
@@ -61,22 +63,21 @@
     public void testBlueUnderlineOnBackspace() {
         final String STRING_TO_TYPE = "tgis";
         final int typedLength = STRING_TO_TYPE.length();
-        final int EXPECTED_SUGGESTION_SPAN_START = -1;
         final int EXPECTED_UNDERLINE_SPAN_START = 0;
-        final int EXPECTED_UNDERLINE_SPAN_END = 4;
+        final int EXPECTED_UNDERLINE_SPAN_END = 3;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_SPACE);
         // typedLength + 1 because we also typed a space
         mLatinIME.onUpdateSelection(0, 0, typedLength + 1, typedLength + 1, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter suggestionSpan = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertFalse("show no blue underline after backspace, span should not be the auto-"
@@ -93,7 +94,7 @@
         final int typedLength = STRING_TO_TYPE.length();
         final int NEW_CURSOR_POSITION = 0;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         // Simulate the onUpdateSelection() event
         mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
         runMessages();
@@ -103,7 +104,7 @@
         mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
         mLatinIME.onUpdateSelection(typedLength, typedLength,
                 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertFalse("blue underline removed when cursor is moved",
@@ -113,7 +114,7 @@
     public void testComposingStopsOnSpace() {
         final String STRING_TO_TYPE = "this ";
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         // Simulate the onUpdateSelection() event
         mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
         runMessages();
diff --git a/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java b/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java
new file mode 100644
index 0000000..f90a18b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsContentObserverTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.ContactsContract.Contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for {@link ContactsContentObserver}.
+ */
+@SmallTest
+public class ContactsContentObserverTest {
+    private static final int UPDATED_CONTACT_COUNT = 10;
+    private static final int STALE_CONTACT_COUNT = 8;
+    private static final ArrayList<String> STALE_NAMES_LIST = new ArrayList<>();
+    private static final ArrayList<String> UPDATED_NAMES_LIST = new ArrayList<>();
+
+    static {
+        STALE_NAMES_LIST.add("Larry Page");
+        STALE_NAMES_LIST.add("Roger Federer");
+        UPDATED_NAMES_LIST.add("Larry Page");
+        UPDATED_NAMES_LIST.add("Roger Federer");
+        UPDATED_NAMES_LIST.add("Barak Obama");
+    }
+
+    @Mock private ContactsManager mMockManager;
+    @Mock private Context mContext;
+
+    private ContactsContentObserver mObserver;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mObserver = new ContactsContentObserver(mMockManager, mContext);
+    }
+
+    @After
+    public void tearDown() {
+        validateMockitoUsage();
+    }
+
+    @Test
+    public void testHaveContentsChanged_NoChange() {
+        when(mMockManager.getContactCount()).thenReturn(STALE_CONTACT_COUNT);
+        when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+        when(mMockManager.getValidNames(eq(Contacts.CONTENT_URI))).thenReturn(STALE_NAMES_LIST);
+        when(mMockManager.getHashCodeAtLastRebuild()).thenReturn(STALE_NAMES_LIST.hashCode());
+        assertFalse(mObserver.haveContentsChanged());
+    }
+    @Test
+    public void testHaveContentsChanged_UpdatedCount() {
+        when(mMockManager.getContactCount()).thenReturn(UPDATED_CONTACT_COUNT);
+        when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+        assertTrue(mObserver.haveContentsChanged());
+    }
+
+    @Test
+    public void testHaveContentsChanged_HashUpdate() {
+        when(mMockManager.getContactCount()).thenReturn(STALE_CONTACT_COUNT);
+        when(mMockManager.getContactCountAtLastRebuild()).thenReturn(STALE_CONTACT_COUNT);
+        when(mMockManager.getValidNames(eq(Contacts.CONTENT_URI))).thenReturn(UPDATED_NAMES_LIST);
+        when(mMockManager.getHashCodeAtLastRebuild()).thenReturn(STALE_NAMES_LIST.hashCode());
+        assertTrue(mObserver.haveContentsChanged());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java b/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java
new file mode 100644
index 0000000..9b49f1a
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsDictionaryUtilsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Locale;
+
+/**
+ * Tests for {@link ContactsDictionaryUtils}
+ */
+@SmallTest
+public class ContactsDictionaryUtilsTest {
+
+    @Test
+    public void testGetWordEndPosition() {
+        final String testString1 = "Larry Page";
+        assertEquals(5, ContactsDictionaryUtils.getWordEndPosition(
+                testString1, testString1.length(), 0 /* startIndex */));
+
+        assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+                testString1, testString1.length(), 6 /* startIndex */));
+
+        final String testString2 = "Larry-Page";
+        assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+                testString2, testString1.length(), 0 /* startIndex */));
+
+        final String testString3 = "Larry'Page";
+        assertEquals(10, ContactsDictionaryUtils.getWordEndPosition(
+                testString3, testString1.length(), 0 /* startIndex */));
+    }
+
+    @Test
+    public void testUseFirstLastBigramsForLocale() {
+        assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.ENGLISH));
+        assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.US));
+        assertTrue(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.UK));
+        assertFalse(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.CHINA));
+        assertFalse(ContactsDictionaryUtils.useFirstLastBigramsForLocale(Locale.GERMAN));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java b/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java
new file mode 100644
index 0000000..6326b3b
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/ContactsManagerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.test.AndroidTestCase;
+import android.test.RenamingDelegatingContext;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Tests for {@link ContactsManager}
+ */
+@SmallTest
+public class ContactsManagerTest extends AndroidTestCase {
+
+    private ContactsManager mManager;
+    private FakeContactsContentProvider mFakeContactsContentProvider;
+    private MatrixCursor mMatrixCursor;
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        // Fake content provider
+        mFakeContactsContentProvider = new FakeContactsContentProvider();
+        mMatrixCursor = new MatrixCursor(ContactsDictionaryConstants.PROJECTION);
+        // Add the fake content provider to fake content resolver.
+        final MockContentResolver contentResolver = new MockContentResolver();
+        contentResolver.addProvider(ContactsContract.AUTHORITY, mFakeContactsContentProvider);
+        // Add the fake content resolver to a fake context.
+        final ContextWithMockContentResolver context = new ContextWithMockContentResolver(mContext);
+        context.setContentResolver(contentResolver);
+
+        mManager = new ContactsManager(context);
+    }
+
+    @Test
+    public void testGetValidNames() {
+        final String contactName1 = "firstname lastname";
+        final String contactName2 = "larry";
+        mMatrixCursor.addRow(new Object[] { 1, contactName1 });
+        mMatrixCursor.addRow(new Object[] { 2, null /* null name */ });
+        mMatrixCursor.addRow(new Object[] { 3, contactName2 });
+        mMatrixCursor.addRow(new Object[] { 4, "floopy@example.com" /* invalid name */ });
+        mFakeContactsContentProvider.addQueryResult(Contacts.CONTENT_URI, mMatrixCursor);
+
+        final ArrayList<String> validNames = mManager.getValidNames(Contacts.CONTENT_URI);
+        assertEquals(2, validNames.size());
+        assertEquals(contactName1, validNames.get(0));
+        assertEquals(contactName2, validNames.get(1));
+    }
+
+    @Test
+    public void testGetCount() {
+        mMatrixCursor.addRow(new Object[] { 1, "firstname" });
+        mMatrixCursor.addRow(new Object[] { 2, null /* null name */ });
+        mMatrixCursor.addRow(new Object[] { 3, "larry" });
+        mMatrixCursor.addRow(new Object[] { 4, "floopy@example.com" /* invalid name */ });
+        mFakeContactsContentProvider.addQueryResult(Contacts.CONTENT_URI, mMatrixCursor);
+
+        assertEquals(4, mManager.getContactCount());
+    }
+
+
+    static class ContextWithMockContentResolver extends RenamingDelegatingContext {
+        private ContentResolver contentResolver;
+
+        public void setContentResolver(final ContentResolver contentResolver) {
+            this.contentResolver = contentResolver;
+        }
+
+        public ContextWithMockContentResolver(final Context targetContext) {
+            super(targetContext, "test");
+        }
+
+        @Override
+        public ContentResolver getContentResolver() {
+            return contentResolver;
+        }
+    }
+
+    static class FakeContactsContentProvider extends MockContentProvider {
+        private final HashMap<String, MatrixCursor> mQueryCursorMapForTestExpectations =
+                new HashMap<>();
+
+        @Override
+        public Cursor query(final Uri uri, final String[] projection, final String selection,
+                final String[] selectionArgs, final String sortOrder) {
+            return mQueryCursorMapForTestExpectations.get(uri.toString());
+        }
+
+        public void reset() {
+            mQueryCursorMapForTestExpectations.clear();
+        }
+
+        public void addQueryResult(final Uri uri, final MatrixCursor cursor) {
+            mQueryCursorMapForTestExpectations.put(uri.toString(), cursor);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
new file mode 100644
index 0000000..6b0bbc2
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCacheTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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;
+
+import java.util.Locale;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+@LargeTest
+public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
+    public void testGetFacilitator() {
+        final DictionaryFacilitatorLruCache cache =
+                new DictionaryFacilitatorLruCache(getContext(), "");
+
+        final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
+        assertNotNull(dictionaryFacilitatorEnUs);
+        assertTrue(dictionaryFacilitatorEnUs.isForLocale(Locale.US));
+
+        final DictionaryFacilitator dictionaryFacilitatorFr = cache.get(Locale.FRENCH);
+        assertNotNull(dictionaryFacilitatorEnUs);
+        assertTrue(dictionaryFacilitatorFr.isForLocale(Locale.FRENCH));
+
+        final DictionaryFacilitator dictionaryFacilitatorDe = cache.get(Locale.GERMANY);
+        assertNotNull(dictionaryFacilitatorDe);
+        assertTrue(dictionaryFacilitatorDe.isForLocale(Locale.GERMANY));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
deleted file mode 100644
index e6fb282..0000000
--- a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-import android.content.Context;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
-
-/**
- * Unit test for DistracterFilter
- */
-@LargeTest
-public class DistracterFilterTest extends AndroidTestCase {
-    private DistracterFilterCheckingExactMatchesAndSuggestions mDistracterFilter;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        final Context context = getContext();
-        mDistracterFilter = new DistracterFilterCheckingExactMatchesAndSuggestions(context);
-        RichInputMethodManager.init(context);
-        final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
-        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
-        subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.US.toString(), "qwerty"));
-        subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.FRENCH.toString(), "azerty"));
-        subtypes.add(richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.GERMAN.toString(), "qwertz"));
-        mDistracterFilter.updateEnabledSubtypes(subtypes);
-    }
-
-    public void testIsDistractorToWordsInDictionaries() {
-        final PrevWordsInfo EMPTY_PREV_WORDS_INFO = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-
-        final Locale localeEnUs = new Locale("en", "US");
-        String typedWord;
-
-        typedWord = "Bill";
-        // For this test case, we consider "Bill" is a distracter to "bill".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "nOt";
-        // For this test case, we consider "nOt" is a distracter to "not".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "youre";
-        // For this test case, we consider "youre" is a distracter to "you're".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "Banana";
-        // For this test case, we consider "Banana" is a distracter to "banana".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "orange";
-        // For this test case, we consider "orange" is not a distracter to any word in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "Orange";
-        // For this test case, we consider "Orange" is a distracter to "orange".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "café";
-        // For this test case, we consider "café" is a distracter to "cafe".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "cafe";
-        // For this test case, we consider "cafe" is not a distracter to any word in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "I'll";
-        // For this test case, we consider "I'll" is not a distracter to any word in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "ill";
-        // For this test case, we consider "ill" is a distracter to "I'll"
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "asdfd";
-        // For this test case, we consider "asdfd" is not a distracter to any word in dictionaries.
-        assertFalse(
-                mDistracterFilter.isDistracterToWordsInDictionaries(
-                        EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "thank";
-        // For this test case, we consider "thank" is not a distracter to any other word
-        // in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "thabk";
-        // For this test case, we consider "thabk" is a distracter to "thank"
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "thanks";
-        // For this test case, we consider "thanks" is not a distracter to any other word
-        // in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "thabks";
-        // For this test case, we consider "thabks" is a distracter to "thanks"
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "think";
-        // For this test case, we consider "think" is not a distracter to any other word
-        // in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "thibk";
-        // For this test case, we consider "thibk" is a distracter to "think"
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        typedWord = "tgis";
-        // For this test case, we consider "tgis" is a distracter to "this"
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs));
-
-        final Locale localeDeDe = new Locale("de");
-
-        typedWord = "fUEr";
-        // For this test case, we consider "fUEr" is a distracter to "für".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
-        typedWord = "fuer";
-        // For this test case, we consider "fuer" is a distracter to "für".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
-        typedWord = "fur";
-        // For this test case, we consider "fur" is a distracter to "für".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeDeDe));
-
-        final Locale localeFrFr = new Locale("fr");
-
-        typedWord = "a";
-        // For this test case, we consider "a" is a distracter to "à".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
-        typedWord = "à";
-        // For this test case, we consider "à" is not a distracter to any word in dictionaries.
-        assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
-        typedWord = "etre";
-        // For this test case, we consider "etre" is a distracter to "être".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
-        typedWord = "États-unis";
-        // For this test case, we consider "États-unis" is a distracter to "États-Unis".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-
-        typedWord = "ÉtatsUnis";
-        // For this test case, we consider "ÉtatsUnis" is a distracter to "États-Unis".
-        assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries(
-                EMPTY_PREV_WORDS_INFO, typedWord, localeFrFr));
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java b/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
deleted file mode 100644
index 09309bc..0000000
--- a/tests/src/com/android/inputmethod/latin/FusionDictionaryTests.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.ProbabilityInfo;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-
-import java.util.HashMap;
-
-/**
- * Unit test for FusionDictionary
- */
-@SmallTest
-public class FusionDictionaryTests extends AndroidTestCase {
-    public void testFindWordInTree() {
-        FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                new DictionaryOptions(new HashMap<String,String>()));
-
-        dict.add("abc", new ProbabilityInfo(10), null, false /* isNotAWord */);
-        assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
-        assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
-
-        dict.add("aa", new ProbabilityInfo(10), null, false /* isNotAWord */);
-        assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
-        assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aa"));
-
-        dict.add("babcd", new ProbabilityInfo(10), null, false /* isNotAWord */);
-        dict.add("bacde", new ProbabilityInfo(10), null, false /* isNotAWord */);
-        assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "ba"));
-        assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "babcd"));
-        assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "bacde"));
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index 59b858d..02cd21c 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -16,15 +16,33 @@
 
 package com.android.inputmethod.latin;
 
+import static android.test.MoreAsserts.assertNotEqual;
+
 import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.view.inputmethod.BaseInputConnection;
 
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.settings.Settings;
 
 @LargeTest
 public class InputLogicTests extends InputTestsBase {
 
+    private boolean mNextWordPrediction;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mNextWordPrediction = getBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, true);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mNextWordPrediction, true);
+        super.tearDown();
+    }
+
     public void testTypeWord() {
         final String WORD_TO_TYPE = "abcd";
         type(WORD_TO_TYPE);
@@ -36,7 +54,7 @@
         final String EXPECTED_RESULT = "thi";
         type(WORD_TO_TYPE);
         pickSuggestionManually(WORD_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
         type(Constants.CODE_DELETE);
         assertEquals("press suggestion then backspace", EXPECTED_RESULT,
                 mEditText.getText().toString());
@@ -49,7 +67,7 @@
         type(WORD_TO_TYPE);
         // Choose the auto-correction. For "tgis", the auto-correction should be "this".
         pickSuggestionManually(WORD_TO_PICK);
-        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
         assertEquals("pick typed word over auto-correction then backspace", WORD_TO_PICK,
                 mEditText.getText().toString());
         type(Constants.CODE_DELETE);
@@ -63,7 +81,7 @@
         type(WORD_TO_TYPE);
         // Choose the typed word.
         pickSuggestionManually(WORD_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
         assertEquals("pick typed word over auto-correction then backspace", WORD_TO_TYPE,
                 mEditText.getText().toString());
         type(Constants.CODE_DELETE);
@@ -78,7 +96,7 @@
         type(WORD_TO_TYPE);
         // Choose the second suggestion, which should be "thus" when "tgis" is typed.
         pickSuggestionManually(WORD_TO_PICK);
-        mLatinIME.onUpdateSelection(0, 0, WORD_TO_TYPE.length(), WORD_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(WORD_TO_TYPE.length());
         assertEquals("pick different suggestion then backspace", WORD_TO_PICK,
                 mEditText.getText().toString());
         type(Constants.CODE_DELETE);
@@ -93,7 +111,8 @@
         final int SELECTION_END = 19;
         final String EXPECTED_RESULT = "some text  some text";
         type(STRING_TO_TYPE);
-        // There is no IMF to call onUpdateSelection for us so we must do it by hand.
+        // Don't use the sendUpdateForCursorMove* family of methods here because they
+        // don't handle selections.
         // Send once to simulate the cursor actually responding to the move caused by typing.
         // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor
         // move with a move triggered by LatinIME inputting stuff.
@@ -113,7 +132,8 @@
         final int SELECTION_END = 19;
         final String EXPECTED_RESULT = "some text some text";
         type(STRING_TO_TYPE);
-        // There is no IMF to call onUpdateSelection for us so we must do it by hand.
+        // Don't use the sendUpdateForCursorMove* family of methods here because they
+        // don't handle selections.
         // Send once to simulate the cursor actually responding to the move caused by typing.
         // This is necessary because LatinIME is bookkeeping to avoid confusing a real cursor
         // move with a move triggered by LatinIME inputting stuff.
@@ -152,49 +172,90 @@
         final String STRING_TO_TYPE = "tgis.";
         final String EXPECTED_RESULT = "tgis.";
         type(STRING_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
         type(Constants.CODE_DELETE);
         assertEquals("auto-correct with period then revert", EXPECTED_RESULT,
                 mEditText.getText().toString());
     }
 
     public void testAutoCorrectWithSpaceThenRevert() {
+        // Backspacing to cancel the "tgis"->"this" autocorrection should result in
+        // a "phantom space": if the user presses space immediately after,
+        // only one space will be inserted in total.
         final String STRING_TO_TYPE = "tgis ";
-        final String EXPECTED_RESULT = "tgis ";
+        final String EXPECTED_RESULT = "tgis";
         type(STRING_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
         type(Constants.CODE_DELETE);
         assertEquals("auto-correct with space then revert", EXPECTED_RESULT,
                 mEditText.getText().toString());
     }
 
+    public void testAutoCorrectWithSpaceThenRevertThenTypeMore() {
+        final String STRING_TO_TYPE_FIRST = "tgis ";
+        final String STRING_TO_TYPE_SECOND = "a";
+        final String EXPECTED_RESULT = "tgis a";
+        type(STRING_TO_TYPE_FIRST);
+        sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length());
+        type(Constants.CODE_DELETE);
+
+        type(STRING_TO_TYPE_SECOND);
+        sendUpdateForCursorMoveTo(STRING_TO_TYPE_FIRST.length() - 1
+                + STRING_TO_TYPE_SECOND.length());
+        assertEquals("auto-correct with space then revert then type more", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
     public void testAutoCorrectToSelfDoesNotRevert() {
         final String STRING_TO_TYPE = "this ";
         final String EXPECTED_RESULT = "this";
         type(STRING_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
+        sendUpdateForCursorMoveTo(STRING_TO_TYPE.length());
         type(Constants.CODE_DELETE);
         assertEquals("auto-correct with space does not revert", EXPECTED_RESULT,
                 mEditText.getText().toString());
     }
 
     public void testDoubleSpace() {
-        // Set default pref just in case
-        setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
         // U+1F607 is an emoji
         final String[] STRINGS_TO_TYPE =
                 new String[] { "this   ", "a+  ", "\u1F607  ", "..  ", ")  ", "(  ", "%  " };
         final String[] EXPECTED_RESULTS =
                 new String[] { "this.  ", "a+. ", "\u1F607. ", "..  ", "). ", "(  ", "%. " };
-        for (int i = 0; i < STRINGS_TO_TYPE.length; ++i) {
+        verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS);
+    }
+
+    public void testDoubleSpaceHindi() {
+        changeLanguage("hi");
+        // U+1F607 is an emoji
+        final String[] STRINGS_TO_TYPE =
+                new String[] { "this   ", "a+  ", "\u1F607  ", "||  ", ")  ", "(  ", "%  " };
+        final String[] EXPECTED_RESULTS =
+                new String[] { "this|  ", "a+| ", "\u1F607| ", "||  ", ")| ", "(  ", "%| " };
+        verifyDoubleSpace(STRINGS_TO_TYPE, EXPECTED_RESULTS);
+    }
+
+    private void verifyDoubleSpace(String[] stringsToType, String[] expectedResults) {
+        // Set default pref just in case
+        setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
+        for (int i = 0; i < stringsToType.length; ++i) {
             mEditText.setText("");
-            type(STRINGS_TO_TYPE[i]);
-            assertEquals("double space processing", EXPECTED_RESULTS[i],
+            type(stringsToType[i]);
+            assertEquals("double space processing", expectedResults[i],
                     mEditText.getText().toString());
         }
     }
 
-    public void testCancelDoubleSpace() {
+    public void testCancelDoubleSpaceEnglish() {
+        final String STRING_TO_TYPE = "this  ";
+        final String EXPECTED_RESULT = "this ";
+        type(STRING_TO_TYPE);
+        type(Constants.CODE_DELETE);
+        assertEquals("double space make a period", EXPECTED_RESULT, mEditText.getText().toString());
+    }
+
+    public void testCancelDoubleSpaceHindi() {
+        changeLanguage("hi");
         final String STRING_TO_TYPE = "this  ";
         final String EXPECTED_RESULT = "this ";
         type(STRING_TO_TYPE);
@@ -243,9 +304,9 @@
     public void testDoubleSpacePeriod() {
         // Reset settings to default, else these tests will go flaky.
         setBooleanPreference(Settings.PREF_SHOW_SUGGESTIONS, true, true);
-        setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD, "1", "1");
+        setBooleanPreference(Settings.PREF_AUTO_CORRECTION, true, true);
         setBooleanPreference(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true, true);
-        testDoubleSpacePeriodWithSettings(true /* expectsPeriod */);
+        testDoubleSpacePeriodWithSettings(true);
         // "Suggestion visibility" to off
         testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false);
         // "Suggestion visibility" to on
@@ -255,18 +316,16 @@
         testDoubleSpacePeriodWithSettings(false, Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false);
 
         // "Auto-correction" to "off"
-        testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0");
-        // "Auto-correction" to "modest"
-        testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "1");
-        // "Auto-correction" to "very aggressive"
-        testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION_THRESHOLD, "3");
+        testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, false);
+        // "Auto-correction" to "on"
+        testDoubleSpacePeriodWithSettings(true, Settings.PREF_AUTO_CORRECTION, true);
 
         // "Suggestion visibility" to "always hide" and "Auto-correction" to "off"
         testDoubleSpacePeriodWithSettings(true, Settings.PREF_SHOW_SUGGESTIONS, false,
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0");
+                Settings.PREF_AUTO_CORRECTION, false);
         // "Suggestion visibility" to "always hide" and "Auto-correction" to "off"
         testDoubleSpacePeriodWithSettings(false, Settings.PREF_SHOW_SUGGESTIONS, false,
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD, "0",
+                Settings.PREF_AUTO_CORRECTION, false,
                 Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, false);
     }
 
@@ -276,10 +335,9 @@
         final String EXPECTED_RESULT = "this ";
         final int NEW_CURSOR_POSITION = 0;
         type(STRING_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+        sendUpdateForCursorMoveTo(typedLength);
         mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
-        mLatinIME.onUpdateSelection(typedLength, typedLength,
-                NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
+        sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
         type(Constants.CODE_DELETE);
         assertEquals("auto correct then move cursor to start of line then backspace",
                 EXPECTED_RESULT, mEditText.getText().toString());
@@ -291,10 +349,9 @@
         final String EXPECTED_RESULT = "andthis ";
         final int NEW_CURSOR_POSITION = STRING_TO_TYPE.indexOf('t');
         type(STRING_TO_TYPE);
-        mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+        sendUpdateForCursorMoveTo(typedLength);
         mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
-        mLatinIME.onUpdateSelection(typedLength, typedLength,
-                NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
+        sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
         type(Constants.CODE_DELETE);
         assertEquals("auto correct then move cursor then backspace",
                 EXPECTED_RESULT, mEditText.getText().toString());
@@ -329,8 +386,8 @@
         assertEquals("manual pick then separator", EXPECTED_RESULT, mEditText.getText().toString());
     }
 
-    // This test matches the one in InputLogicTestsNonEnglish. In some non-English languages,
-    // ! and ? are clustering punctuation signs.
+    // This test matches testClusteringPunctuationForFrench.
+    // In some non-English languages, ! and ? are clustering punctuation signs.
     public void testClusteringPunctuation() {
         final String WORD1_TO_TYPE = "test";
         final String WORD2_TO_TYPE = "!!?!:!";
@@ -394,7 +451,7 @@
                 BaseInputConnection.getComposingSpanStart(mEditText.getText()));
         assertEquals("resume suggestion on backspace", -1,
                 BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
-        mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
+        sendUpdateForCursorMoveTo(typedLength);
         type(Constants.CODE_DELETE);
         assertEquals("resume suggestion on backspace", 4,
                 BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -429,44 +486,25 @@
         type("  ");
         helperTestComposing("a'", true);
     }
+
     // TODO: Add some tests for non-BMP characters
 
     public void testAutoCorrectByUserHistory() {
-        final String WORD_TO_BE_CORRECTED = "qpmx";
-        final String NOT_CORRECTED_RESULT = "qpmx ";
-        final String DESIRED_WORD = "qpmz";
-        final String CORRECTED_RESULT = "qpmz ";
-        final int typeCountNotToAutocorrect = 1;
-        final int typeCountToAutoCorrect = 16;
-        int startIndex = 0;
-        int endIndex = 0;
+        type("qpmz");
+        type(Constants.CODE_SPACE);
 
-        for (int i = 0; i < typeCountNotToAutocorrect; i++) {
-            type(DESIRED_WORD);
-            type(Constants.CODE_SPACE);
-        }
-        startIndex = mEditText.getText().length();
-        type(WORD_TO_BE_CORRECTED);
+        int startIndex = mEditText.getText().length();
+        type("qpmx");
         type(Constants.CODE_SPACE);
-        endIndex = mEditText.getText().length();
-        assertEquals("not auto-corrected by user history", NOT_CORRECTED_RESULT,
-                mEditText.getText().subSequence(startIndex, endIndex).toString());
-        for (int i = typeCountNotToAutocorrect; i < typeCountToAutoCorrect; i++) {
-            type(DESIRED_WORD);
-            type(Constants.CODE_SPACE);
-        }
-        startIndex = mEditText.getText().length();
-        type(WORD_TO_BE_CORRECTED);
-        type(Constants.CODE_SPACE);
-        endIndex = mEditText.getText().length();
+        int endIndex = mEditText.getText().length();
         assertEquals("auto-corrected by user history",
-                CORRECTED_RESULT, mEditText.getText().subSequence(startIndex, endIndex).toString());
+                "qpmz ", mEditText.getText().subSequence(startIndex, endIndex).toString());
     }
 
     public void testPredictionsAfterSpace() {
         final String WORD_TO_TYPE = "Barack ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -476,24 +514,19 @@
 
     public void testPredictionsWithDoubleSpaceToPeriod() {
         mLatinIME.clearPersonalizedDictionariesForTest();
-        final String WORD_TO_TYPE = "Barack ";
+        final String WORD_TO_TYPE = "Barack  ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
-        // No need to test here, testPredictionsAfterSpace is testing it already
-        type(" ");
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
-        runMessages();
-        // Test the predictions have been cleared
-        SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
-        assertEquals("predictions cleared after double-space-to-period", suggestedWords.size(), 0);
+
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
-        // Test the first prediction is displayed
+
+        SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
         suggestedWords = mLatinIME.getSuggestedWordsForTest();
         assertEquals("predictions after cancel double-space-to-period", "Obama",
-                suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
+                mLatinIME.getSuggestedWordsForTest().getWord(0));
     }
 
     public void testPredictionsAfterManualPick() {
@@ -501,7 +534,7 @@
         type(WORD_TO_TYPE);
         // Choose the auto-correction. For "Barack", the auto-correction should be "Barack".
         pickSuggestionManually(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -513,17 +546,11 @@
         mLatinIME.clearPersonalizedDictionariesForTest();
         final String WORD_TO_TYPE = "Barack. ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
-        SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
-        assertEquals("No prediction after period after inputting once.", 0, suggestedWords.size());
 
-        type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
-        runMessages();
-        suggestedWords = mLatinIME.getSuggestedWordsForTest();
-        assertEquals("Beginning-of-Sentence prediction after inputting 2 times.", "Barack",
-                suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
+        SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
+        assertFalse(mLatinIME.getSuggestedWordsForTest().isEmpty());
     }
 
     public void testPredictionsAfterRecorrection() {
@@ -535,27 +562,23 @@
         final int endOfSuggestion = endOfPrefix + FIRST_NON_TYPED_SUGGESTION.length();
         final int indexForManualCursor = endOfPrefix + 3; // +3 because it's after "Bar" in "Barack"
         type(PREFIX);
-        mLatinIME.onUpdateSelection(0, 0, endOfPrefix, endOfPrefix, -1, -1);
+        sendUpdateForCursorMoveTo(endOfPrefix);
         type(WORD_TO_TYPE);
         pickSuggestionManually(FIRST_NON_TYPED_SUGGESTION);
-        mLatinIME.onUpdateSelection(endOfPrefix, endOfPrefix, endOfSuggestion, endOfSuggestion,
-                -1, -1);
+        sendUpdateForCursorMoveTo(endOfSuggestion);
         runMessages();
         type(" ");
-        mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion,
-                endOfSuggestion + 1, endOfSuggestion + 1, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sendUpdateForCursorMoveBy(1);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Simulate a manual cursor move
         mInputConnection.setSelection(indexForManualCursor, indexForManualCursor);
-        mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1,
-                indexForManualCursor, indexForManualCursor, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sendUpdateForCursorMoveTo(indexForManualCursor);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         pickSuggestionManually(WORD_TO_TYPE);
-        mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor,
-                endOfWord, endOfWord, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sendUpdateForCursorMoveTo(endOfWord);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -603,7 +626,7 @@
 
         for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
             type(WORD_TO_TYPE.substring(i, i+1));
-            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
             runMessages();
         }
         assertEquals("type many trailing single quotes one by one", EXPECTED_RESULT,
@@ -615,26 +638,148 @@
         final String EXPECTED_RESULT = WORD_TO_TYPE;
         for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
             type(WORD_TO_TYPE.substring(i, i+1));
-            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
             runMessages();
         }
         assertEquals("type words letter by letter", EXPECTED_RESULT,
                 mEditText.getText().toString());
     }
 
-    public void testSwitchLanguages() {
-        final String WORD_TO_TYPE_FIRST_PART = "com";
-        final String WORD_TO_TYPE_SECOND_PART = "md";
-        final String EXPECTED_RESULT = "comme";
-        changeLanguage("en");
-        type(WORD_TO_TYPE_FIRST_PART);
-        changeLanguage("fr");
+    public void testBasicGesture() {
+        gesture("this");
+        assertEquals("this", mEditText.getText().toString());
+    }
+
+    public void testGestureGesture() {
+        gesture("got");
+        gesture("milk");
+        assertEquals("got milk", mEditText.getText().toString());
+    }
+
+    public void testGestureBackspaceGestureAgain() {
+        gesture("this");
+        type(Constants.CODE_DELETE);
+        assertEquals("gesture then backspace", "", mEditText.getText().toString());
+        gesture("this");
+        if (DecoderSpecificConstants.SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION) {
+            assertNotEqual("this", mEditText.getText().toString());
+        } else {
+            assertEquals("this", mEditText.getText().toString());
+        }
+    }
+
+    private void typeOrGestureWordAndPutCursorInside(final boolean gesture, final String word,
+            final int startPos) {
+        final int END_OF_WORD = startPos + word.length();
+        final int NEW_CURSOR_POSITION = startPos + word.length() / 2;
+        if (gesture) {
+            gesture(word);
+        } else {
+            type(word);
+        }
+        sendUpdateForCursorMoveTo(END_OF_WORD);
         runMessages();
-        type(WORD_TO_TYPE_SECOND_PART);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sendUpdateForCursorMoveTo(NEW_CURSOR_POSITION);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
+        runMessages();
+    }
+
+    private void typeWordAndPutCursorInside(final String word, final int startPos) {
+        typeOrGestureWordAndPutCursorInside(false /* gesture */, word, startPos);
+    }
+
+    private void gestureWordAndPutCursorInside(final String word, final int startPos) {
+        typeOrGestureWordAndPutCursorInside(true /* gesture */, word, startPos);
+    }
+
+    private void ensureComposingSpanPos(final String message, final int from, final int to) {
+        assertEquals(message, from, BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+        assertEquals(message, to, BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+    }
+
+    public void testTypeWithinComposing() {
+        final String WORD_TO_TYPE = "something";
+        final String EXPECTED_RESULT = "some thing";
+        typeWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */);
+        type(" ");
+        ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1);
+        assertEquals("space in the middle of a composing word", EXPECTED_RESULT,
+                mEditText.getText().toString());
+        int cursorPos = sendUpdateForCursorMoveToEndOfLine();
+        runMessages();
+        type(" ");
+        assertEquals("mbo", "some thing ", mEditText.getText().toString());
+        typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */);
+        type(Constants.CODE_DELETE);
+        ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1);
+    }
+
+    public void testTypeWithinGestureComposing() {
+        final String WORD_TO_TYPE = "something";
+        final String EXPECTED_RESULT = "some thing";
+        gestureWordAndPutCursorInside(WORD_TO_TYPE, 0 /* startPos */);
+        type(" ");
+        ensureComposingSpanPos("space while in the middle of a word cancels composition", -1, -1);
+        assertEquals("space in the middle of a composing word", EXPECTED_RESULT,
+                mEditText.getText().toString());
+        int cursorPos = sendUpdateForCursorMoveToEndOfLine();
+        runMessages();
+        type(" ");
+        typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */);
+        type(Constants.CODE_DELETE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
+        ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1);
+    }
+
+    public void testManualPickThenSeparatorForFrench() {
+        final String WORD1_TO_TYPE = "test";
+        final String WORD2_TO_TYPE = "!";
+        final String EXPECTED_RESULT = "test !";
+        changeLanguage("fr");
+        type(WORD1_TO_TYPE);
+        pickSuggestionManually(WORD1_TO_TYPE);
+        type(WORD2_TO_TYPE);
+        assertEquals("manual pick then separator for French", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testClusteringPunctuationForFrench() {
+        final String WORD1_TO_TYPE = "test";
+        final String WORD2_TO_TYPE = "!!?!:!";
+        // In English, the expected result would be "test!!?!:!"
+        final String EXPECTED_RESULT = "test !!?! : !";
+        changeLanguage("fr");
+        type(WORD1_TO_TYPE);
+        pickSuggestionManually(WORD1_TO_TYPE);
+        type(WORD2_TO_TYPE);
+        assertEquals("clustering punctuation for French", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testWordThenSpaceThenPunctuationFromStripTwice() {
+        setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, false, true);
+
+        final String WORD_TO_TYPE = "test ";
+        final String PUNCTUATION_FROM_STRIP = "!";
+        final String EXPECTED_RESULT = "test!! ";
+        type(WORD_TO_TYPE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
+        runMessages();
+        assertTrue("type word then type space should display punctuation strip",
+                mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
+        pickSuggestionManually(PUNCTUATION_FROM_STRIP);
+        pickSuggestionManually(PUNCTUATION_FROM_STRIP);
+        assertEquals(EXPECTED_RESULT, mEditText.getText().toString());
+    }
+
+    public void testWordThenSpaceDisplaysPredictions() {
+        final String WORD_TO_TYPE = "Barack ";
+        final String EXPECTED_RESULT = "Obama";
+        type(WORD_TO_TYPE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
-        assertEquals("Suggestions updated after switching languages",
-                    EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
+        assertEquals("type word then type space yields predictions for French",
+                EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
new file mode 100644
index 0000000..4b44138
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsDeadKeys.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.common.Constants;
+
+import java.util.ArrayList;
+
+@LargeTest
+public class InputLogicTestsDeadKeys extends InputTestsBase {
+    // A helper class for readability
+    static class EventList extends ArrayList<Event> {
+        public EventList addCodePoint(final int codePoint, final boolean isDead) {
+            final Event event;
+            if (isDead) {
+                event = Event.createDeadEvent(codePoint, Event.NOT_A_KEY_CODE, null /* next */);
+            } else {
+                event = Event.createSoftwareKeypressEvent(codePoint, Event.NOT_A_KEY_CODE,
+                        Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+                        false /* isKeyRepeat */);
+            }
+            add(event);
+            return this;
+        }
+
+        public EventList addKey(final int keyCode) {
+            add(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT, keyCode,
+                    Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+                    false /* isKeyRepeat */));
+            return this;
+        }
+    }
+
+    public void testDeadCircumflexSimple() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final String EXPECTED_RESULT = "aê";
+        final EventList events = new EventList()
+                .addCodePoint('a', false)
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+                .addCodePoint('e', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("simple dead circumflex", EXPECTED_RESULT, mEditText.getText().toString());
+    }
+
+    public void testDeadCircumflexBackspace() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final String EXPECTED_RESULT = "ae";
+        final EventList events = new EventList()
+                .addCodePoint('a', false)
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+                .addKey(Constants.CODE_DELETE)
+                .addCodePoint('e', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead circumflex backspace", EXPECTED_RESULT, mEditText.getText().toString());
+    }
+
+    public void testDeadCircumflexFeedback() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final String EXPECTED_RESULT = "a\u02C6";
+        final EventList events = new EventList()
+                .addCodePoint('a', false)
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead circumflex gives feedback", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDeadDiaeresisSpace() {
+        final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+        final String EXPECTED_RESULT = "a\u00A8e\u00A8i";
+        final EventList events = new EventList()
+                .addCodePoint('a', false)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addCodePoint(Constants.CODE_SPACE, false)
+                .addCodePoint('e', false)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addCodePoint(Constants.CODE_ENTER, false)
+                .addCodePoint('i', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead diaeresis space commits the dead char", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDeadAcuteLetterBackspace() {
+        final int MODIFIER_LETTER_ACUTE = 0xB4;
+        final String EXPECTED_RESULT1 = "aá";
+        final String EXPECTED_RESULT2 = "a";
+        final EventList events = new EventList()
+                .addCodePoint('a', false)
+                .addCodePoint(MODIFIER_LETTER_ACUTE, true)
+                .addCodePoint('a', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead acute on a typed", EXPECTED_RESULT1, mEditText.getText().toString());
+        mLatinIME.onEvent(Event.createSoftwareKeypressEvent(Event.NOT_A_CODE_POINT,
+                Constants.CODE_DELETE, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+                false /* isKeyRepeat */));
+        assertEquals("a with acute deleted", EXPECTED_RESULT2, mEditText.getText().toString());
+    }
+
+    public void testFinnishStroke() {
+        final int MODIFIER_LETTER_STROKE = '-';
+        final String EXPECTED_RESULT = "x\u0110\u0127";
+        final EventList events = new EventList()
+                .addCodePoint('x', false)
+                .addCodePoint(MODIFIER_LETTER_STROKE, true)
+                .addCodePoint('D', false)
+                .addCodePoint(MODIFIER_LETTER_STROKE, true)
+                .addCodePoint('h', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("Finnish dead stroke", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDoubleDeadOgonek() {
+        final int MODIFIER_LETTER_OGONEK = 0x02DB;
+        final String EXPECTED_RESULT = "txǫs\u02DBfk";
+        final EventList events = new EventList()
+                .addCodePoint('t', false)
+                .addCodePoint('x', false)
+                .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+                .addCodePoint('o', false)
+                .addCodePoint('s', false)
+                .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+                .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+                .addCodePoint('f', false)
+                .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+                .addCodePoint(MODIFIER_LETTER_OGONEK, true)
+                .addKey(Constants.CODE_DELETE)
+                .addCodePoint('k', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("double dead ogonek, and backspace", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDeadCircumflexDeadDiaeresis() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+        final String EXPECTED_RESULT = "r̂̈";
+
+        final EventList events = new EventList()
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addCodePoint('r', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("both circumflex and diaeresis on r", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDeadCircumflexDeadDiaeresisBackspace() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+        final String EXPECTED_RESULT = "û";
+
+        final EventList events = new EventList()
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addKey(Constants.CODE_DELETE)
+                .addCodePoint('u', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead circumflex, dead diaeresis, backspace, u", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+
+    public void testDeadCircumflexDoubleDeadDiaeresisBackspace() {
+        final int MODIFIER_LETTER_CIRCUMFLEX_ACCENT = 0x02C6;
+        final int MODIFIER_LETTER_DIAERESIS = 0xA8;
+        final String EXPECTED_RESULT = "\u02C6u";
+
+        final EventList events = new EventList()
+                .addCodePoint(MODIFIER_LETTER_CIRCUMFLEX_ACCENT, true)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addCodePoint(MODIFIER_LETTER_DIAERESIS, true)
+                .addKey(Constants.CODE_DELETE)
+                .addCodePoint('u', false);
+        for (final Event event : events) {
+            mLatinIME.onEvent(event);
+        }
+        assertEquals("dead circumflex, double dead diaeresis, backspace, u", EXPECTED_RESULT,
+                mEditText.getText().toString());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
index 2560407..12461c9 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
@@ -19,6 +19,8 @@
 import android.test.suitebuilder.annotation.LargeTest;
 import android.view.inputmethod.BaseInputConnection;
 
+import com.android.inputmethod.latin.common.Constants;
+
 @LargeTest
 public class InputLogicTestsLanguageWithoutSpaces extends InputTestsBase {
     public void testAutoCorrectForLanguageWithoutSpaces() {
@@ -74,7 +76,7 @@
         mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
         mLatinIME.onUpdateSelection(typedLength, typedLength,
                 CURSOR_POS, CURSOR_POS, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         assertEquals("start composing inside text", -1,
                 BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -87,11 +89,39 @@
                 BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
     }
 
+    public void testMovingCursorInsideWordAndType() {
+        final String WORD_TO_TYPE = "abcdefgh";
+        final int typedLength = WORD_TO_TYPE.length();
+        final int CURSOR_POS = 4;
+        changeKeyboardLocaleAndDictLocale("th", "en_US");
+        type(WORD_TO_TYPE);
+        mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, 0, typedLength);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+        runMessages();
+        mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
+        mLatinIME.onUpdateSelection(typedLength, typedLength,
+                CURSOR_POS, CURSOR_POS, 0, typedLength);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+        runMessages();
+        assertEquals("move cursor inside text", 0,
+                BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+        assertEquals("move cursor inside text", typedLength,
+                BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+        type("x");
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
+        runMessages();
+        assertEquals("start typing while cursor inside composition", CURSOR_POS,
+                BaseInputConnection.getComposingSpanStart(mEditText.getText()));
+        assertEquals("start typing while cursor inside composition", CURSOR_POS + 1,
+                BaseInputConnection.getComposingSpanEnd(mEditText.getText()));
+    }
+
     public void testPredictions() {
         final String WORD_TO_TYPE = "Barack ";
         changeKeyboardLocaleAndDictLocale("th", "en_US");
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Make sure there is no space
         assertEquals("predictions in lang without spaces", "Barack",
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
deleted file mode 100644
index 866f889..0000000
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.test.suitebuilder.annotation.LargeTest;
-
-@LargeTest
-public class InputLogicTestsNonEnglish extends InputTestsBase {
-    final String NEXT_WORD_PREDICTION_OPTION = "next_word_prediction";
-
-    public void testAutoCorrectForFrench() {
-        final String STRING_TO_TYPE = "irq ";
-        final String EXPECTED_RESULT = "ira ";
-        changeLanguage("fr");
-        type(STRING_TO_TYPE);
-        assertEquals("simple auto-correct for French", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
-    public void testManualPickThenSeparatorForFrench() {
-        final String WORD1_TO_TYPE = "test";
-        final String WORD2_TO_TYPE = "!";
-        final String EXPECTED_RESULT = "test !";
-        changeLanguage("fr");
-        type(WORD1_TO_TYPE);
-        pickSuggestionManually(WORD1_TO_TYPE);
-        type(WORD2_TO_TYPE);
-        assertEquals("manual pick then separator for French", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
-    public void testClusteringPunctuationForFrench() {
-        final String WORD1_TO_TYPE = "test";
-        final String WORD2_TO_TYPE = "!!?!:!";
-        // In English, the expected result would be "test!!?!:!"
-        final String EXPECTED_RESULT = "test !!?! : !";
-        changeLanguage("fr");
-        type(WORD1_TO_TYPE);
-        pickSuggestionManually(WORD1_TO_TYPE);
-        type(WORD2_TO_TYPE);
-        assertEquals("clustering punctuation for French", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
-    public void testWordThenSpaceThenPunctuationFromStripTwiceForFrench() {
-        final String WORD_TO_TYPE = "test ";
-        final String PUNCTUATION_FROM_STRIP = "!";
-        final String EXPECTED_RESULT = "test !!";
-        final boolean defaultNextWordPredictionOption =
-                mLatinIME.getResources().getBoolean(R.bool.config_default_next_word_prediction);
-        final boolean previousNextWordPredictionOption =
-                setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, false,
-                        defaultNextWordPredictionOption);
-        try {
-            changeLanguage("fr");
-            type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
-            runMessages();
-            assertTrue("type word then type space should display punctuation strip",
-                    mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
-            pickSuggestionManually(PUNCTUATION_FROM_STRIP);
-            pickSuggestionManually(PUNCTUATION_FROM_STRIP);
-            assertEquals("type word then type space then punctuation from strip twice for French",
-                    EXPECTED_RESULT, mEditText.getText().toString());
-        } finally {
-            setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, previousNextWordPredictionOption,
-                    defaultNextWordPredictionOption);
-        }
-    }
-
-    public void testWordThenSpaceDisplaysPredictions() {
-        final String WORD_TO_TYPE = "beaujolais ";
-        final String EXPECTED_RESULT = "nouveau";
-        final boolean defaultNextWordPredictionOption =
-                mLatinIME.getResources().getBoolean(R.bool.config_default_next_word_prediction);
-        final boolean previousNextWordPredictionOption =
-                setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, true,
-                        defaultNextWordPredictionOption);
-        try {
-            changeLanguage("fr");
-            type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
-            runMessages();
-            final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
-            assertEquals("type word then type space yields predictions for French",
-                    EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
-        } finally {
-            setBooleanPreference(NEXT_WORD_PREDICTION_OPTION, previousNextWordPredictionOption,
-                    defaultNextWordPredictionOption);
-        }
-    }
-
-    public void testAutoCorrectForGerman() {
-        final String STRING_TO_TYPE = "unf ";
-        final String EXPECTED_RESULT = "und ";
-        changeLanguage("de");
-        type(STRING_TO_TYPE);
-        assertEquals("simple auto-correct for German", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
-    public void testAutoCorrectWithUmlautForGerman() {
-        final String STRING_TO_TYPE = "ueber ";
-        final String EXPECTED_RESULT = "über ";
-        changeLanguage("de");
-        type(STRING_TO_TYPE);
-        assertEquals("auto-correct with umlaut for German", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
deleted file mode 100644
index ab69c85..0000000
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsReorderingMyanmar.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.util.Pair;
-
-/*
- * Relevant characters for this test :
- * Spurs the need to reorder :
- * U+1031 MYANMAR VOWEL SIGN E : ေ
- * U+1004 U+103A U+1039 Kinzi. It's a compound character.
- *
- * List of consonants :
- * U+1000 MYANMAR LETTER KA က
- * U+1001 MYANMAR LETTER KHA ခ
- * U+1002 MYANMAR LETTER GA ဂ
- * U+1003 MYANMAR LETTER GHA ဃ
- * U+1004 MYANMAR LETTER NGA င
- * U+1005 MYANMAR LETTER CA စ
- * U+1006 MYANMAR LETTER CHA ဆ
- * U+1007 MYANMAR LETTER JA ဇ
- * U+1008 MYANMAR LETTER JHA ဈ
- * U+1009 MYANMAR LETTER NYA ဉ
- * U+100A MYANMAR LETTER NNYA ည
- * U+100B MYANMAR LETTER TTA ဋ
- * U+100C MYANMAR LETTER TTHA ဌ
- * U+100D MYANMAR LETTER DDA ဍ
- * U+100E MYANMAR LETTER DDHA ဎ
- * U+100F MYANMAR LETTER NNA ဏ
- * U+1010 MYANMAR LETTER TA တ
- * U+1011 MYANMAR LETTER THA ထ
- * U+1012 MYANMAR LETTER DA ဒ
- * U+1013 MYANMAR LETTER DHA ဓ
- * U+1014 MYANMAR LETTER NA န
- * U+1015 MYANMAR LETTER PA ပ
- * U+1016 MYANMAR LETTER PHA ဖ
- * U+1017 MYANMAR LETTER BA ဗ
- * U+1018 MYANMAR LETTER BHA ဘ
- * U+1019 MYANMAR LETTER MA မ
- * U+101A MYANMAR LETTER YA ယ
- * U+101B MYANMAR LETTER RA ရ
- * U+101C MYANMAR LETTER LA လ
- * U+101D MYANMAR LETTER WA ဝ
- * U+101E MYANMAR LETTER SA သ
- * U+101F MYANMAR LETTER HA ဟ
- * U+1020 MYANMAR LETTER LLA ဠ
- * U+103F MYANMAR LETTER GREAT SA ဿ
- *
- * List of medials :
- * U+103B MYANMAR CONSONANT SIGN MEDIAL YA ျ
- * U+103C MYANMAR CONSONANT SIGN MEDIAL RA ြ
- * U+103D MYANMAR CONSONANT SIGN MEDIAL WA ွ
- * U+103E MYANMAR CONSONANT SIGN MEDIAL HA ှ
- * U+105E MYANMAR CONSONANT SIGN MON MEDIAL NA ၞ
- * U+105F MYANMAR CONSONANT SIGN MON MEDIAL MA ၟ
- * U+1060 MYANMAR CONSONANT SIGN MON MEDIAL LA ၠ
- * U+1082 MYANMAR CONSONANT SIGN SHAN MEDIAL WA ႂ
- *
- * Other relevant characters :
- * U+200C ZERO WIDTH NON-JOINER
- * U+200B ZERO WIDTH SPACE
- */
-
-@LargeTest
-// These tests are inactive until the combining code for Myanmar Reordering is sorted out.
-@Suppress
-@SuppressWarnings("rawtypes")
-public class InputLogicTestsReorderingMyanmar extends InputTestsBase {
-    // The tests are formatted as follows.
-    // Each test is an entry in the array of Pair arrays.
-
-    // One test is an array of pairs. Each pair contains, in the `first' member,
-    // the code points that the next key press should contain. In the `second'
-    // member is stored the string that should be in the text view after this
-    // key press.
-
-    private static final Pair[][] TESTS = {
-
-        // Tests for U+1031 MYANMAR VOWEL SIGN E : ေ
-        new Pair[] { // Type : U+1031 U+1000 U+101F ေ က ဟ
-            Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
-            Pair.create(new int[] { 0x1000 }, "\u1000\u1031"), // ကေ
-            Pair.create(new int[] { 0x101F }, "\u1000\u1031\u101F") // ကေဟ
-        },
-
-        new Pair[] { // Type : U+1000 U+1031 U+101F က ေ ဟ
-            Pair.create(new int[] { 0x1000 }, "\u1000"), // က
-            Pair.create(new int[] { 0x1031 }, "\u1000\u200B\u1031"), // က‌ေ
-            Pair.create(new int[] { 0x101F }, "\u1000\u101F\u1031") // ကဟေ
-        },
-
-        new Pair[] { // Type : U+1031 U+101D U+103E U+1018 ေ ဝ ှ ဘ
-            Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
-            Pair.create(new int[] { 0x101D }, "\u101D\u1031"), // ဝေ
-            Pair.create(new int[] { 0x103E }, "\u101D\u103E\u1031"), // ဝှေ
-            Pair.create(new int[] { 0x1018 }, "\u101D\u103E\u1031\u1018") // ဝှေဘ
-        },
-
-        new Pair[] { // Type : U+1031 U+1014 U+1031 U+1000 U+102C U+1004 U+103A U+1038 U+101C
-            // U+102C U+1038 U+104B ေ န ေ က ာ င ် း လ ာ း ။
-            Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
-            Pair.create(new int[] { 0x1014 }, "\u1014\u1031"), // နေ
-            Pair.create(new int[] { 0x1031 }, "\u1014\u1031\u1031"), // နေ‌ေ
-            Pair.create(new int[] { 0x1000 }, "\u1014\u1031\u1000\u1031"), // နေကေ
-            Pair.create(new int[] { 0x102C }, "\u1014\u1031\u1000\u1031\u102C"), // နေကော
-            Pair.create(new int[] { 0x1004 }, "\u1014\u1031\u1000\u1031\u102C\u1004"), // နေကောင
-            Pair.create(new int[] { 0x103A }, // နေကောင်
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A"),
-            Pair.create(new int[] { 0x1038 }, // နေကောင်း
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038"),
-            Pair.create(new int[] { 0x101C }, // နေကောင်းလ
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C"),
-            Pair.create(new int[] { 0x102C }, // နေကောင်းလာ
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C"),
-            Pair.create(new int[] { 0x1038 }, // နေကောင်းလား
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038"),
-            Pair.create(new int[] { 0x104B }, // နေကောင်းလား။
-                    "\u1014\u1031\u1000\u1031\u102C\u1004\u103A\u1038\u101C\u102C\u1038\u104B")
-        },
-
-        new Pair[] { // Type : U+1031 U+1031 U+1031 U+1000 ေ ေ ေ က
-            Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
-            Pair.create(new int[] { 0x1031 }, "\u1031\u1031"), // ေေ
-            Pair.create(new int[] { 0x1031 }, "\u1031\u1031\u1031"), // U+1031ေေေ
-            Pair.create(new int[] { 0x1000 }, "\u1031\u1031\u1000\u1031") // ေေကေ
-        },
-
-        new Pair[] { // Type : U+1031 U+1001 U+103B U+103D U+1038 ေ ခ ျ ွ း
-            Pair.create(new int[] { 0x1031 }, "\u1031"), // ေ
-            Pair.create(new int[] { 0x1001 }, "\u1001\u1031"), // ခေ
-            Pair.create(new int[] { 0x103B }, "\u1001\u103B\u1031"), // ချေ
-            Pair.create(new int[] { 0x103D }, "\u1001\u103B\u103D\u1031"), // ချွေ
-            Pair.create(new int[] { 0x1038 }, "\u1001\u103B\u103D\u1031\u1038") // ချွေး
-        },
-
-        // Tests for Kinzi U+1004 U+103A U+1039 :
-
-        /* Kinzi reordering is not implemented yet. Uncomment these tests when it is.
-
-        new Pair[] { // Type : U+1021 U+1002 (U+1004 U+103A U+1039)
-            // U+101C U+1014 U+103A အ ဂ (င ် ္) လ န ်
-            Pair.create(new int[] { 0x1021 }, "\u1021"), // အ
-            Pair.create(new int[] { 0x1002 }, "\u1021\u1002"), // အဂ
-            Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // အင်္ဂ
-                    "\u1021\u1004\u103A\u1039\u1002"),
-            Pair.create(new int[] { 0x101C }, // အင်္ဂလ
-                    "\u1021\u1004\u103A\u1039\u1002\u101C"),
-            Pair.create(new int[] { 0x1014 }, // အင်္ဂလန
-                    "\u1021\u1004\u103A\u1039\u1002\u101C\u1014"),
-            Pair.create(new int[] { 0x103A }, // အင်္ဂလန်
-                    "\u1021\u1004\u103A\u1039\u1002\u101C\u1014\u103A")
-        },
-
-        new Pair[] { //Type : kinzi after a whole syllable U+101E U+1001 U+103B U+102D U+102F
-            // (U+1004 U+103A U+1039) U+1004 U+103A U+1038 သ ခ ျ ိ ု င ် ္ င ် း
-            Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
-            Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
-            Pair.create(new int[] { 0x103B }, "\u101E\u1001\u103B"), // သချ
-            Pair.create(new int[] { 0x102D }, "\u101E\u1001\u103B\u102D"), // သချိ
-            Pair.create(new int[] { 0x102F }, "\u101E\u1001\u103B\u102D\u102F"), // သချို
-            Pair.create(new int[] { 0x1004, 0x103A, 0x1039}, // သင်္ချို
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
-            Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
-            Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
-            Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
-        },
-
-        new Pair[] { // Type : kinzi after the consonant U+101E U+1001 (U+1004 U+103A U+1039)
-            // U+103B U+102D U+102F U+1004 U+103A U+1038 သ ခ င ် ္ ျ ိ ု င ် း
-            Pair.create(new int[] { 0x101E }, "\u101E"), // သခ
-            Pair.create(new int[] { 0x1001 }, "\u101E\u1001"), // သခ
-            Pair.create(new int[] { 0x1004, 0x103A, 0x1039 }, // သင်္ခ
-                    "\u101E\u1004\u103A\u1039\u1001"),
-            Pair.create(new int[] { 0x103B }, // သင်္ချ
-                    "\u101E\u1004\u103A\u1039\u1001\u103B"),
-            Pair.create(new int[] { 0x102D }, // သင်္ချိ
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D"),
-            Pair.create(new int[] { 0x102F }, // သင်္ချို
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F"),
-            Pair.create(new int[] { 0x1004 }, // သင်္ချိုင
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004"),
-            Pair.create(new int[] { 0x103A }, // သင်္ချိုင်
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A"),
-            Pair.create(new int[] { 0x1038 }, // သင်္ချိုင်း
-                    "\u101E\u1004\u103A\u1039\u1001\u103B\u102D\u102F\u1004\u103A\u1038")
-        },
-        */
-    };
-
-    @SuppressWarnings("unchecked")
-    private void doMyanmarTest(final int testNumber, final Pair[] test) {
-        int stepNumber = 0;
-        for (final Pair<int[], String> step : test) {
-            ++stepNumber;
-            final int[] input = step.first;
-            final String expectedResult = step.second;
-            if (input.length > 1) {
-                mLatinIME.onTextInput(new String(input, 0, input.length));
-            } else {
-                type(input[0]);
-            }
-            assertEquals("Myanmar reordering test " + testNumber + ", step " + stepNumber,
-                    expectedResult, mEditText.getText().toString());
-        }
-    }
-
-    public void testMyanmarReordering() {
-        int testNumber = 0;
-        changeLanguage("my_MM", "CombiningRules=MyanmarReordering");
-        for (final Pair[] test : TESTS) {
-            // Small trick to reset LatinIME : setText("") and send updateSelection with values
-            // LatinIME has never seen, and cursor pos 0,0.
-            mEditText.setText("");
-            mLatinIME.onUpdateSelection(1, 1, 0, 0, -1, -1);
-            doMyanmarTest(++testNumber, test);
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
deleted file mode 100644
index 1a47cdd..0000000
--- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.inputmethod.latin.utils.ResizableIntArray;
-
-import java.util.Arrays;
-
-@SmallTest
-public class InputPointersTests extends AndroidTestCase {
-    private static final int DEFAULT_CAPACITY = 48;
-
-    public void testNewInstance() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        assertEquals("new instance size", 0, src.getPointerSize());
-        assertNotNull("new instance xCoordinates", src.getXCoordinates());
-        assertNotNull("new instance yCoordinates", src.getYCoordinates());
-        assertNotNull("new instance pointerIds", src.getPointerIds());
-        assertNotNull("new instance times", src.getTimes());
-    }
-
-    public void testReset() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int[] xCoordinates = src.getXCoordinates();
-        final int[] yCoordinates = src.getXCoordinates();
-        final int[] pointerIds = src.getXCoordinates();
-        final int[] times = src.getXCoordinates();
-
-        src.reset();
-        assertEquals("size after reset", 0, src.getPointerSize());
-        assertNotSame("xCoordinates after reset", xCoordinates, src.getXCoordinates());
-        assertNotSame("yCoordinates after reset", yCoordinates, src.getYCoordinates());
-        assertNotSame("pointerIds after reset", pointerIds, src.getPointerIds());
-        assertNotSame("times after reset", times, src.getTimes());
-    }
-
-    public void testAdd() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int limit = src.getXCoordinates().length * 2 + 10;
-        for (int i = 0; i < limit; i++) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            src.addPointer(x, y, pointerId, time);
-            assertEquals("size after add " + i, i + 1, src.getPointerSize());
-        }
-        for (int i = 0; i < limit; i++) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
-            assertEquals("times at " + i, time, src.getTimes()[i]);
-        }
-    }
-
-    public void testAddAt() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int limit = 1000, step = 100;
-        for (int i = 0; i < limit; i += step) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            src.addPointerAt(i, x, y, pointerId, time);
-            assertEquals("size after add at " + i, i + 1, src.getPointerSize());
-        }
-        for (int i = 0; i < limit; i += step) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
-            assertEquals("times at " + i, time, src.getTimes()[i]);
-        }
-    }
-
-    public void testSet() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int limit = src.getXCoordinates().length * 2 + 10;
-        for (int i = 0; i < limit; i++) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            src.addPointer(x, y, pointerId, time);
-        }
-        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        dst.set(src);
-        assertEquals("size after set", dst.getPointerSize(), src.getPointerSize());
-        assertSame("xCoordinates after set", dst.getXCoordinates(), src.getXCoordinates());
-        assertSame("yCoordinates after set", dst.getYCoordinates(), src.getYCoordinates());
-        assertSame("pointerIds after set", dst.getPointerIds(), src.getPointerIds());
-        assertSame("times after set", dst.getTimes(), src.getTimes());
-    }
-
-    public void testCopy() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int limit = 100;
-        for (int i = 0; i < limit; i++) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            src.addPointer(x, y, pointerId, time);
-        }
-        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        dst.copy(src);
-        assertEquals("size after copy", dst.getPointerSize(), src.getPointerSize());
-        assertNotSame("xCoordinates after copy", dst.getXCoordinates(), src.getXCoordinates());
-        assertNotSame("yCoordinates after copy", dst.getYCoordinates(), src.getYCoordinates());
-        assertNotSame("pointerIds after copy", dst.getPointerIds(), src.getPointerIds());
-        assertNotSame("times after copy", dst.getTimes(), src.getTimes());
-        final int size = dst.getPointerSize();
-        assertIntArrayEquals("xCoordinates values after copy",
-                dst.getXCoordinates(), 0, src.getXCoordinates(), 0, size);
-        assertIntArrayEquals("yCoordinates values after copy",
-                dst.getYCoordinates(), 0, src.getYCoordinates(), 0, size);
-        assertIntArrayEquals("pointerIds values after copy",
-                dst.getPointerIds(), 0, src.getPointerIds(), 0, size);
-        assertIntArrayEquals("times values after copy",
-                dst.getTimes(), 0, src.getTimes(), 0, size);
-    }
-
-    public void testAppend() {
-        final int dstLength = 50;
-        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        for (int i = 0; i < dstLength; i++) {
-            final int x = i * 4;
-            final int y = i * 3;
-            final int pointerId = i * 2;
-            final int time = i;
-            dst.addPointer(x, y, pointerId, time);
-        }
-        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
-        dstCopy.copy(dst);
-
-        final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
-        final ResizableIntArray srcYCoords = new ResizableIntArray(DEFAULT_CAPACITY);
-        final ResizableIntArray srcPointerIds = new ResizableIntArray(DEFAULT_CAPACITY);
-        final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int srcLength = 100;
-        final int srcPointerId = 10;
-        for (int i = 0; i < srcLength; i++) {
-            final int x = i;
-            final int y = i * 2;
-            // The time value must be larger than <code>dst</code>.
-            final int time = i * 4 + dstLength;
-            srcXCoords.add(x);
-            srcYCoords.add(y);
-            srcPointerIds.add(srcPointerId);
-            srcTimes.add(time);
-        }
-
-        final int startPos = 0;
-        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
-                startPos, 0 /* length */);
-        assertEquals("size after append zero", dstLength, dst.getPointerSize());
-        assertIntArrayEquals("xCoordinates after append zero",
-                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
-        assertIntArrayEquals("yCoordinates after append zero",
-                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
-        assertIntArrayEquals("pointerIds after append zero",
-                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
-        assertIntArrayEquals("times after append zero",
-                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
-
-        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
-                startPos, srcLength);
-        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
-        assertTrue("primitive length after append",
-                dst.getPointerIds().length >= dstLength + srcLength);
-        assertIntArrayEquals("original xCoordinates values after append",
-                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
-        assertIntArrayEquals("original yCoordinates values after append",
-                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
-        assertIntArrayEquals("original pointerIds values after append",
-                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
-        assertIntArrayEquals("original times values after append",
-                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
-        assertIntArrayEquals("appended xCoordinates values after append",
-                srcXCoords.getPrimitiveArray(), startPos, dst.getXCoordinates(),
-                dstLength, srcLength);
-        assertIntArrayEquals("appended yCoordinates values after append",
-                srcYCoords.getPrimitiveArray(), startPos, dst.getYCoordinates(),
-                dstLength, srcLength);
-        assertIntArrayEquals("appended pointerIds values after append",
-                srcPointerIds.getPrimitiveArray(), startPos, dst.getPointerIds(),
-                dstLength, srcLength);
-        assertIntArrayEquals("appended times values after append",
-                srcTimes.getPrimitiveArray(), startPos, dst.getTimes(), dstLength, srcLength);
-    }
-
-    public void testAppendResizableIntArray() {
-        final int dstLength = 50;
-        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
-        for (int i = 0; i < dstLength; i++) {
-            final int x = i * 4;
-            final int y = i * 3;
-            final int pointerId = i * 2;
-            final int time = i;
-            dst.addPointer(x, y, pointerId, time);
-        }
-        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
-        dstCopy.copy(dst);
-
-        final int srcLength = 100;
-        final int srcPointerId = 1;
-        final int[] srcPointerIds = new int[srcLength];
-        Arrays.fill(srcPointerIds, srcPointerId);
-        final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
-        final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
-        final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY);
-        for (int i = 0; i < srcLength; i++) {
-            // The time value must be larger than <code>dst</code>.
-            final int time = i * 2 + dstLength;
-            final int x = i * 3;
-            final int y = i * 4;
-            srcTimes.add(time);
-            srcXCoords.add(x);
-            srcYCoords.add(y);
-        }
-
-        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0);
-        assertEquals("size after append zero", dstLength, dst.getPointerSize());
-        assertIntArrayEquals("xCoordinates after append zero",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
-        assertIntArrayEquals("yCoordinates after append zero",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
-        assertIntArrayEquals("pointerIds after append zero",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
-        assertIntArrayEquals("times after append zero",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
-
-        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLength);
-        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
-        assertTrue("primitive length after append",
-                dst.getPointerIds().length >= dstLength + srcLength);
-        assertIntArrayEquals("original xCoordinates values after append",
-                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
-        assertIntArrayEquals("original yCoordinates values after append",
-                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
-        assertIntArrayEquals("original pointerIds values after append",
-                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
-        assertIntArrayEquals("original times values after append",
-                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
-        assertIntArrayEquals("appended xCoordinates values after append",
-                srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLength, srcLength);
-        assertIntArrayEquals("appended yCoordinates values after append",
-                srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLength, srcLength);
-        assertIntArrayEquals("appended pointerIds values after append",
-                srcPointerIds, 0, dst.getPointerIds(), dstLength, srcLength);
-        assertIntArrayEquals("appended times values after append",
-                srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLength, srcLength);
-    }
-
-    // TODO: Consolidate this method with
-    // {@link ResizableIntArrayTests#assertIntArrayEquals(String,int[],int,int[],int,int)}.
-    private static void assertIntArrayEquals(final String message, final int[] expecteds,
-            final int expectedPos, final int[] actuals, final int actualPos, final int length) {
-        if (expecteds == actuals) {
-            return;
-        }
-        if (expecteds == null || actuals == null) {
-            assertEquals(message, Arrays.toString(expecteds), Arrays.toString(actuals));
-            return;
-        }
-        if (expecteds.length < expectedPos + length || actuals.length < actualPos + length) {
-            fail(message + ": insufficient length: expecteds=" + Arrays.toString(expecteds)
-                    + " actuals=" + Arrays.toString(actuals));
-            return;
-        }
-        for (int i = 0; i < length; i++) {
-            assertEquals(message + " [" + i + "]",
-                    expecteds[i + expectedPos], actuals[i + actualPos]);
-        }
-    }
-
-    public void testShift() {
-        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
-        final int limit = 100;
-        final int shiftAmount = 20;
-        for (int i = 0; i < limit; i++) {
-            final int x = i;
-            final int y = i * 2;
-            final int pointerId = i * 3;
-            final int time = i * 4;
-            src.addPointer(x, y, pointerId, time);
-        }
-        src.shift(shiftAmount);
-        assertEquals("length after shift", src.getPointerSize(), limit - shiftAmount);
-        for (int i = 0; i < limit - shiftAmount; ++i) {
-            final int oldIndex = i + shiftAmount;
-            final int x = oldIndex;
-            final int y = oldIndex * 2;
-            final int pointerId = oldIndex * 3;
-            final int time = oldIndex * 4;
-            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
-            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
-            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
-            assertEquals("times at " + i, time, src.getTimes()[i]);
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 986fb10..dead53d 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.graphics.Point;
 import android.os.Looper;
 import android.preference.PreferenceManager;
 import android.test.ServiceTestCase;
@@ -36,12 +37,17 @@
 import android.widget.FrameLayout;
 
 import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
+import com.android.inputmethod.event.Event;
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Dictionary.PhonyDictionary;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.InputPointers;
+import com.android.inputmethod.latin.common.LocaleUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.settings.DebugSettings;
 import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.LocaleUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Locale;
@@ -52,21 +58,28 @@
 
     // Default value for auto-correction threshold. This is the string representation of the
     // index in the resources array of auto-correction threshold settings.
-    private static final String DEFAULT_AUTO_CORRECTION_THRESHOLD = "1";
+    private static final boolean DEFAULT_AUTO_CORRECTION = true;
 
     // The message that sets the underline is posted with a 500 ms delay
-    protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 500;
+    protected static final int DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS = 500;
     // The message that sets predictions is posted with a 200 ms delay
-    protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
-    private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
+    protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS = 200;
+    // We wait for gesture computation for this delay
+    protected static final int DELAY_TO_WAIT_FOR_GESTURE_MILLIS = 200;
+    // If a dictionary takes longer to load, we could have serious problems.
+    private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 5;
+
+    // Type for a test phony dictionary
+    private static final String TYPE_TEST = "test";
+    private static final PhonyDictionary DICTIONARY_TEST = new PhonyDictionary(TYPE_TEST);
 
     protected LatinIME mLatinIME;
     protected Keyboard mKeyboard;
     protected MyEditText mEditText;
     protected View mInputView;
     protected InputConnection mInputConnection;
+    private boolean mPreviousAutoCorrectSetting;
     private boolean mPreviousBigramPredictionSettings;
-    private String mPreviousAutoCorrectSetting;
 
     // A helper class to ease span tests
     public static class SpanGetter {
@@ -94,12 +107,15 @@
                 throw new RuntimeException("Expected one span, found " + spans.length);
             }
         }
+        public SuggestionSpan getSpan() {
+            return (SuggestionSpan) mSpan;
+        }
         public boolean isAutoCorrectionIndicator() {
             return (mSpan instanceof SuggestionSpan) &&
-                    0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & ((SuggestionSpan)mSpan).getFlags());
+                    0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & getSpan().getFlags());
         }
         public String[] getSuggestions() {
-            return ((SuggestionSpan)mSpan).getSuggestions();
+            return getSpan().getSuggestions();
         }
     }
 
@@ -140,8 +156,6 @@
         super(LatinIMEForTests.class);
     }
 
-    // TODO: Isn't there a way to make this generic somehow? We can take a <T> and return a <T>
-    // but we'd have to dispatch types on editor.put...() functions
     protected boolean setBooleanPreference(final String key, final boolean value,
             final boolean defaultValue) {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
@@ -152,6 +166,11 @@
         return previousSetting;
     }
 
+    protected boolean getBooleanPreference(final String key, final boolean defaultValue) {
+        return PreferenceManager.getDefaultSharedPreferences(mLatinIME)
+                .getBoolean(key, defaultValue);
+    }
+
     protected String setStringPreference(final String key, final String value,
             final String defaultValue) {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
@@ -182,13 +201,17 @@
                 | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
         mEditText.setInputType(inputType);
         mEditText.setEnabled(true);
+        mLastCursorPos = 0;
+        if (null == Looper.myLooper()) {
+            Looper.prepare();
+        }
         setupService();
         mLatinIME = getService();
         setDebugMode(true);
         mPreviousBigramPredictionSettings = setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS,
                 true, true /* defaultValue */);
-        mPreviousAutoCorrectSetting = setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
-                DEFAULT_AUTO_CORRECTION_THRESHOLD, DEFAULT_AUTO_CORRECTION_THRESHOLD);
+        mPreviousAutoCorrectSetting = setBooleanPreference(Settings.PREF_AUTO_CORRECTION,
+                DEFAULT_AUTO_CORRECTION, DEFAULT_AUTO_CORRECTION);
         mLatinIME.onCreate();
         EditorInfo ei = new EditorInfo();
         final InputConnection ic = mEditText.onCreateInputConnection(ei);
@@ -207,7 +230,7 @@
         // Run messages to avoid the messages enqueued by startInputView() and its friends
         // to run on a later call and ruin things. We need to wait first because some of them
         // can be posted with a delay (notably,  MSG_RESUME_SUGGESTIONS)
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
     }
 
@@ -219,8 +242,8 @@
         mLatinIME.mHandler.removeAllMessages();
         setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, mPreviousBigramPredictionSettings,
                 true /* defaultValue */);
-        setStringPreference(Settings.PREF_AUTO_CORRECTION_THRESHOLD, mPreviousAutoCorrectSetting,
-                DEFAULT_AUTO_CORRECTION_THRESHOLD);
+        setBooleanPreference(Settings.PREF_AUTO_CORRECTION, mPreviousAutoCorrectSetting,
+                DEFAULT_AUTO_CORRECTION);
         setDebugMode(false);
         mLatinIME.recycle();
         super.tearDown();
@@ -236,7 +259,7 @@
     // Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
     // is called, which has a lot of bad side effects. We can however just throw an exception
     // in the runnable which will unwind the stack and allow us to exit.
-    private final class InterruptRunMessagesException extends RuntimeException {
+    final class InterruptRunMessagesException extends RuntimeException {
         // Empty class
     }
     protected void runMessages() {
@@ -263,14 +286,16 @@
         // but keep them in mind if something breaks. Commenting them out as is should work.
         //mLatinIME.onPressKey(codePoint, 0 /* repeatCount */, true /* isSinglePointer */);
         final Key key = mKeyboard.getKey(codePoint);
+        final Event event;
         if (key == null) {
-            mLatinIME.onCodeInput(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
-                    isKeyRepeat);
+            event = Event.createSoftwareKeypressEvent(codePoint, Event.NOT_A_KEY_CODE,
+                    Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, isKeyRepeat);
         } else {
             final int x = key.getX() + key.getWidth() / 2;
             final int y = key.getY() + key.getHeight() / 2;
-            mLatinIME.onCodeInput(codePoint, x, y, isKeyRepeat);
+            event = LatinIME.createSoftwareKeypressEvent(codePoint, x, y, isKeyRepeat);
         }
+        mLatinIME.onEvent(event);
         // Also see the comment at the top of this function about onReleaseKey
         //mLatinIME.onReleaseKey(codePoint, false /* withSliding */);
     }
@@ -289,6 +314,46 @@
         }
     }
 
+    protected Point getXY(final int codePoint) {
+        final Key key = mKeyboard.getKey(codePoint);
+        if (key == null) {
+            throw new RuntimeException("Code point not on the keyboard");
+        }
+        return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
+    }
+
+    protected void gesture(final String stringToGesture) {
+        if (StringUtils.codePointCount(stringToGesture) < 2) {
+            throw new RuntimeException("Can't gesture strings less than 2 chars long");
+        }
+
+        mLatinIME.onStartBatchInput();
+        final int startCodePoint = stringToGesture.codePointAt(0);
+        Point oldPoint = getXY(startCodePoint);
+        int timestamp = 0; // In milliseconds since the start of the gesture
+        final InputPointers pointers = new InputPointers(Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
+        pointers.addPointer(oldPoint.x, oldPoint.y, 0 /* pointerId */, timestamp);
+
+        for (int i = Character.charCount(startCodePoint); i < stringToGesture.length();
+                i = stringToGesture.offsetByCodePoints(i, 1)) {
+            final Point newPoint = getXY(stringToGesture.codePointAt(i));
+            // Arbitrarily 0.5s between letters and 0.1 between events. Refine this later if needed.
+            final int STEPS = 5;
+            for (int j = 0; j < STEPS; ++j) {
+                timestamp += 100;
+                pointers.addPointer(oldPoint.x + ((newPoint.x - oldPoint.x) * j) / STEPS,
+                        oldPoint.y + ((newPoint.y - oldPoint.y) * j) / STEPS,
+                        0 /* pointerId */, timestamp);
+            }
+            oldPoint.x = newPoint.x;
+            oldPoint.y = newPoint.y;
+            mLatinIME.onUpdateBatchInput(pointers);
+        }
+        mLatinIME.onEndBatchInput(pointers);
+        sleep(DELAY_TO_WAIT_FOR_GESTURE_MILLIS);
+        runMessages();
+    }
+
     protected void waitForDictionariesToBeLoaded() {
         try {
             mLatinIME.waitForLoadingDictionaries(
@@ -329,7 +394,7 @@
                 false /* isAuxiliary */,
                 false /* overridesImplicitlyEnabledSubtype */,
                 0 /* id */);
-        SubtypeSwitcher.getInstance().forceSubtype(subtype);
+        RichInputMethodManager.forceSubtype(subtype);
         mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
         runMessages();
         mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();
@@ -346,8 +411,9 @@
     }
 
     protected void pickSuggestionManually(final String suggestion) {
-        mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion, 1,
-                SuggestedWordInfo.KIND_CORRECTION, null /* sourceDict */,
+        mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion,
+                "" /* prevWordsContext */, 1 /* score */,
+                SuggestedWordInfo.KIND_CORRECTION, DICTIONARY_TEST,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                 SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
     }
@@ -358,4 +424,40 @@
             Thread.sleep(milliseconds);
         } catch (InterruptedException e) {}
     }
+
+    // Some helper methods to manage the mock cursor position
+    // DO NOT CALL LatinIME#onUpdateSelection IF YOU WANT TO USE THOSE
+    int mLastCursorPos = 0;
+    /**
+     * Move the cached cursor position to the passed position and send onUpdateSelection to LatinIME
+     */
+    protected int sendUpdateForCursorMoveTo(final int position) {
+        mInputConnection.setSelection(position, position);
+        mLatinIME.onUpdateSelection(mLastCursorPos, mLastCursorPos, position, position, -1, -1);
+        mLastCursorPos = position;
+        return position;
+    }
+
+    /**
+     * Move the cached cursor position by the passed amount and send onUpdateSelection to LatinIME
+     */
+    protected int sendUpdateForCursorMoveBy(final int offset) {
+        final int lastPos = mEditText.getText().length();
+        final int requestedPosition = mLastCursorPos + offset;
+        if (requestedPosition < 0) {
+            return sendUpdateForCursorMoveTo(0);
+        } else if (requestedPosition > lastPos) {
+            return sendUpdateForCursorMoveTo(lastPos);
+        } else {
+            return sendUpdateForCursorMoveTo(requestedPosition);
+        }
+    }
+
+    /**
+     * Move the cached cursor position to the end of the line and send onUpdateSelection to LatinIME
+     */
+    protected int sendUpdateForCursorMoveToEndOfLine() {
+        final int lastPos = mEditText.getText().length();
+        return sendUpdateForCursorMoveTo(lastPos);
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java b/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
index e47c557..035c8d7 100644
--- a/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinIMEForTests.java
@@ -21,4 +21,16 @@
     public boolean isInputViewShown() {
         return true;
     }
+
+    private boolean deallocateMemoryWasPerformed = false;
+
+    @Override
+    protected void deallocateMemory() {
+        super.deallocateMemory();
+        deallocateMemoryWasPerformed = true;
+    }
+
+    public boolean getDeallocateMemoryWasPerformed() {
+        return deallocateMemoryWasPerformed;
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
index f5e993d..22114b7 100644
--- a/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
+++ b/tests/src/com/android/inputmethod/latin/LatinImeStressTests.java
@@ -18,7 +18,7 @@
 
 import android.test.suitebuilder.annotation.LargeTest;
 
-import com.android.inputmethod.latin.makedict.CodePointUtils;
+import com.android.inputmethod.latin.common.CodePointUtils;
 
 import java.util.Random;
 
diff --git a/tests/src/com/android/inputmethod/latin/LatinImeTests.java b/tests/src/com/android/inputmethod/latin/LatinImeTests.java
new file mode 100644
index 0000000..c6f6313
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/LatinImeTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+@LargeTest
+public class LatinImeTests extends InputTestsBase {
+    public void testDeferredDeallocation_doesntHappenBeforeTimeout() {
+        mLatinIME.mHandler.onFinishInputView(true);
+        runMessages();
+        sleep(1000); // 1s
+        runMessages();
+        assertFalse("memory deallocation performed before timeout passed",
+                ((LatinIMEForTests)mLatinIME).getDeallocateMemoryWasPerformed());
+    }
+
+    public void testDeferredDeallocation_doesHappenAfterTimeout() {
+        mLatinIME.mHandler.onFinishInputView(true);
+        runMessages();
+        sleep(11000); // 11s (timeout is at 10s)
+        runMessages();
+        assertTrue("memory deallocation not performed although timeout passed",
+                ((LatinIMEForTests)mLatinIME).getDeallocateMemoryWasPerformed());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/NgramContextTests.java b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
new file mode 100644
index 0000000..0a662db
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/NgramContextTests.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 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;
+
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+import com.android.inputmethod.latin.utils.NgramContextUtils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class NgramContextTests extends AndroidTestCase {
+    public void testConstruct() {
+        assertEquals(new NgramContext(new WordInfo("a")), new NgramContext(new WordInfo("a")));
+        assertEquals(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO),
+                new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO));
+        assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
+                new NgramContext(WordInfo.EMPTY_WORD_INFO));
+        assertEquals(new NgramContext(WordInfo.EMPTY_WORD_INFO),
+                new NgramContext(WordInfo.EMPTY_WORD_INFO));
+    }
+
+    public void testIsBeginningOfSentenceContext() {
+        assertFalse(new NgramContext().isBeginningOfSentenceContext());
+        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+                .isBeginningOfSentenceContext());
+        assertTrue(NgramContext.BEGINNING_OF_SENTENCE.isBeginningOfSentenceContext());
+        assertFalse(new NgramContext(new WordInfo("a")).isBeginningOfSentenceContext());
+        assertFalse(new NgramContext(new WordInfo("")).isBeginningOfSentenceContext());
+        assertFalse(new NgramContext(WordInfo.EMPTY_WORD_INFO).isBeginningOfSentenceContext());
+        assertTrue(new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO, new WordInfo("a"))
+                .isBeginningOfSentenceContext());
+        assertFalse(new NgramContext(new WordInfo("a"), WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+                .isBeginningOfSentenceContext());
+        assertFalse(new NgramContext(
+                WordInfo.EMPTY_WORD_INFO, WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO)
+                .isBeginningOfSentenceContext());
+    }
+
+    public void testGetNextNgramContext() {
+        final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+        final NgramContext ngramContext_b_a =
+                ngramContext_a.getNextNgramContext(new WordInfo("b"));
+        assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+        assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+        final NgramContext ngramContext_bos_b =
+                ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+        assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+        final NgramContext ngramContext_c_bos =
+                ngramContext_b_a.getNextNgramContext(new WordInfo("c"));
+        assertEquals("c", ngramContext_c_bos.getNthPrevWord(1));
+    }
+
+    public void testExtractPrevWordsContextTest() {
+        final NgramContext ngramContext_bos =
+                new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        assertEquals("<S>", ngramContext_bos.extractPrevWordsContext());
+        final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+        final NgramContext ngramContext_b_a =
+                ngramContext_a.getNextNgramContext(new WordInfo("b"));
+        assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+        assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+        assertEquals("a b", ngramContext_b_a.extractPrevWordsContext());
+
+        final NgramContext ngramContext_bos_b =
+                ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+        assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+        assertEquals("a b <S>", ngramContext_bos_b.extractPrevWordsContext());
+
+        final NgramContext ngramContext_empty = new NgramContext(WordInfo.EMPTY_WORD_INFO);
+        assertEquals("", ngramContext_empty.extractPrevWordsContext());
+        final NgramContext ngramContext_a_empty =
+                ngramContext_empty.getNextNgramContext(new WordInfo("a"));
+        assertEquals("a", ngramContext_a_empty.getNthPrevWord(1));
+        assertEquals("a", ngramContext_a_empty.extractPrevWordsContext());
+    }
+
+    public void testExtractPrevWordsContextArray() {
+        final NgramContext ngramContext_bos =
+                new NgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        assertEquals("<S>", ngramContext_bos.extractPrevWordsContext());
+        assertEquals(1, ngramContext_bos.extractPrevWordsContextArray().length);
+        final NgramContext ngramContext_a = new NgramContext(new WordInfo("a"));
+        final NgramContext ngramContext_b_a =
+                ngramContext_a.getNextNgramContext(new WordInfo("b"));
+        assertEquals(2, ngramContext_b_a.extractPrevWordsContextArray().length);
+        assertEquals("b", ngramContext_b_a.getNthPrevWord(1));
+        assertEquals("a", ngramContext_b_a.getNthPrevWord(2));
+        assertEquals("a", ngramContext_b_a.extractPrevWordsContextArray()[0]);
+        assertEquals("b", ngramContext_b_a.extractPrevWordsContextArray()[1]);
+
+        final NgramContext ngramContext_bos_b =
+                ngramContext_b_a.getNextNgramContext(WordInfo.BEGINNING_OF_SENTENCE_WORD_INFO);
+        assertTrue(ngramContext_bos_b.isBeginningOfSentenceContext());
+        assertEquals(3, ngramContext_bos_b.extractPrevWordsContextArray().length);
+        assertEquals("b", ngramContext_bos_b.getNthPrevWord(2));
+        assertEquals("a", ngramContext_bos_b.extractPrevWordsContextArray()[0]);
+        assertEquals("b", ngramContext_bos_b.extractPrevWordsContextArray()[1]);
+        assertEquals("<S>", ngramContext_bos_b.extractPrevWordsContextArray()[2]);
+
+        final NgramContext ngramContext_empty = new NgramContext(WordInfo.EMPTY_WORD_INFO);
+        assertEquals(0, ngramContext_empty.extractPrevWordsContextArray().length);
+        final NgramContext ngramContext_a_empty =
+                ngramContext_empty.getNextNgramContext(new WordInfo("a"));
+        assertEquals(1, ngramContext_a_empty.extractPrevWordsContextArray().length);
+        assertEquals("a", ngramContext_a_empty.extractPrevWordsContextArray()[0]);
+    }
+
+    public void testGetNgramContextFromNthPreviousWord() {
+        SpacingAndPunctuations spacingAndPunctuations = new SpacingAndPunctuations(
+                mContext.getResources());
+        assertEquals("<S>", NgramContextUtils.getNgramContextFromNthPreviousWord("",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a. b ",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a? b ",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a! b ",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertEquals("<S> b", NgramContextUtils.getNgramContextFromNthPreviousWord("a\nb ",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertEquals("<S> a b", NgramContextUtils.getNgramContextFromNthPreviousWord("a b ",
+                spacingAndPunctuations, 1).extractPrevWordsContext());
+        assertFalse(NgramContextUtils
+                .getNgramContextFromNthPreviousWord("a b c d e", spacingAndPunctuations, 1)
+                .extractPrevWordsContext().startsWith("<S>"));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
index 64750fb..3537918 100644
--- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java
+++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
@@ -38,7 +38,7 @@
         try {
             mLatinIME.loadSettings();
             type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+            sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
             runMessages();
             assertTrue("type word then type space should display punctuation strip",
                     mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
index f9d7226..08779b9 100644
--- a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
+++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
@@ -30,12 +30,12 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputConnectionWrapper;
 
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.PrevWordsInfoUtils;
+import com.android.inputmethod.latin.utils.NgramContextUtils;
 import com.android.inputmethod.latin.utils.RunInLocale;
 import com.android.inputmethod.latin.utils.ScriptUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
 import java.util.Locale;
@@ -137,7 +137,7 @@
         }
     }
 
-    private class MockInputMethodService extends InputMethodService {
+    static class MockInputMethodService extends InputMethodService {
         private MockConnection mMockConnection;
         public void setInputConnection(final MockConnection mockConnection) {
             mMockConnection = mockConnection;
@@ -158,26 +158,25 @@
      */
     public void testGetPreviousWord() {
         // If one of the following cases breaks, the bigram suggestions won't work.
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc. def", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc. def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
 
-        assertFalse(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence);
-        assertTrue(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mIsBeginningOfSentence);
+        assertFalse(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
+        assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
 
         // For n-gram
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[1].mWord, "abc");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 2).mPrevWordsInfo[1],
-                WordInfo.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(2), "abc");
+        assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 2).isNthPrevWordBeginningOfSentence(2));
 
         // The following tests reflect the current behavior of the function
         // RichInputConnection#getNthPreviousWord.
@@ -186,33 +185,37 @@
         // this function if needed - especially since it does not seem very
         // logical. These tests are just there to catch any unintentional
         // changes in the behavior of the RichInputConnection#getPreviousWord method.
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def ", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def.", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "abc");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def .", mSpacingAndPunctuations, 2).mPrevWordsInfo[0].mWord, "def");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc ", mSpacingAndPunctuations, 2), PrevWordsInfo.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def ", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def.", mSpacingAndPunctuations, 2).getNthPrevWord(1), "abc");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def .", mSpacingAndPunctuations, 2).getNthPrevWord(1), "def");
+        assertTrue(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc ", mSpacingAndPunctuations, 2).isBeginningOfSentenceContext());
 
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def ", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "def");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc 'def", mSpacingAndPunctuations, 1).mPrevWordsInfo[0].mWord, "'def");
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def.", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc def .", mSpacingAndPunctuations, 1), PrevWordsInfo.BEGINNING_OF_SENTENCE);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc, def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc? def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc! def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
-        assertEquals(PrevWordsInfoUtils.getPrevWordsInfoFromNthPreviousWord(
-                "abc 'def", mSpacingAndPunctuations, 2), PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def ", mSpacingAndPunctuations, 1).getNthPrevWord(1), "def");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc 'def", mSpacingAndPunctuations, 1).getNthPrevWord(1), "'def");
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def.", mSpacingAndPunctuations, 1), NgramContext.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc def .", mSpacingAndPunctuations, 1), NgramContext.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc, def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
+        // question mark is treated as the end of the sentence. Hence, beginning of the
+        // sentence is expected.
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc? def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+        // Exclamation mark is treated as the end of the sentence. Hence, beginning of the
+        // sentence is expected.
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc! def", mSpacingAndPunctuations, 2), NgramContext.BEGINNING_OF_SENTENCE);
+        assertEquals(NgramContextUtils.getNgramContextFromNthPreviousWord(
+                "abc 'def", mSpacingAndPunctuations, 2), NgramContext.EMPTY_PREV_WORDS_INFO);
     }
 
     public void testGetWordRangeAtCursor() {
@@ -223,7 +226,6 @@
                 mSpacingAndPunctuations, new int[] { Constants.CODE_SPACE });
         final SpacingAndPunctuations TAB = new SpacingAndPunctuations(
                 mSpacingAndPunctuations, new int[] { Constants.CODE_TAB });
-        final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
         // A character that needs surrogate pair to represent its code point (U+2008A).
         final String SUPPLEMENTARY_CHAR_STRING = "\uD840\uDC8A";
         final SpacingAndPunctuations SUPPLEMENTARY_CHAR = new SpacingAndPunctuations(
diff --git a/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java b/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java
new file mode 100644
index 0000000..af94be6
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/RichInputMethodSubtypeTests.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+@SmallTest
+public class RichInputMethodSubtypeTests extends AndroidTestCase {
+    // All input method subtypes of LatinIME.
+    private final ArrayList<RichInputMethodSubtype> mSubtypesList = new ArrayList<>();
+
+    private RichInputMethodManager mRichImm;
+    private Resources mRes;
+    private InputMethodSubtype mSavedAddtionalSubtypes[];
+
+    RichInputMethodSubtype EN_US;
+    RichInputMethodSubtype EN_GB;
+    RichInputMethodSubtype ES_US;
+    RichInputMethodSubtype FR;
+    RichInputMethodSubtype FR_CA;
+    RichInputMethodSubtype FR_CH;
+    RichInputMethodSubtype DE;
+    RichInputMethodSubtype DE_CH;
+    RichInputMethodSubtype HI;
+    RichInputMethodSubtype SR;
+    RichInputMethodSubtype ZZ;
+    RichInputMethodSubtype DE_QWERTY;
+    RichInputMethodSubtype FR_QWERTZ;
+    RichInputMethodSubtype EN_US_AZERTY;
+    RichInputMethodSubtype EN_UK_DVORAK;
+    RichInputMethodSubtype ES_US_COLEMAK;
+    RichInputMethodSubtype ZZ_AZERTY;
+    RichInputMethodSubtype ZZ_PC;
+
+    // These are preliminary subtypes and may not exist.
+    RichInputMethodSubtype HI_LATN; // Hinglish
+    RichInputMethodSubtype SR_LATN; // Serbian Latin
+    RichInputMethodSubtype HI_LATN_DVORAK;
+    RichInputMethodSubtype SR_LATN_QWERTY;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getContext();
+        mRes = context.getResources();
+        RichInputMethodManager.init(context);
+        mRichImm = RichInputMethodManager.getInstance();
+
+        // Save and reset additional subtypes
+        mSavedAddtionalSubtypes = mRichImm.getAdditionalSubtypes();
+        final InputMethodSubtype[] predefinedAddtionalSubtypes =
+                AdditionalSubtypeUtils.createAdditionalSubtypesArray(
+                        AdditionalSubtypeUtils.createPrefSubtypes(
+                                mRes.getStringArray(R.array.predefined_subtypes)));
+        mRichImm.setAdditionalInputMethodSubtypes(predefinedAddtionalSubtypes);
+
+        final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
+        final int subtypeCount = imi.getSubtypeCount();
+        for (int index = 0; index < subtypeCount; index++) {
+            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+            mSubtypesList.add(new RichInputMethodSubtype(subtype));
+        }
+
+        EN_US = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.US.toString(), "qwerty"));
+        EN_GB = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.UK.toString(), "qwerty"));
+        ES_US = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "es_US", "spanish"));
+        FR = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.FRENCH.toString(), "azerty"));
+        FR_CA = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.CANADA_FRENCH.toString(), "qwerty"));
+        FR_CH = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "fr_CH", "swiss"));
+        DE = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                Locale.GERMAN.toString(), "qwertz"));
+        DE_CH = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "de_CH", "swiss"));
+        HI = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "hi", "hindi"));
+        SR = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "sr", "south_slavic"));
+        ZZ = new RichInputMethodSubtype(mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"));
+        DE_QWERTY = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    Locale.GERMAN.toString(), "qwerty"));
+        FR_QWERTZ = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    Locale.FRENCH.toString(), "qwertz"));
+        EN_US_AZERTY = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    Locale.US.toString(), "azerty"));
+        EN_UK_DVORAK = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    Locale.UK.toString(), "dvorak"));
+        ES_US_COLEMAK = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    "es_US", "colemak"));
+        ZZ_AZERTY = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    SubtypeLocaleUtils.NO_LANGUAGE, "azerty"));
+        ZZ_PC = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty"));
+
+        final InputMethodSubtype hiLatn = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "hi_ZZ", "qwerty");
+        if (hiLatn != null) {
+            HI_LATN = new RichInputMethodSubtype(hiLatn);
+            HI_LATN_DVORAK = new RichInputMethodSubtype(
+                    AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                            "hi_ZZ", "dvorak"));
+        }
+        final InputMethodSubtype srLatn = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "sr_ZZ", "serbian_qwertz");
+        if (srLatn != null) {
+            SR_LATN = new RichInputMethodSubtype(srLatn);
+            SR_LATN_QWERTY = new RichInputMethodSubtype(
+                    AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                            "sr_ZZ", "qwerty"));
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Restore additional subtypes.
+        mRichImm.setAdditionalInputMethodSubtypes(mSavedAddtionalSubtypes);
+        super.tearDown();
+    }
+
+    public void testAllFullDisplayNameForSpacebar() {
+        for (final RichInputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocaleUtils
+                    .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+            final String spacebarText = subtype.getFullDisplayName();
+            final String languageName = SubtypeLocaleUtils
+                    .getSubtypeLocaleDisplayName(subtype.getLocale().toString());
+            if (subtype.isNoLanguage()) {
+                assertFalse(subtypeName, spacebarText.contains(languageName));
+            } else {
+                assertTrue(subtypeName, spacebarText.contains(languageName));
+            }
+        }
+    }
+
+   public void testAllMiddleDisplayNameForSpacebar() {
+        for (final RichInputMethodSubtype subtype : mSubtypesList) {
+            final String subtypeName = SubtypeLocaleUtils
+                    .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+            final Locale locale = subtype.getLocale();
+            final Locale displayLocale = SubtypeLocaleUtils.getDisplayLocaleOfSubtypeLocale(
+                    locale.toString());
+            if (Locale.ROOT.equals(displayLocale)) {
+                // Skip test because the language part of this locale string doesn't represent
+                // the locale to be displayed on the spacebar (for example Hinglish).
+                continue;
+            }
+            final String spacebarText = subtype.getMiddleDisplayName();
+            if (subtype.isNoLanguage()) {
+                assertEquals(subtypeName, SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(
+                        subtype.getRawSubtype()), spacebarText);
+            } else {
+                assertEquals(subtypeName,
+                        SubtypeLocaleUtils.getSubtypeLanguageDisplayName(locale.toString()),
+                        spacebarText);
+            }
+        }
+    }
+
+    // InputMethodSubtype's display name for spacebar text in its locale.
+    //               isAdditionalSubtype (T=true, F=false)
+    // locale layout         |  Middle     Full
+    // ------ -------------- - --------- ----------------------
+    //  en_US qwerty         F  English   English (US)           exception
+    //  en_GB qwerty         F  English   English (UK)           exception
+    //  es_US spanish        F  Español   Español (EE.UU.)       exception
+    //  fr    azerty         F  Français  Français
+    //  fr_CA qwerty         F  Français  Français (Canada)
+    //  fr_CH swiss          F  Français  Français (Suisse)
+    //  de    qwertz         F  Deutsch   Deutsch
+    //  de_CH swiss          F  Deutsch   Deutsch (Schweiz)
+    //  hi    hindi          F  हिन्दी       हिन्दी
+    //  hi_ZZ qwerty         F  Hinglish  Hinglish               exception
+    //  sr    south_slavic   F  Српски    Српски
+    //  sr_ZZ serbian_qwertz F  Srpski    Srpski                 exception
+    //  zz    qwerty         F  QWERTY    QWERTY
+    //  fr    qwertz         T  Français  Français
+    //  de    qwerty         T  Deutsch   Deutsch
+    //  en_US azerty         T  English   English (US)
+    //  en_GB dvorak         T  English   English (UK)
+    //  hi_ZZ dvorak         T  Hinglish  Hinglish               exception
+    //  sr_ZZ qwerty         T  Srpski    Srpski                 exception
+    //  zz    azerty         T  AZERTY    AZERTY
+
+    private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() {
+        @Override
+        protected Void job(final Resources res) {
+            assertEquals("en_US", "English (US)", EN_US.getFullDisplayName());
+            assertEquals("en_GB", "English (UK)", EN_GB.getFullDisplayName());
+            assertEquals("es_US", "Español (EE.UU.)", ES_US.getFullDisplayName());
+            assertEquals("fr", "Français", FR.getFullDisplayName());
+            assertEquals("fr_CA", "Français (Canada)", FR_CA.getFullDisplayName());
+            assertEquals("fr_CH", "Français (Suisse)", FR_CH.getFullDisplayName());
+            assertEquals("de", "Deutsch", DE.getFullDisplayName());
+            assertEquals("de_CH", "Deutsch (Schweiz)", DE_CH.getFullDisplayName());
+            assertEquals("hi", "हिन्दी", HI.getFullDisplayName());
+            assertEquals("sr", "Српски", SR.getFullDisplayName());
+            assertEquals("zz", "QWERTY", ZZ.getFullDisplayName());
+
+            assertEquals("en_US", "English", EN_US.getMiddleDisplayName());
+            assertEquals("en_GB", "English", EN_GB.getMiddleDisplayName());
+            assertEquals("es_US", "Español", ES_US.getMiddleDisplayName());
+            assertEquals("fr", "Français", FR.getMiddleDisplayName());
+            assertEquals("fr_CA", "Français", FR_CA.getMiddleDisplayName());
+            assertEquals("fr_CH", "Français", FR_CH.getMiddleDisplayName());
+            assertEquals("de", "Deutsch", DE.getMiddleDisplayName());
+            assertEquals("de_CH", "Deutsch", DE_CH.getMiddleDisplayName());
+            assertEquals("zz", "QWERTY", ZZ.getMiddleDisplayName());
+
+            // These are preliminary subtypes and may not exist.
+            if (HI_LATN != null) {
+                assertEquals("hi_ZZ", "Hinglish", HI_LATN.getFullDisplayName());
+                assertEquals("hi_ZZ", "Hinglish", HI_LATN.getMiddleDisplayName());
+            }
+            if (SR_LATN != null) {
+                assertEquals("sr_ZZ", "Srpski", SR_LATN.getFullDisplayName());
+                assertEquals("sr_ZZ", "Srpski", SR_LATN.getMiddleDisplayName());
+            }
+            return null;
+        }
+    };
+
+    private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
+        @Override
+        protected Void job(final Resources res) {
+            assertEquals("fr qwertz", "Français", FR_QWERTZ.getFullDisplayName());
+            assertEquals("de qwerty", "Deutsch", DE_QWERTY.getFullDisplayName());
+            assertEquals("en_US azerty", "English (US)", EN_US_AZERTY.getFullDisplayName());
+            assertEquals("en_UK dvorak", "English (UK)", EN_UK_DVORAK.getFullDisplayName());
+            assertEquals("es_US colemak", "Español (EE.UU.)", ES_US_COLEMAK.getFullDisplayName());
+            assertEquals("zz azerty", "AZERTY", ZZ_AZERTY.getFullDisplayName());
+            assertEquals("zz pc", "PC", ZZ_PC.getFullDisplayName());
+
+            assertEquals("fr qwertz", "Français", FR_QWERTZ.getMiddleDisplayName());
+            assertEquals("de qwerty", "Deutsch", DE_QWERTY.getMiddleDisplayName());
+            assertEquals("en_US azerty", "English", EN_US_AZERTY.getMiddleDisplayName());
+            assertEquals("en_UK dvorak", "English", EN_UK_DVORAK.getMiddleDisplayName());
+            assertEquals("es_US colemak", "Español", ES_US_COLEMAK.getMiddleDisplayName());
+            assertEquals("zz azerty", "AZERTY", ZZ_AZERTY.getMiddleDisplayName());
+            assertEquals("zz pc", "PC", ZZ_PC.getMiddleDisplayName());
+
+            // These are preliminary subtypes and may not exist.
+            if (HI_LATN_DVORAK != null) {
+                assertEquals("hi_ZZ dvorak", "Hinglish", HI_LATN_DVORAK.getFullDisplayName());
+                assertEquals("hi_ZZ dvorak", "Hinglish", HI_LATN_DVORAK.getMiddleDisplayName());
+            }
+            if (SR_LATN_QWERTY != null) {
+                assertEquals("sr_ZZ qwerty", "Srpski", SR_LATN_QWERTY.getFullDisplayName());
+                assertEquals("sr_ZZ qwerty", "Srpski", SR_LATN_QWERTY.getMiddleDisplayName());
+            }
+            return null;
+        }
+    };
+
+    public void testPredefinedSubtypesForSpacebarInEnglish() {
+        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+    }
+
+    public void testAdditionalSubtypeForSpacebarInEnglish() {
+        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
+    }
+
+    public void testPredefinedSubtypesForSpacebarInFrench() {
+        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+    }
+
+    public void testAdditionalSubtypeForSpacebarInFrench() {
+        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
+    }
+
+    public void testRichInputMethodSubtypeForNullInputMethodSubtype() {
+        RichInputMethodSubtype subtype = RichInputMethodSubtype.getRichInputMethodSubtype(null);
+        assertNotNull(subtype);
+        assertEquals("zz", subtype.getRawSubtype().getLocale());
+        assertEquals("keyboard", subtype.getRawSubtype().getMode());
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index db3c9ba..59bb5f8 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -16,13 +16,11 @@
 
 package com.android.inputmethod.latin;
 
-import android.os.Build;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.view.inputmethod.EditorInfo;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.WordComposer;
+import com.android.inputmethod.latin.common.Constants;
 
 @LargeTest
 public class ShiftModeTests extends InputTestsBase {
@@ -75,7 +73,7 @@
             repeatKey(Constants.CODE_DELETE);
         }
         assertFalse("Caps immediately after repeating Backspace a lot", isCapsModeAutoShifted());
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
     }
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 869c550..d465ce6 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -37,7 +37,7 @@
     private static SuggestedWordInfo createTypedWordInfo(final String word) {
         // Use 100 as the frequency because the numerical value does not matter as
         // long as it's > 1 and < INT_MAX.
-        return new SuggestedWordInfo(word, 100 /* score */,
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 100 /* score */,
                 SuggestedWordInfo.KIND_TYPED,
                 null /* sourceDict */,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
@@ -52,49 +52,23 @@
      * @return a new instance of {@link SuggestedWordInfo}.
      */
     private static SuggestedWordInfo createCorrectionWordInfo(final String word) {
-        return new SuggestedWordInfo(word, 1 /* score */,
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 1 /* score */,
                 SuggestedWordInfo.KIND_CORRECTION,
                 null /* sourceDict */,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                 SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
     }
 
-    public void testGetSuggestedWordsExcludingTypedWord() {
-        final String TYPED_WORD = "typed";
-        final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
-        final int KIND_OF_SECOND_CORRECTION = SuggestedWordInfo.KIND_CORRECTION;
-        final ArrayList<SuggestedWordInfo> list = new ArrayList<>();
-        list.add(createTypedWordInfo(TYPED_WORD));
-        for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
-            list.add(createCorrectionWordInfo(Integer.toString(i)));
+    private static ArrayList<SuggestedWordInfo> createCorrectionWordInfos(final String... words) {
+        final ArrayList<SuggestedWordInfo> infos = new ArrayList<>();
+        for (final String word : words) {
+            infos.add(createCorrectionWordInfo(word));
         }
-
-        final SuggestedWords words = new SuggestedWords(
-                list, null /* rawSuggestions */,
-                false /* typedWordValid */,
-                false /* willAutoCorrect */,
-                false /* isObsoleteSuggestions */,
-                SuggestedWords.INPUT_STYLE_NONE);
-        assertEquals(NUMBER_OF_ADDED_SUGGESTIONS + 1, words.size());
-        assertEquals("typed", words.getWord(0));
-        assertTrue(words.getInfo(0).isKindOf(SuggestedWordInfo.KIND_TYPED));
-        assertEquals("0", words.getWord(1));
-        assertTrue(words.getInfo(1).isKindOf(KIND_OF_SECOND_CORRECTION));
-        assertEquals("4", words.getWord(5));
-        assertTrue(words.getInfo(5).isKindOf(KIND_OF_SECOND_CORRECTION));
-
-        final SuggestedWords wordsWithoutTyped =
-                words.getSuggestedWordsExcludingTypedWordForRecorrection();
-        // Make sure that the typed word has indeed been excluded, by testing the size of the
-        // suggested words, the string and the kind of the top suggestion, which should match
-        // the string and kind of what we inserted after the typed word.
-        assertEquals(words.size() - 1, wordsWithoutTyped.size());
-        assertEquals("0", wordsWithoutTyped.getWord(0));
-        assertTrue(wordsWithoutTyped.getInfo(0).isKindOf(KIND_OF_SECOND_CORRECTION));
+        return infos;
     }
 
     // Helper for testGetTransformedWordInfo
-    private SuggestedWordInfo transformWordInfo(final String info,
+    private static SuggestedWordInfo transformWordInfo(final String info,
             final int trailingSingleQuotesCount) {
         final SuggestedWordInfo suggestedWordInfo = createTypedWordInfo(info);
         final SuggestedWordInfo returnedWordInfo =
@@ -106,6 +80,30 @@
         return returnedWordInfo;
     }
 
+    public void testRemoveDupesNoDupes() {
+        final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "c");
+        assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
+        assertEquals(2, infos.size());
+    }
+
+    public void testRemoveDupesTypedWordNotDupe() {
+        final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "a", "c");
+        assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
+        assertEquals(2, infos.size());
+    }
+
+    public void testRemoveDupesTypedWordOnlyDupe() {
+        final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "c");
+        assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
+        assertEquals(2, infos.size());
+    }
+
+    public void testRemoveDupesTypedWordNotOnlyDupe() {
+        final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "b", "c");
+        assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
+        assertEquals(2, infos.size());
+    }
+
     public void testGetTransformedSuggestedWordInfo() {
         SuggestedWordInfo result = transformWordInfo("word", 0);
         assertEquals(result.mWord, "word");
@@ -123,9 +121,10 @@
 
     public void testGetTypedWordInfoOrNull() {
         final String TYPED_WORD = "typed";
+        final SuggestedWordInfo TYPED_WORD_INFO = createTypedWordInfo(TYPED_WORD);
         final int NUMBER_OF_ADDED_SUGGESTIONS = 5;
         final ArrayList<SuggestedWordInfo> list = new ArrayList<>();
-        list.add(createTypedWordInfo(TYPED_WORD));
+        list.add(TYPED_WORD_INFO);
         for (int i = 0; i < NUMBER_OF_ADDED_SUGGESTIONS; ++i) {
             list.add(createCorrectionWordInfo(Integer.toString(i)));
         }
@@ -133,30 +132,41 @@
         // Make sure getTypedWordInfoOrNull() returns non-null object.
         final SuggestedWords wordsWithTypedWord = new SuggestedWords(
                 list, null /* rawSuggestions */,
+                TYPED_WORD_INFO,
                 false /* typedWordValid */,
                 false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
-                SuggestedWords.INPUT_STYLE_NONE);
+                SuggestedWords.INPUT_STYLE_NONE,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
         final SuggestedWordInfo typedWord = wordsWithTypedWord.getTypedWordInfoOrNull();
         assertNotNull(typedWord);
         assertEquals(TYPED_WORD, typedWord.mWord);
 
-        // Make sure getTypedWordInfoOrNull() returns null.
-        final SuggestedWords wordsWithoutTypedWord =
-                wordsWithTypedWord.getSuggestedWordsExcludingTypedWordForRecorrection();
-        assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
-
-        // Make sure getTypedWordInfoOrNull() returns null.
-        assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
-
-        final SuggestedWords emptySuggestedWords = new SuggestedWords(
-                new ArrayList<SuggestedWordInfo>(), null /* rawSuggestions */,
+        // Make sure getTypedWordInfoOrNull() returns null when no typed word.
+        list.remove(0);
+        final SuggestedWords wordsWithoutTypedWord = new SuggestedWords(
+                list, null /* rawSuggestions */,
+                null /* typedWord */,
                 false /* typedWordValid */,
                 false /* willAutoCorrect */,
                 false /* isObsoleteSuggestions */,
-                SuggestedWords.INPUT_STYLE_NONE);
+                SuggestedWords.INPUT_STYLE_NONE,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
+        assertNull(wordsWithoutTypedWord.getTypedWordInfoOrNull());
+
+        // Make sure getTypedWordInfoOrNull() returns null.
+        assertNull(SuggestedWords.getEmptyInstance().getTypedWordInfoOrNull());
+
+        final SuggestedWords emptySuggestedWords = new SuggestedWords(
+                new ArrayList<SuggestedWordInfo>(), null /* rawSuggestions */,
+                null /* typedWord */,
+                false /* typedWordValid */,
+                false /* willAutoCorrect */,
+                false /* isObsoleteSuggestions */,
+                SuggestedWords.INPUT_STYLE_NONE,
+                SuggestedWords.NOT_A_SEQUENCE_NUMBER);
         assertNull(emptySuggestedWords.getTypedWordInfoOrNull());
 
-        assertNull(SuggestedWords.EMPTY.getTypedWordInfoOrNull());
+        assertNull(SuggestedWords.getEmptyInstance().getTypedWordInfoOrNull());
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/WordComposerTests.java b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
index c44544f..8ae475f 100644
--- a/tests/src/com/android/inputmethod/latin/WordComposerTests.java
+++ b/tests/src/com/android/inputmethod/latin/WordComposerTests.java
@@ -19,8 +19,9 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.StringUtils;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.StringUtils;
 
 /**
  * Unit tests for WordComposer.
diff --git a/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java b/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java
new file mode 100644
index 0000000..8328179
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiverTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 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.accounts;
+
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+
+import com.android.inputmethod.latin.settings.LocalSettingsConstants;
+
+/**
+ * Tests for {@link AccountsChangedReceiver}.
+ */
+public class AccountsChangedReceiverTests extends AndroidTestCase {
+    private static final String ACCOUNT_1 = "account1@example.com";
+    private static final String ACCOUNT_2 = "account2@example.com";
+
+    private SharedPreferences mPrefs;
+    private String mLastKnownAccount = null;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+        // Keep track of the current account so that we restore it when the test finishes.
+        mLastKnownAccount = mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        // Restore the account that was present before running the test.
+        updateAccountName(mLastKnownAccount);
+    }
+
+    public void testUnknownIntent() {
+        updateAccountName(ACCOUNT_1);
+        AccountsChangedReceiver reciever = new AccountsChangedReceiver();
+        reciever.onReceive(getContext(), new Intent("some-random-action"));
+        // Account should *not* be removed from preferences.
+        assertAccountName(ACCOUNT_1);
+    }
+
+    public void testAccountRemoved() {
+        updateAccountName(ACCOUNT_1);
+        AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+            @Override
+            protected String[] getAccountsForLogin(Context context) {
+                return new String[] {ACCOUNT_2};
+            }
+        };
+        reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+        // Account should be removed from preferences.
+        assertAccountName(null);
+    }
+
+    public void testAccountRemoved_noAccounts() {
+        updateAccountName(ACCOUNT_2);
+        AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+            @Override
+            protected String[] getAccountsForLogin(Context context) {
+                return new String[0];
+            }
+        };
+        reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+        // Account should be removed from preferences.
+        assertAccountName(null);
+    }
+
+    public void testAccountNotRemoved() {
+        updateAccountName(ACCOUNT_2);
+        AccountsChangedReceiver reciever = new AccountsChangedReceiver() {
+            @Override
+            protected String[] getAccountsForLogin(Context context) {
+                return new String[] {ACCOUNT_1, ACCOUNT_2};
+            }
+        };
+        reciever.onReceive(getContext(), new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+        // Account should *not* be removed from preferences.
+        assertAccountName(ACCOUNT_2);
+    }
+
+    private void updateAccountName(String accountName) {
+        if (accountName == null) {
+            mPrefs.edit().remove(LocalSettingsConstants.PREF_ACCOUNT_NAME).apply();
+        } else {
+            mPrefs.edit().putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, accountName).apply();
+        }
+    }
+
+    private void assertAccountName(String expectedAccountName) {
+        assertEquals(expectedAccountName,
+                mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/common/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/common/InputPointersTests.java
new file mode 100644
index 0000000..6b3490d
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/common/InputPointersTests.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Arrays;
+
+@SmallTest
+public class InputPointersTests extends AndroidTestCase {
+    private static final int DEFAULT_CAPACITY = 48;
+
+    public void testNewInstance() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        assertEquals("new instance size", 0, src.getPointerSize());
+        assertNotNull("new instance xCoordinates", src.getXCoordinates());
+        assertNotNull("new instance yCoordinates", src.getYCoordinates());
+        assertNotNull("new instance pointerIds", src.getPointerIds());
+        assertNotNull("new instance times", src.getTimes());
+    }
+
+    public void testReset() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int[] xCoordinates = src.getXCoordinates();
+        final int[] yCoordinates = src.getXCoordinates();
+        final int[] pointerIds = src.getXCoordinates();
+        final int[] times = src.getXCoordinates();
+
+        src.reset();
+        assertEquals("size after reset", 0, src.getPointerSize());
+        assertNotSame("xCoordinates after reset", xCoordinates, src.getXCoordinates());
+        assertNotSame("yCoordinates after reset", yCoordinates, src.getYCoordinates());
+        assertNotSame("pointerIds after reset", pointerIds, src.getPointerIds());
+        assertNotSame("times after reset", times, src.getTimes());
+    }
+
+    public void testAdd() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int limit = src.getXCoordinates().length * 2 + 10;
+        for (int i = 0; i < limit; i++) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
+            assertEquals("size after add " + i, i + 1, src.getPointerSize());
+        }
+        for (int i = 0; i < limit; i++) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
+        }
+    }
+
+    public void testAddAt() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int limit = 1000, step = 100;
+        for (int i = 0; i < limit; i += step) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointerAt(i, x, y, pointerId, time);
+            assertEquals("size after add at " + i, i + 1, src.getPointerSize());
+        }
+        for (int i = 0; i < limit; i += step) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
+        }
+    }
+
+    public void testSet() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int limit = src.getXCoordinates().length * 2 + 10;
+        for (int i = 0; i < limit; i++) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
+        }
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
+        dst.set(src);
+        assertEquals("size after set", dst.getPointerSize(), src.getPointerSize());
+        assertSame("xCoordinates after set", dst.getXCoordinates(), src.getXCoordinates());
+        assertSame("yCoordinates after set", dst.getYCoordinates(), src.getYCoordinates());
+        assertSame("pointerIds after set", dst.getPointerIds(), src.getPointerIds());
+        assertSame("times after set", dst.getTimes(), src.getTimes());
+    }
+
+    public void testCopy() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int limit = 100;
+        for (int i = 0; i < limit; i++) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
+        }
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
+        dst.copy(src);
+        assertEquals("size after copy", dst.getPointerSize(), src.getPointerSize());
+        assertNotSame("xCoordinates after copy", dst.getXCoordinates(), src.getXCoordinates());
+        assertNotSame("yCoordinates after copy", dst.getYCoordinates(), src.getYCoordinates());
+        assertNotSame("pointerIds after copy", dst.getPointerIds(), src.getPointerIds());
+        assertNotSame("times after copy", dst.getTimes(), src.getTimes());
+        final int size = dst.getPointerSize();
+        assertIntArrayEquals("xCoordinates values after copy",
+                dst.getXCoordinates(), 0, src.getXCoordinates(), 0, size);
+        assertIntArrayEquals("yCoordinates values after copy",
+                dst.getYCoordinates(), 0, src.getYCoordinates(), 0, size);
+        assertIntArrayEquals("pointerIds values after copy",
+                dst.getPointerIds(), 0, src.getPointerIds(), 0, size);
+        assertIntArrayEquals("times values after copy",
+                dst.getTimes(), 0, src.getTimes(), 0, size);
+    }
+
+    public void testAppend() {
+        final int dstLength = 50;
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
+        for (int i = 0; i < dstLength; i++) {
+            final int x = i * 4;
+            final int y = i * 3;
+            final int pointerId = i * 2;
+            final int time = i;
+            dst.addPointer(x, y, pointerId, time);
+        }
+        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
+        dstCopy.copy(dst);
+
+        final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcYCoords = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcPointerIds = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int srcLength = 100;
+        final int srcPointerId = 10;
+        for (int i = 0; i < srcLength; i++) {
+            final int x = i;
+            final int y = i * 2;
+            // The time value must be larger than <code>dst</code>.
+            final int time = i * 4 + dstLength;
+            srcXCoords.add(x);
+            srcYCoords.add(y);
+            srcPointerIds.add(srcPointerId);
+            srcTimes.add(time);
+        }
+
+        final int startPos = 0;
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
+                startPos, 0 /* length */);
+        assertEquals("size after append zero", dstLength, dst.getPointerSize());
+        assertIntArrayEquals("xCoordinates after append zero",
+                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
+        assertIntArrayEquals("yCoordinates after append zero",
+                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
+        assertIntArrayEquals("pointerIds after append zero",
+                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
+        assertIntArrayEquals("times after append zero",
+                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
+
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords,
+                startPos, srcLength);
+        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
+        assertTrue("primitive length after append",
+                dst.getPointerIds().length >= dstLength + srcLength);
+        assertIntArrayEquals("original xCoordinates values after append",
+                dstCopy.getXCoordinates(), startPos, dst.getXCoordinates(), startPos, dstLength);
+        assertIntArrayEquals("original yCoordinates values after append",
+                dstCopy.getYCoordinates(), startPos, dst.getYCoordinates(), startPos, dstLength);
+        assertIntArrayEquals("original pointerIds values after append",
+                dstCopy.getPointerIds(), startPos, dst.getPointerIds(), startPos, dstLength);
+        assertIntArrayEquals("original times values after append",
+                dstCopy.getTimes(), startPos, dst.getTimes(), startPos, dstLength);
+        assertIntArrayEquals("appended xCoordinates values after append",
+                srcXCoords.getPrimitiveArray(), startPos, dst.getXCoordinates(),
+                dstLength, srcLength);
+        assertIntArrayEquals("appended yCoordinates values after append",
+                srcYCoords.getPrimitiveArray(), startPos, dst.getYCoordinates(),
+                dstLength, srcLength);
+        assertIntArrayEquals("appended pointerIds values after append",
+                srcPointerIds.getPrimitiveArray(), startPos, dst.getPointerIds(),
+                dstLength, srcLength);
+        assertIntArrayEquals("appended times values after append",
+                srcTimes.getPrimitiveArray(), startPos, dst.getTimes(), dstLength, srcLength);
+    }
+
+    public void testAppendResizableIntArray() {
+        final int dstLength = 50;
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
+        for (int i = 0; i < dstLength; i++) {
+            final int x = i * 4;
+            final int y = i * 3;
+            final int pointerId = i * 2;
+            final int time = i;
+            dst.addPointer(x, y, pointerId, time);
+        }
+        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
+        dstCopy.copy(dst);
+
+        final int srcLength = 100;
+        final int srcPointerId = 1;
+        final int[] srcPointerIds = new int[srcLength];
+        Arrays.fill(srcPointerIds, srcPointerId);
+        final ResizableIntArray srcTimes = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcXCoords = new ResizableIntArray(DEFAULT_CAPACITY);
+        final ResizableIntArray srcYCoords= new ResizableIntArray(DEFAULT_CAPACITY);
+        for (int i = 0; i < srcLength; i++) {
+            // The time value must be larger than <code>dst</code>.
+            final int time = i * 2 + dstLength;
+            final int x = i * 3;
+            final int y = i * 4;
+            srcTimes.add(time);
+            srcXCoords.add(x);
+            srcYCoords.add(y);
+        }
+
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, 0);
+        assertEquals("size after append zero", dstLength, dst.getPointerSize());
+        assertIntArrayEquals("xCoordinates after append zero",
+                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
+        assertIntArrayEquals("yCoordinates after append zero",
+                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
+        assertIntArrayEquals("pointerIds after append zero",
+                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
+        assertIntArrayEquals("times after append zero",
+                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
+
+        dst.append(srcPointerId, srcTimes, srcXCoords, srcYCoords, 0, srcLength);
+        assertEquals("size after append", dstLength + srcLength, dst.getPointerSize());
+        assertTrue("primitive length after append",
+                dst.getPointerIds().length >= dstLength + srcLength);
+        assertIntArrayEquals("original xCoordinates values after append",
+                dstCopy.getXCoordinates(), 0, dst.getXCoordinates(), 0, dstLength);
+        assertIntArrayEquals("original yCoordinates values after append",
+                dstCopy.getYCoordinates(), 0, dst.getYCoordinates(), 0, dstLength);
+        assertIntArrayEquals("original pointerIds values after append",
+                dstCopy.getPointerIds(), 0, dst.getPointerIds(), 0, dstLength);
+        assertIntArrayEquals("original times values after append",
+                dstCopy.getTimes(), 0, dst.getTimes(), 0, dstLength);
+        assertIntArrayEquals("appended xCoordinates values after append",
+                srcXCoords.getPrimitiveArray(), 0, dst.getXCoordinates(), dstLength, srcLength);
+        assertIntArrayEquals("appended yCoordinates values after append",
+                srcYCoords.getPrimitiveArray(), 0, dst.getYCoordinates(), dstLength, srcLength);
+        assertIntArrayEquals("appended pointerIds values after append",
+                srcPointerIds, 0, dst.getPointerIds(), dstLength, srcLength);
+        assertIntArrayEquals("appended times values after append",
+                srcTimes.getPrimitiveArray(), 0, dst.getTimes(), dstLength, srcLength);
+    }
+
+    // TODO: Consolidate this method with
+    // {@link ResizableIntArrayTests#assertIntArrayEquals(String,int[],int,int[],int,int)}.
+    private static void assertIntArrayEquals(final String message, final int[] expecteds,
+            final int expectedPos, final int[] actuals, final int actualPos, final int length) {
+        if (expecteds == actuals) {
+            return;
+        }
+        if (expecteds == null || actuals == null) {
+            assertEquals(message, Arrays.toString(expecteds), Arrays.toString(actuals));
+            return;
+        }
+        if (expecteds.length < expectedPos + length || actuals.length < actualPos + length) {
+            fail(message + ": insufficient length: expecteds=" + Arrays.toString(expecteds)
+                    + " actuals=" + Arrays.toString(actuals));
+            return;
+        }
+        for (int i = 0; i < length; i++) {
+            assertEquals(message + " [" + i + "]",
+                    expecteds[i + expectedPos], actuals[i + actualPos]);
+        }
+    }
+
+    public void testShift() {
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
+        final int limit = 100;
+        final int shiftAmount = 20;
+        for (int i = 0; i < limit; i++) {
+            final int x = i;
+            final int y = i * 2;
+            final int pointerId = i * 3;
+            final int time = i * 4;
+            src.addPointer(x, y, pointerId, time);
+        }
+        src.shift(shiftAmount);
+        assertEquals("length after shift", src.getPointerSize(), limit - shiftAmount);
+        for (int i = 0; i < limit - shiftAmount; ++i) {
+            final int oldIndex = i + shiftAmount;
+            final int x = oldIndex;
+            final int y = oldIndex * 2;
+            final int pointerId = oldIndex * 3;
+            final int time = oldIndex * 4;
+            assertEquals("xCoordinates at " + i, x, src.getXCoordinates()[i]);
+            assertEquals("yCoordinates at " + i, y, src.getYCoordinates()[i]);
+            assertEquals("pointerIds at " + i, pointerId, src.getPointerIds()[i]);
+            assertEquals("times at " + i, time, src.getTimes()[i]);
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java b/tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java
new file mode 100644
index 0000000..bd1629f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/common/ResizableIntArrayTests.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2012 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.common;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Arrays;
+
+@SmallTest
+public class ResizableIntArrayTests extends AndroidTestCase {
+    private static final int DEFAULT_CAPACITY = 48;
+
+    public void testNewInstance() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int[] array = src.getPrimitiveArray();
+        assertEquals("new instance length", 0, src.getLength());
+        assertNotNull("new instance array", array);
+        assertEquals("new instance array length", DEFAULT_CAPACITY, array.length);
+    }
+
+    public void testAdd() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int[] array = src.getPrimitiveArray();
+        int[] array2 = null, array3 = null;
+        final int limit = DEFAULT_CAPACITY * 2 + 10;
+        for (int i = 0; i < limit; i++) {
+            final int value = i;
+            src.add(value);
+            assertEquals("length after add " + i, i + 1, src.getLength());
+            if (i == DEFAULT_CAPACITY) {
+                array2 = src.getPrimitiveArray();
+            }
+            if (i == DEFAULT_CAPACITY * 2) {
+                array3 = src.getPrimitiveArray();
+            }
+            if (i < DEFAULT_CAPACITY) {
+                assertSame("array after add " + i, array, src.getPrimitiveArray());
+            } else if (i < DEFAULT_CAPACITY * 2) {
+                assertSame("array after add " + i, array2, src.getPrimitiveArray());
+            } else if (i < DEFAULT_CAPACITY * 3) {
+                assertSame("array after add " + i, array3, src.getPrimitiveArray());
+            }
+        }
+        for (int i = 0; i < limit; i++) {
+            final int value = i;
+            assertEquals("value at " + i, value, src.get(i));
+        }
+    }
+
+    public void testAddAt() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int limit = DEFAULT_CAPACITY * 10, step = DEFAULT_CAPACITY * 2;
+        for (int i = 0; i < limit; i += step) {
+            final int value = i;
+            src.addAt(i, value);
+            assertEquals("length after add at " + i, i + 1, src.getLength());
+        }
+        for (int i = 0; i < limit; i += step) {
+            final int value = i;
+            assertEquals("value at " + i, value, src.get(i));
+        }
+    }
+
+    public void testGet() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        try {
+            src.get(0);
+            fail("get(0) shouldn't succeed");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // success
+        }
+        try {
+            src.get(DEFAULT_CAPACITY);
+            fail("get(DEFAULT_CAPACITY) shouldn't succeed");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // success
+        }
+
+        final int index = DEFAULT_CAPACITY / 2;
+        final int valueAddAt = 100;
+        src.addAt(index, valueAddAt);
+        assertEquals("legth after add at " + index, index + 1, src.getLength());
+        assertEquals("value after add at " + index, valueAddAt, src.get(index));
+        assertEquals("value after add at 0", 0, src.get(0));
+        try {
+            src.get(src.getLength());
+            fail("get(length) shouldn't succeed");
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // success
+        }
+    }
+
+    public void testReset() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int[] array = src.getPrimitiveArray();
+        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+            final int value = i;
+            src.add(value);
+            assertEquals("length after add " + i, i + 1, src.getLength());
+        }
+
+        final int smallerLength = DEFAULT_CAPACITY / 2;
+        src.reset(smallerLength);
+        final int[] array2 = src.getPrimitiveArray();
+        assertEquals("length after reset", 0, src.getLength());
+        assertNotSame("array after reset", array, array2);
+
+        int[] array3 = null;
+        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+            final int value = i;
+            src.add(value);
+            assertEquals("length after add " + i, i + 1, src.getLength());
+            if (i == smallerLength) {
+                array3 = src.getPrimitiveArray();
+            }
+            if (i < smallerLength) {
+                assertSame("array after add " + i, array2, src.getPrimitiveArray());
+            } else if (i < smallerLength * 2) {
+                assertSame("array after add " + i, array3, src.getPrimitiveArray());
+            }
+        }
+    }
+
+    public void testSetLength() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int[] array = src.getPrimitiveArray();
+        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+            final int value = i;
+            src.add(value);
+            assertEquals("length after add " + i, i + 1, src.getLength());
+        }
+
+        final int largerLength = DEFAULT_CAPACITY * 2;
+        src.setLength(largerLength);
+        final int[] array2 = src.getPrimitiveArray();
+        assertEquals("length after larger setLength", largerLength, src.getLength());
+        assertNotSame("array after larger setLength", array, array2);
+        assertEquals("array length after larger setLength", largerLength, array2.length);
+        for (int i = 0; i < largerLength; i++) {
+            final int value = i;
+            if (i < DEFAULT_CAPACITY) {
+                assertEquals("value at " + i, value, src.get(i));
+            } else {
+                assertEquals("value at " + i, 0, src.get(i));
+            }
+        }
+
+        final int smallerLength = DEFAULT_CAPACITY / 2;
+        src.setLength(smallerLength);
+        final int[] array3 = src.getPrimitiveArray();
+        assertEquals("length after smaller setLength", smallerLength, src.getLength());
+        assertSame("array after smaller setLength", array2, array3);
+        assertEquals("array length after smaller setLength", largerLength, array3.length);
+        for (int i = 0; i < smallerLength; i++) {
+            final int value = i;
+            assertEquals("value at " + i, value, src.get(i));
+        }
+    }
+
+    public void testSet() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int limit = DEFAULT_CAPACITY * 2 + 10;
+        for (int i = 0; i < limit; i++) {
+            final int value = i;
+            src.add(value);
+        }
+
+        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY);
+        dst.set(src);
+        assertEquals("length after set", dst.getLength(), src.getLength());
+        assertSame("array after set", dst.getPrimitiveArray(), src.getPrimitiveArray());
+    }
+
+    public void testCopy() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+            final int value =  i;
+            src.add(value);
+        }
+
+        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int[] array = dst.getPrimitiveArray();
+        dst.copy(src);
+        assertEquals("length after copy", dst.getLength(), src.getLength());
+        assertSame("array after copy", array, dst.getPrimitiveArray());
+        assertNotSame("array after copy", dst.getPrimitiveArray(), src.getPrimitiveArray());
+        assertIntArrayEquals("values after copy",
+                dst.getPrimitiveArray(), 0, src.getPrimitiveArray(), 0, dst.getLength());
+
+        final int smallerLength = DEFAULT_CAPACITY / 2;
+        dst.reset(smallerLength);
+        final int[] array2 = dst.getPrimitiveArray();
+        dst.copy(src);
+        final int[] array3 = dst.getPrimitiveArray();
+        assertEquals("length after copy to smaller", dst.getLength(), src.getLength());
+        assertNotSame("array after copy to smaller", array2, array3);
+        assertNotSame("array after copy to smaller", array3, src.getPrimitiveArray());
+        assertIntArrayEquals("values after copy to smaller",
+                dst.getPrimitiveArray(), 0, src.getPrimitiveArray(), 0, dst.getLength());
+    }
+
+    public void testAppend() {
+        final int srcLength = DEFAULT_CAPACITY;
+        final ResizableIntArray src = new ResizableIntArray(srcLength);
+        for (int i = 0; i < srcLength; i++) {
+            final int value = i;
+            src.add(value);
+        }
+        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY * 2);
+        final int[] array = dst.getPrimitiveArray();
+        final int dstLength = DEFAULT_CAPACITY / 2;
+        for (int i = 0; i < dstLength; i++) {
+            final int value = -i - 1;
+            dst.add(value);
+        }
+        final ResizableIntArray dstCopy = new ResizableIntArray(dst.getLength());
+        dstCopy.copy(dst);
+
+        final int startPos = 0;
+        dst.append(src, startPos, 0 /* length */);
+        assertEquals("length after append zero", dstLength, dst.getLength());
+        assertSame("array after append zero", array, dst.getPrimitiveArray());
+        assertIntArrayEquals("values after append zero", dstCopy.getPrimitiveArray(), startPos,
+                dst.getPrimitiveArray(), startPos, dstLength);
+
+        dst.append(src, startPos, srcLength);
+        assertEquals("length after append", dstLength + srcLength, dst.getLength());
+        assertSame("array after append", array, dst.getPrimitiveArray());
+        assertTrue("primitive length after append",
+                dst.getPrimitiveArray().length >= dstLength + srcLength);
+        assertIntArrayEquals("original values after append", dstCopy.getPrimitiveArray(), startPos,
+                dst.getPrimitiveArray(), startPos, dstLength);
+        assertIntArrayEquals("appended values after append", src.getPrimitiveArray(), startPos,
+                dst.getPrimitiveArray(), dstLength, srcLength);
+
+        dst.append(src, startPos, srcLength);
+        assertEquals("length after 2nd append", dstLength + srcLength * 2, dst.getLength());
+        assertNotSame("array after 2nd append", array, dst.getPrimitiveArray());
+        assertTrue("primitive length after 2nd append",
+                dst.getPrimitiveArray().length >= dstLength + srcLength * 2);
+        assertIntArrayEquals("original values after 2nd append",
+                dstCopy.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), startPos,
+                dstLength);
+        assertIntArrayEquals("appended values after 2nd append",
+                src.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), dstLength,
+                srcLength);
+        assertIntArrayEquals("appended values after 2nd append",
+                src.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), dstLength + srcLength,
+                srcLength);
+    }
+
+    public void testFill() {
+        final int srcLength = DEFAULT_CAPACITY;
+        final ResizableIntArray src = new ResizableIntArray(srcLength);
+        for (int i = 0; i < srcLength; i++) {
+            final int value = i;
+            src.add(value);
+        }
+        final int[] array = src.getPrimitiveArray();
+
+        final int startPos = srcLength / 3;
+        final int length = srcLength / 3;
+        final int endPos = startPos + length;
+        assertTrue(startPos >= 1);
+        final int fillValue = 123;
+        try {
+            src.fill(fillValue, -1 /* startPos */, length);
+            fail("fill from -1 shouldn't succeed");
+        } catch (IllegalArgumentException e) {
+            // success
+        }
+        try {
+            src.fill(fillValue, startPos, -1 /* length */);
+            fail("fill negative length shouldn't succeed");
+        } catch (IllegalArgumentException e) {
+            // success
+        }
+
+        src.fill(fillValue, startPos, length);
+        assertEquals("length after fill", srcLength, src.getLength());
+        assertSame("array after fill", array, src.getPrimitiveArray());
+        for (int i = 0; i < srcLength; i++) {
+            final int value = i;
+            if (i >= startPos && i < endPos) {
+                assertEquals("new values after fill at " + i, fillValue, src.get(i));
+            } else {
+                assertEquals("unmodified values after fill at " + i, value, src.get(i));
+            }
+        }
+
+        final int length2 = srcLength * 2 - startPos;
+        final int largeEnd = startPos + length2;
+        assertTrue(largeEnd > srcLength);
+        final int fillValue2 = 456;
+        src.fill(fillValue2, startPos, length2);
+        assertEquals("length after large fill", largeEnd, src.getLength());
+        assertNotSame("array after large fill", array, src.getPrimitiveArray());
+        for (int i = 0; i < largeEnd; i++) {
+            final int value = i;
+            if (i >= startPos && i < largeEnd) {
+                assertEquals("new values after large fill at " + i, fillValue2, src.get(i));
+            } else {
+                assertEquals("unmodified values after large fill at " + i, value, src.get(i));
+            }
+        }
+
+        final int startPos2 = largeEnd + length2;
+        final int endPos2 = startPos2 + length2;
+        final int fillValue3 = 789;
+        src.fill(fillValue3, startPos2, length2);
+        assertEquals("length after disjoint fill", endPos2, src.getLength());
+        for (int i = 0; i < endPos2; i++) {
+            final int value = i;
+            if (i >= startPos2 && i < endPos2) {
+                assertEquals("new values after disjoint fill at " + i, fillValue3, src.get(i));
+            } else if (i >= startPos && i < largeEnd) {
+                assertEquals("unmodified values after disjoint fill at " + i,
+                        fillValue2, src.get(i));
+            } else if (i < startPos) {
+                assertEquals("unmodified values after disjoint fill at " + i, value, src.get(i));
+            } else {
+                assertEquals("gap values after disjoint fill at " + i, 0, src.get(i));
+            }
+        }
+    }
+
+    private static void assertIntArrayEquals(final String message, final int[] expecteds,
+            final int expectedPos, final int[] actuals, final int actualPos, final int length) {
+        if (expecteds == actuals) {
+            return;
+        }
+        if (expecteds == null || actuals == null) {
+            assertEquals(message, Arrays.toString(expecteds), Arrays.toString(actuals));
+            return;
+        }
+        if (expecteds.length < expectedPos + length || actuals.length < actualPos + length) {
+            fail(message + ": insufficient length: expecteds=" + Arrays.toString(expecteds)
+                    + " actuals=" + Arrays.toString(actuals));
+            return;
+        }
+        for (int i = 0; i < length; i++) {
+            assertEquals(message + " [" + i + "]",
+                    expecteds[i + expectedPos], actuals[i + actualPos]);
+        }
+    }
+
+    public void testShift() {
+        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
+        final int limit = DEFAULT_CAPACITY * 10;
+        final int shiftAmount = 20;
+        for (int i = 0; i < limit; ++i) {
+            final int value = i;
+            src.addAt(i, value);
+            assertEquals("length after add at " + i, i + 1, src.getLength());
+        }
+        src.shift(shiftAmount);
+        for (int i = 0; i < limit - shiftAmount; ++i) {
+            final int oldValue = i + shiftAmount;
+            assertEquals("value at " + i, oldValue, src.get(i));
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java
new file mode 100644
index 0000000..ec9d4be
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/common/StringUtilsTests.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2014 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.common;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Locale;
+
+@SmallTest
+public class StringUtilsTests extends AndroidTestCase {
+    private static final Locale US = Locale.US;
+    private static final Locale GERMAN = Locale.GERMAN;
+    private static final Locale TURKEY = new Locale("tr", "TR");
+    private static final Locale GREECE = new Locale("el", "GR");
+
+    private static void assert_toTitleCaseOfKeyLabel(final Locale locale,
+            final String lowerCase, final String expected) {
+        assertEquals(lowerCase + " in " + locale, expected,
+                StringUtils.toTitleCaseOfKeyLabel(lowerCase, locale));
+    }
+
+    public void test_toTitleCaseOfKeyLabel() {
+        assert_toTitleCaseOfKeyLabel(US, null, null);
+        assert_toTitleCaseOfKeyLabel(US, "", "");
+        assert_toTitleCaseOfKeyLabel(US, "aeiou", "AEIOU");
+        // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
+        // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
+        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
+        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+        // U+00C0: "À" LATIN CAPITAL LETTER A WITH GRAVE
+        // U+00C8: "È" LATIN CAPITAL LETTER E WITH GRAVE
+        // U+00CE: "Î" LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+        // U+00D6: "Ö" LATIN CAPITAL LETTER O WITH DIAERESIS
+        // U+016A: "Ū" LATIN CAPITAL LETTER U WITH MACRON
+        // U+00D1: "Ñ" LATIN CAPITAL LETTER N WITH TILDE
+        // U+00C7: "Ç" LATIN CAPITAL LETTER C WITH CEDILLA
+        assert_toTitleCaseOfKeyLabel(US,
+                "\u00E0\u00E8\u00EE\u00F6\u016B\u00F1\u00E7",
+                "\u00C0\u00C8\u00CE\u00D6\u016A\u00D1\u00C7");
+        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+        // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+        // U+0161: "š" LATIN SMALL LETTER S WITH CARON
+        // U+015A: "Ś" LATIN CAPITAL LETTER S WITH ACUTE
+        // U+0160: "Š" LATIN CAPITAL LETTER S WITH CARONZ
+        assert_toTitleCaseOfKeyLabel(GERMAN,
+                "\u00DF\u015B\u0161",
+                "SS\u015A\u0160");
+        // U+0259: "ə" LATIN SMALL LETTER SCHWA
+        // U+0069: "i" LATIN SMALL LETTER I
+        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+        // U+018F: "Ə" LATIN SMALL LETTER SCHWA
+        // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
+        // U+0049: "I" LATIN SMALL LETTER I
+        assert_toTitleCaseOfKeyLabel(TURKEY,
+                "\u0259\u0069\u0131",
+                "\u018F\u0130\u0049");
+        // U+03C3: "σ" GREEK SMALL LETTER SIGMA
+        // U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA
+        // U+03A3: "Σ" GREEK CAPITAL LETTER SIGMA
+        assert_toTitleCaseOfKeyLabel(GREECE,
+                "\u03C3\u03C2",
+                "\u03A3\u03A3");
+        // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
+        // U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS
+        // U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS
+        // U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
+        // U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS
+        // U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
+        // U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS
+        // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
+        // U+0388: "Έ" GREEK CAPITAL LETTER EPSILON WITH TONOS
+        // U+0389: "Ή" GREEK CAPITAL LETTER ETA WITH TONOS
+        // U+038A: "Ί" GREEK CAPITAL LETTER IOTA WITH TONOS
+        // U+038C: "Ό" GREEK CAPITAL LETTER OMICRON WITH TONOS
+        // U+038E: "Ύ" GREEK CAPITAL LETTER UPSILON WITH TONOS
+        // U+038F: "Ώ" GREEK CAPITAL LETTER OMEGA WITH TONOS
+        assert_toTitleCaseOfKeyLabel(GREECE,
+                "\u03AC\u03AD\u03AE\u03AF\u03CC\u03CD\u03CE",
+                "\u0386\u0388\u0389\u038A\u038C\u038E\u038F");
+        // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+        // U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+        // U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+        // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+        // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+        // U+03AB: "Ϋ" GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+        // U+0399: "Ι" GREEK CAPITAL LETTER IOTA
+        // U+03A5: "Υ" GREEK CAPITAL LETTER UPSILON
+        // U+0308: COMBINING DIAERESIS
+        // U+0301: COMBINING GRAVE ACCENT
+        assert_toTitleCaseOfKeyLabel(GREECE,
+                "\u03CA\u03CB\u0390\u03B0",
+                "\u03AA\u03AB\u0399\u0308\u0301\u03A5\u0308\u0301");
+    }
+
+    private static void assert_toTitleCaseOfKeyCode(final Locale locale, final int lowerCase,
+            final int expected) {
+        assertEquals(lowerCase + " in " + locale, expected,
+                StringUtils.toTitleCaseOfKeyCode(lowerCase, locale));
+    }
+
+    public void test_toTitleCaseOfKeyCode() {
+        assert_toTitleCaseOfKeyCode(US, Constants.CODE_ENTER, Constants.CODE_ENTER);
+        assert_toTitleCaseOfKeyCode(US, Constants.CODE_SPACE, Constants.CODE_SPACE);
+        assert_toTitleCaseOfKeyCode(US, Constants.CODE_COMMA, Constants.CODE_COMMA);
+        // U+0069: "i" LATIN SMALL LETTER I
+        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+        // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
+        // U+0049: "I" LATIN SMALL LETTER I
+        assert_toTitleCaseOfKeyCode(US, 0x0069, 0x0049); // i -> I
+        assert_toTitleCaseOfKeyCode(US, 0x0131, 0x0049); // ı -> I
+        assert_toTitleCaseOfKeyCode(TURKEY, 0x0069, 0x0130); // i -> İ
+        assert_toTitleCaseOfKeyCode(TURKEY, 0x0131, 0x0049); // ı -> I
+        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
+        // The title case of "ß" is "SS".
+        assert_toTitleCaseOfKeyCode(US, 0x00DF, Constants.CODE_UNSPECIFIED);
+        // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
+        // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
+        assert_toTitleCaseOfKeyCode(GREECE, 0x03AC, 0x0386);
+        // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
+        // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+        assert_toTitleCaseOfKeyCode(GREECE, 0x03CA, 0x03AA);
+        // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+        // The title case of "ΰ" is "\u03A5\u0308\u0301".
+        assert_toTitleCaseOfKeyCode(GREECE, 0x03B0, Constants.CODE_UNSPECIFIED);
+    }
+
+    private static void assert_capitalizeFirstCodePoint(final Locale locale, final String text,
+            final String expected) {
+        assertEquals(text + " in " + locale, expected,
+                StringUtils.capitalizeFirstCodePoint(text, locale));
+    }
+
+    public void test_capitalizeFirstCodePoint() {
+        assert_capitalizeFirstCodePoint(US, "", "");
+        assert_capitalizeFirstCodePoint(US, "a", "A");
+        assert_capitalizeFirstCodePoint(US, "à", "À");
+        assert_capitalizeFirstCodePoint(US, "ß", "SS");
+        assert_capitalizeFirstCodePoint(US, "text", "Text");
+        assert_capitalizeFirstCodePoint(US, "iGoogle", "IGoogle");
+        assert_capitalizeFirstCodePoint(TURKEY, "iyi", "İyi");
+        assert_capitalizeFirstCodePoint(TURKEY, "ısırdı", "Isırdı");
+        assert_capitalizeFirstCodePoint(GREECE, "ά", "Ά");
+        assert_capitalizeFirstCodePoint(GREECE, "άνεση", "Άνεση");
+    }
+
+    private static void assert_capitalizeFirstAndDowncaseRest(final Locale locale,
+            final String text, final String expected) {
+        assertEquals(text + " in " + locale, expected,
+                StringUtils.capitalizeFirstAndDowncaseRest(text, locale));
+    }
+
+    public void test_capitalizeFirstAndDowncaseRest() {
+        assert_capitalizeFirstAndDowncaseRest(US, "", "");
+        assert_capitalizeFirstAndDowncaseRest(US, "a", "A");
+        assert_capitalizeFirstAndDowncaseRest(US, "à", "À");
+        assert_capitalizeFirstAndDowncaseRest(US, "ß", "SS");
+        assert_capitalizeFirstAndDowncaseRest(US, "text", "Text");
+        assert_capitalizeFirstAndDowncaseRest(US, "iGoogle", "Igoogle");
+        assert_capitalizeFirstAndDowncaseRest(US, "invite", "Invite");
+        assert_capitalizeFirstAndDowncaseRest(US, "INVITE", "Invite");
+        assert_capitalizeFirstAndDowncaseRest(TURKEY, "iyi", "İyi");
+        assert_capitalizeFirstAndDowncaseRest(TURKEY, "İYİ", "İyi");
+        assert_capitalizeFirstAndDowncaseRest(TURKEY, "ısırdı", "Isırdı");
+        assert_capitalizeFirstAndDowncaseRest(TURKEY, "ISIRDI", "Isırdı");
+        assert_capitalizeFirstAndDowncaseRest(GREECE, "ά", "Ά");
+        assert_capitalizeFirstAndDowncaseRest(GREECE, "άνεση", "Άνεση");
+        assert_capitalizeFirstAndDowncaseRest(GREECE, "ΆΝΕΣΗ", "Άνεση");
+    }
+
+    public void testContainsInArray() {
+        assertFalse("empty array", StringUtils.containsInArray("key", new String[0]));
+        assertFalse("not in 1 element", StringUtils.containsInArray("key", new String[] {
+                "key1"
+        }));
+        assertFalse("not in 2 elements", StringUtils.containsInArray("key", new String[] {
+                "key1", "key2"
+        }));
+
+        assertTrue("in 1 element", StringUtils.containsInArray("key", new String[] {
+                "key"
+        }));
+        assertTrue("in 2 elements", StringUtils.containsInArray("key", new String[] {
+                "key1", "key"
+        }));
+    }
+
+    public void testContainsInCommaSplittableText() {
+        assertFalse("null", StringUtils.containsInCommaSplittableText("key", null));
+        assertFalse("empty", StringUtils.containsInCommaSplittableText("key", ""));
+        assertFalse("not in 1 element",
+                StringUtils.containsInCommaSplittableText("key", "key1"));
+        assertFalse("not in 2 elements",
+                StringUtils.containsInCommaSplittableText("key", "key1,key2"));
+
+        assertTrue("in 1 element", StringUtils.containsInCommaSplittableText("key", "key"));
+        assertTrue("in 2 elements", StringUtils.containsInCommaSplittableText("key", "key1,key"));
+    }
+
+    public void testRemoveFromCommaSplittableTextIfExists() {
+        assertEquals("null", "", StringUtils.removeFromCommaSplittableTextIfExists("key", null));
+        assertEquals("empty", "", StringUtils.removeFromCommaSplittableTextIfExists("key", ""));
+
+        assertEquals("not in 1 element", "key1",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1"));
+        assertEquals("not in 2 elements", "key1,key2",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key2"));
+
+        assertEquals("in 1 element", "",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key"));
+        assertEquals("in 2 elements at position 1", "key2",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key,key2"));
+        assertEquals("in 2 elements at position 2", "key1",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key"));
+        assertEquals("in 3 elements at position 2", "key1,key3",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key,key3"));
+
+        assertEquals("in 3 elements at position 1,2,3", "",
+                StringUtils.removeFromCommaSplittableTextIfExists("key", "key,key,key"));
+        assertEquals("in 5 elements at position 2,4", "key1,key3,key5",
+                StringUtils.removeFromCommaSplittableTextIfExists(
+                        "key", "key1,key,key3,key,key5"));
+    }
+
+
+    public void testCapitalizeFirstCodePoint() {
+        assertEquals("SSaa",
+                StringUtils.capitalizeFirstCodePoint("ßaa", Locale.GERMAN));
+        assertEquals("Aßa",
+                StringUtils.capitalizeFirstCodePoint("aßa", Locale.GERMAN));
+        assertEquals("Iab",
+                StringUtils.capitalizeFirstCodePoint("iab", Locale.ENGLISH));
+        assertEquals("CAmElCaSe",
+                StringUtils.capitalizeFirstCodePoint("cAmElCaSe", Locale.ENGLISH));
+        assertEquals("İab",
+                StringUtils.capitalizeFirstCodePoint("iab", new Locale("tr")));
+        assertEquals("AİB",
+                StringUtils.capitalizeFirstCodePoint("AİB", new Locale("tr")));
+        assertEquals("A",
+                StringUtils.capitalizeFirstCodePoint("a", Locale.ENGLISH));
+        assertEquals("A",
+                StringUtils.capitalizeFirstCodePoint("A", Locale.ENGLISH));
+    }
+
+    public void testCapitalizeFirstAndDowncaseRest() {
+        assertEquals("SSaa",
+                StringUtils.capitalizeFirstAndDowncaseRest("ßaa", Locale.GERMAN));
+        assertEquals("Aßa",
+                StringUtils.capitalizeFirstAndDowncaseRest("aßa", Locale.GERMAN));
+        assertEquals("Iab",
+                StringUtils.capitalizeFirstAndDowncaseRest("iab", Locale.ENGLISH));
+        assertEquals("Camelcase",
+                StringUtils.capitalizeFirstAndDowncaseRest("cAmElCaSe", Locale.ENGLISH));
+        assertEquals("İab",
+                StringUtils.capitalizeFirstAndDowncaseRest("iab", new Locale("tr")));
+        assertEquals("Aib",
+                StringUtils.capitalizeFirstAndDowncaseRest("AİB", new Locale("tr")));
+        assertEquals("A",
+                StringUtils.capitalizeFirstAndDowncaseRest("a", Locale.ENGLISH));
+        assertEquals("A",
+                StringUtils.capitalizeFirstAndDowncaseRest("A", Locale.ENGLISH));
+    }
+
+    public void testGetCapitalizationType() {
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("cApITalize"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("capitalizE"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType("__c a piu$@tali56ze"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("A__c a piu$@tali56ze"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("Capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_FIRST,
+                StringUtils.getCapitalizationType("     Capitalize"));
+        assertEquals(StringUtils.CAPITALIZE_ALL,
+                StringUtils.getCapitalizationType("CAPITALIZE"));
+        assertEquals(StringUtils.CAPITALIZE_ALL,
+                StringUtils.getCapitalizationType("  PI26LIE"));
+        assertEquals(StringUtils.CAPITALIZE_NONE,
+                StringUtils.getCapitalizationType(""));
+    }
+
+    public void testIsIdenticalAfterUpcaseIsIdenticalAfterDowncase() {
+        assertFalse(StringUtils.isIdenticalAfterUpcase("capitalize"));
+        assertTrue(StringUtils.isIdenticalAfterDowncase("capitalize"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("cApITalize"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("cApITalize"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("capitalizE"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("capitalizE"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("__c a piu$@tali56ze"));
+        assertTrue(StringUtils.isIdenticalAfterDowncase("__c a piu$@tali56ze"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("A__c a piu$@tali56ze"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("A__c a piu$@tali56ze"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("Capitalize"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("Capitalize"));
+        assertFalse(StringUtils.isIdenticalAfterUpcase("     Capitalize"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("     Capitalize"));
+        assertTrue(StringUtils.isIdenticalAfterUpcase("CAPITALIZE"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("CAPITALIZE"));
+        assertTrue(StringUtils.isIdenticalAfterUpcase("  PI26LIE"));
+        assertFalse(StringUtils.isIdenticalAfterDowncase("  PI26LIE"));
+        assertTrue(StringUtils.isIdenticalAfterUpcase(""));
+        assertTrue(StringUtils.isIdenticalAfterDowncase(""));
+    }
+
+    private static void checkCapitalize(final String src, final String dst,
+            final int[] sortedSeparators, final Locale locale) {
+        assertEquals(dst, StringUtils.capitalizeEachWord(src, sortedSeparators, locale));
+        assert(src.equals(dst)
+                == StringUtils.isIdenticalAfterCapitalizeEachWord(src, sortedSeparators));
+    }
+
+    private static final int[] SPACE = { Constants.CODE_SPACE };
+    private static final int[] SPACE_PERIOD = StringUtils.toSortedCodePointArray(" .");
+    private static final int[] SENTENCE_SEPARATORS =
+            StringUtils.toSortedCodePointArray(" \n.!?*()&");
+    private static final int[] WORD_SEPARATORS = StringUtils.toSortedCodePointArray(" \n.!?*,();&");
+
+    public void testCapitalizeEachWord() {
+        checkCapitalize("", "", SPACE, Locale.ENGLISH);
+        checkCapitalize("test", "Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("    test", "    Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("Test", "Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("    Test", "    Test", SPACE, Locale.ENGLISH);
+        checkCapitalize(".Test", ".test", SPACE, Locale.ENGLISH);
+        checkCapitalize(".Test", ".Test", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And Retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.Retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
+        checkCapitalize("Test And.Retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
+        checkCapitalize("test and ietest", "Test And İetest", SPACE_PERIOD, new Locale("tr"));
+        checkCapitalize("test and ietest", "Test And Ietest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("Test&retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("rest\nrecreation! And in the end...",
+                "Rest\nRecreation! And In The End...", WORD_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("lorem ipsum dolor sit amet", "Lorem Ipsum Dolor Sit Amet",
+                WORD_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("Lorem!Ipsum (Dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
+                WORD_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("Lorem!Ipsum (dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
+                WORD_SEPARATORS, Locale.ENGLISH);
+    }
+
+    public void testLooksLikeURL() {
+        assertTrue(StringUtils.lastPartLooksLikeURL("http://www.google."));
+        assertFalse(StringUtils.lastPartLooksLikeURL("word wo"));
+        assertTrue(StringUtils.lastPartLooksLikeURL("/etc/foo"));
+        assertFalse(StringUtils.lastPartLooksLikeURL("left/right"));
+        assertTrue(StringUtils.lastPartLooksLikeURL("www.goo"));
+        assertTrue(StringUtils.lastPartLooksLikeURL("www."));
+        assertFalse(StringUtils.lastPartLooksLikeURL("U.S.A"));
+        assertFalse(StringUtils.lastPartLooksLikeURL("U.S.A."));
+        assertTrue(StringUtils.lastPartLooksLikeURL("rtsp://foo."));
+        assertTrue(StringUtils.lastPartLooksLikeURL("://"));
+        assertFalse(StringUtils.lastPartLooksLikeURL("abc/"));
+        assertTrue(StringUtils.lastPartLooksLikeURL("abc.def/ghi"));
+        assertFalse(StringUtils.lastPartLooksLikeURL("abc.def"));
+        // TODO: ideally this would not look like a URL, but to keep down the complexity of the
+        // code for now True is acceptable.
+        assertTrue(StringUtils.lastPartLooksLikeURL("abc./def"));
+        // TODO: ideally this would not look like a URL, but to keep down the complexity of the
+        // code for now True is acceptable.
+        assertTrue(StringUtils.lastPartLooksLikeURL(".abc/def"));
+    }
+
+    public void testHexStringUtils() {
+        final byte[] bytes = new byte[] { (byte)0x01, (byte)0x11, (byte)0x22, (byte)0x33,
+                (byte)0x55, (byte)0x88, (byte)0xEE };
+        final String bytesStr = StringUtils.byteArrayToHexString(bytes);
+        final byte[] bytes2 = StringUtils.hexStringToByteArray(bytesStr);
+        for (int i = 0; i < bytes.length; ++i) {
+            assertTrue(bytes[i] == bytes2[i]);
+        }
+        final String bytesStr2 = StringUtils.byteArrayToHexString(bytes2);
+        assertTrue(bytesStr.equals(bytesStr2));
+    }
+
+    public void testToCodePointArray() {
+        final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh\u0000\u2002\u2003\u3000xx";
+        final int[] EXPECTED_RESULT = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7, 'f', 'g', 'h',
+                0, 0x2002, 0x2003, 0x3000, 'x', 'x'};
+        final int[] codePointArray = StringUtils.toCodePointArray(STR_WITH_SUPPLEMENTARY_CHAR, 0,
+                STR_WITH_SUPPLEMENTARY_CHAR.length());
+        assertEquals("toCodePointArray, size matches", codePointArray.length,
+                EXPECTED_RESULT.length);
+        for (int i = 0; i < EXPECTED_RESULT.length; ++i) {
+            assertEquals("toCodePointArray position " + i, codePointArray[i], EXPECTED_RESULT[i]);
+        }
+    }
+
+    public void testCopyCodePointsAndReturnCodePointCount() {
+        final String STR_WITH_SUPPLEMENTARY_CHAR = "AbcDE\uD861\uDED7fGh\u0000\u2002\u3000あx";
+        final int[] EXPECTED_RESULT = new int[] { 'A', 'b', 'c', 'D', 'E', 0x286D7,
+                'f', 'G', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
+        final int[] EXPECTED_RESULT_DOWNCASE = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7,
+                'f', 'g', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
+
+        int[] codePointArray = new int[50];
+        int codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
+                STR_WITH_SUPPLEMENTARY_CHAR, 0,
+                STR_WITH_SUPPLEMENTARY_CHAR.length(), false /* downCase */);
+        assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
+                EXPECTED_RESULT.length);
+        for (int i = 0; i < codePointCount; ++i) {
+            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
+                    EXPECTED_RESULT[i]);
+        }
+
+        codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
+                STR_WITH_SUPPLEMENTARY_CHAR, 0,
+                STR_WITH_SUPPLEMENTARY_CHAR.length(), true /* downCase */);
+        assertEquals("copyCodePointsAndReturnCodePointCount downcase, size matches", codePointCount,
+                EXPECTED_RESULT_DOWNCASE.length);
+        for (int i = 0; i < codePointCount; ++i) {
+            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
+                    EXPECTED_RESULT_DOWNCASE[i]);
+        }
+
+        final int JAVA_CHAR_COUNT = 8;
+        final int CODEPOINT_COUNT = 7;
+        codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
+                STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
+        assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
+                CODEPOINT_COUNT);
+        for (int i = 0; i < codePointCount; ++i) {
+            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
+                    EXPECTED_RESULT[i]);
+        }
+
+        boolean exceptionHappened = false;
+        codePointArray = new int[5];
+        try {
+            codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
+                    STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            exceptionHappened = true;
+        }
+        assertTrue("copyCodePointsAndReturnCodePointCount throws when array is too small",
+                exceptionHappened);
+    }
+
+    public void testGetTrailingSingleQuotesCount() {
+        assertEquals(0, StringUtils.getTrailingSingleQuotesCount(""));
+        assertEquals(1, StringUtils.getTrailingSingleQuotesCount("'"));
+        assertEquals(5, StringUtils.getTrailingSingleQuotesCount("'''''"));
+        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("a"));
+        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("'this"));
+        assertEquals(1, StringUtils.getTrailingSingleQuotesCount("'word'"));
+        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("I'm"));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java b/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java
new file mode 100644
index 0000000..59bb082
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/common/UnicodeSurrogateTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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.common;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class UnicodeSurrogateTests extends AndroidTestCase {
+
+    public void testIsLowSurrogate() {
+        assertFalse(UnicodeSurrogate.isLowSurrogate('\uD7FF'));
+        assertTrue(UnicodeSurrogate.isLowSurrogate('\uD83D'));
+        assertFalse(UnicodeSurrogate.isLowSurrogate('\uDC00'));
+    }
+
+    public void testIsHighSurrogate() {
+        assertFalse(UnicodeSurrogate.isHighSurrogate('\uDBFF'));
+        assertTrue(UnicodeSurrogate.isHighSurrogate('\uDE25'));
+        assertFalse(UnicodeSurrogate.isHighSurrogate('\uE000'));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
deleted file mode 100644
index 406046a..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderEncoderTests.java
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * Copyright (C) 2012 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.makedict;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.ByteArrayDictBuffer;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map.Entry;
-import java.util.Random;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * Unit tests for BinaryDictDecoderUtils and BinaryDictEncoderUtils.
- */
-@LargeTest
-public class BinaryDictDecoderEncoderTests extends AndroidTestCase {
-    private static final String TAG = BinaryDictDecoderEncoderTests.class.getSimpleName();
-    private static final int DEFAULT_MAX_UNIGRAMS = 300;
-    private static final int DEFAULT_CODE_POINT_SET_SIZE = 50;
-    private static final int LARGE_CODE_POINT_SET_SIZE = 300;
-    private static final int UNIGRAM_FREQ = 10;
-    private static final int BIGRAM_FREQ = 50;
-    private static final int TOLERANCE_OF_BIGRAM_FREQ = 5;
-    private static final int NUM_OF_NODES_HAVING_SHORTCUTS = 50;
-    private static final int NUM_OF_SHORTCUTS = 5;
-
-    private static final ArrayList<String> sWords = new ArrayList<>();
-    private static final ArrayList<String> sWordsWithVariousCodePoints = new ArrayList<>();
-    private static final SparseArray<List<Integer>> sEmptyBigrams = new SparseArray<>();
-    private static final SparseArray<List<Integer>> sStarBigrams = new SparseArray<>();
-    private static final SparseArray<List<Integer>> sChainBigrams = new SparseArray<>();
-    private static final HashMap<String, List<String>> sShortcuts = new HashMap<>();
-
-    public BinaryDictDecoderEncoderTests() {
-        this(System.currentTimeMillis(), DEFAULT_MAX_UNIGRAMS);
-    }
-
-    public BinaryDictDecoderEncoderTests(final long seed, final int maxUnigrams) {
-        super();
-        BinaryDictionaryUtils.setCurrentTimeForTest(0);
-        Log.e(TAG, "Testing dictionary: seed is " + seed);
-        final Random random = new Random(seed);
-        sWords.clear();
-        sWordsWithVariousCodePoints.clear();
-        generateWords(maxUnigrams, random);
-
-        for (int i = 0; i < sWords.size(); ++i) {
-            sChainBigrams.put(i, new ArrayList<Integer>());
-            if (i > 0) {
-                sChainBigrams.get(i - 1).add(i);
-            }
-        }
-
-        sStarBigrams.put(0, new ArrayList<Integer>());
-        // MAX - 1 because we added one above already
-        final int maxBigrams = Math.min(sWords.size(), FormatSpec.MAX_BIGRAMS_IN_A_PTNODE - 1);
-        for (int i = 1; i < maxBigrams; ++i) {
-            sStarBigrams.get(0).add(i);
-        }
-
-        sShortcuts.clear();
-        for (int i = 0; i < NUM_OF_NODES_HAVING_SHORTCUTS; ++i) {
-            final int from = Math.abs(random.nextInt()) % sWords.size();
-            sShortcuts.put(sWords.get(from), new ArrayList<String>());
-            for (int j = 0; j < NUM_OF_SHORTCUTS; ++j) {
-                final int to = Math.abs(random.nextInt()) % sWords.size();
-                sShortcuts.get(sWords.get(from)).add(sWords.get(to));
-            }
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        BinaryDictionaryUtils.setCurrentTimeForTest(0);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        // Quit test mode.
-        BinaryDictionaryUtils.setCurrentTimeForTest(-1);
-        super.tearDown();
-    }
-
-    private void generateWords(final int number, final Random random) {
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
-                random);
-        final Set<String> wordSet = new HashSet<>();
-        while (wordSet.size() < number) {
-            wordSet.add(CodePointUtils.generateWord(random, codePointSet));
-        }
-        sWords.addAll(wordSet);
-
-        final int[] largeCodePointSet = CodePointUtils.generateCodePointSet(
-                LARGE_CODE_POINT_SET_SIZE, random);
-        wordSet.clear();
-        while (wordSet.size() < number) {
-            wordSet.add(CodePointUtils.generateWord(random, largeCodePointSet));
-        }
-        sWordsWithVariousCodePoints.addAll(wordSet);
-    }
-
-    /**
-     * Adds unigrams to the dictionary.
-     */
-    private void addUnigrams(final int number, final FusionDictionary dict,
-            final List<String> words, final HashMap<String, List<String>> shortcutMap) {
-        for (int i = 0; i < number; ++i) {
-            final String word = words.get(i);
-            final ArrayList<WeightedString> shortcuts = new ArrayList<>();
-            if (shortcutMap != null && shortcutMap.containsKey(word)) {
-                for (final String shortcut : shortcutMap.get(word)) {
-                    shortcuts.add(new WeightedString(shortcut, UNIGRAM_FREQ));
-                }
-            }
-            dict.add(word, new ProbabilityInfo(UNIGRAM_FREQ),
-                    (shortcutMap == null) ? null : shortcuts, false /* isNotAWord */);
-        }
-    }
-
-    private void addBigrams(final FusionDictionary dict,
-            final List<String> words,
-            final SparseArray<List<Integer>> bigrams) {
-        for (int i = 0; i < bigrams.size(); ++i) {
-            final int w1 = bigrams.keyAt(i);
-            for (int w2 : bigrams.valueAt(i)) {
-                dict.setBigram(words.get(w1), words.get(w2), new ProbabilityInfo(BIGRAM_FREQ));
-            }
-        }
-    }
-
-//    The following is useful to dump the dictionary into a textual file, but it can't compile
-//    on-device, so it's commented out.
-//    private void dumpToCombinedFileForDebug(final FusionDictionary dict, final String filename)
-//            throws IOException {
-//        com.android.inputmethod.latin.dicttool.CombinedInputOutput.writeDictionaryCombined(
-//                new java.io.FileWriter(new File(filename)), dict);
-//    }
-
-    private long timeWritingDictToFile(final File file, final FusionDictionary dict,
-            final FormatSpec.FormatOptions formatOptions) {
-
-        long now = -1, diff = -1;
-
-        try {
-            final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions);
-
-            now = System.currentTimeMillis();
-            // If you need to dump the dict to a textual file, uncomment the line below and the
-            // function above
-            // dumpToCombinedFileForDebug(file, "/tmp/foo");
-            dictEncoder.writeDictionary(dict, formatOptions);
-            diff = System.currentTimeMillis() - now;
-        } catch (IOException e) {
-            Log.e(TAG, "IO exception while writing file", e);
-        } catch (UnsupportedFormatException e) {
-            Log.e(TAG, "UnsupportedFormatException", e);
-        }
-
-        return diff;
-    }
-
-    private void checkDictionary(final FusionDictionary dict, final List<String> words,
-            final SparseArray<List<Integer>> bigrams,
-            final HashMap<String, List<String>> shortcutMap) {
-        assertNotNull(dict);
-
-        // check unigram
-        for (final String word : words) {
-            final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
-            assertNotNull(ptNode);
-        }
-
-        // check bigram
-        for (int i = 0; i < bigrams.size(); ++i) {
-            final int w1 = bigrams.keyAt(i);
-            for (final int w2 : bigrams.valueAt(i)) {
-                final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
-                        words.get(w1));
-                assertNotNull(words.get(w1) + "," + words.get(w2), ptNode.getBigram(words.get(w2)));
-            }
-        }
-
-        // check shortcut
-        if (shortcutMap != null) {
-            for (final Entry<String, List<String>> entry : shortcutMap.entrySet()) {
-                assertTrue(words.contains(entry.getKey()));
-                final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray,
-                        entry.getKey());
-                for (final String word : entry.getValue()) {
-                    assertNotNull("shortcut not found: " + entry.getKey() + ", " + word,
-                            ptNode.getShortcut(word));
-                }
-            }
-        }
-    }
-
-    private String outputOptions(final int bufferType,
-            final FormatSpec.FormatOptions formatOptions) {
-        String result = " : buffer type = "
-                + ((bufferType == BinaryDictUtils.USE_BYTE_BUFFER) ? "byte buffer" : "byte array");
-        return result + " : version = " + formatOptions.mVersion;
-    }
-
-    // Tests for readDictionaryBinary and writeDictionaryBinary
-
-    private long timeReadingAndCheckDict(final File file, final List<String> words,
-            final SparseArray<List<Integer>> bigrams,
-            final HashMap<String, List<String>> shortcutMap, final int bufferType) {
-        long now, diff = -1;
-
-        FusionDictionary dict = null;
-        try {
-            final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
-                    bufferType);
-            now = System.currentTimeMillis();
-            dict = dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
-            diff  = System.currentTimeMillis() - now;
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while reading dictionary", e);
-        } catch (UnsupportedFormatException e) {
-            Log.e(TAG, "Unsupported format", e);
-        }
-
-        checkDictionary(dict, words, bigrams, shortcutMap);
-        return diff;
-    }
-
-    // Tests for readDictionaryBinary and writeDictionaryBinary
-    private String runReadAndWrite(final List<String> words,
-            final SparseArray<List<Integer>> bigrams, final HashMap<String, List<String>> shortcuts,
-            final int bufferType, final FormatSpec.FormatOptions formatOptions,
-            final String message) {
-
-        final String dictName = "runReadAndWrite";
-        final String dictVersion = Long.toString(System.currentTimeMillis());
-        final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
-                getContext().getCacheDir());
-
-        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
-        addBigrams(dict, words, bigrams);
-        checkDictionary(dict, words, bigrams, shortcuts);
-
-        final long write = timeWritingDictToFile(file, dict, formatOptions);
-        final long read = timeReadingAndCheckDict(file, words, bigrams, shortcuts, bufferType);
-
-        return "PROF: read=" + read + "ms, write=" + write + "ms :" + message
-                + " : " + outputOptions(bufferType, formatOptions);
-    }
-
-    private void runReadAndWriteTests(final List<String> results, final int bufferType,
-            final FormatSpec.FormatOptions formatOptions) {
-        results.add(runReadAndWrite(sWords, sEmptyBigrams, null /* shortcuts */, bufferType,
-                formatOptions, "unigram"));
-        results.add(runReadAndWrite(sWords, sChainBigrams, null /* shortcuts */, bufferType,
-                formatOptions, "chain"));
-        results.add(runReadAndWrite(sWords, sStarBigrams, null /* shortcuts */, bufferType,
-                formatOptions, "star"));
-        results.add(runReadAndWrite(sWords, sEmptyBigrams, sShortcuts, bufferType, formatOptions,
-                "unigram with shortcuts"));
-        results.add(runReadAndWrite(sWords, sChainBigrams, sShortcuts, bufferType, formatOptions,
-                "chain with shortcuts"));
-        results.add(runReadAndWrite(sWords, sStarBigrams, sShortcuts, bufferType, formatOptions,
-                "star with shortcuts"));
-        results.add(runReadAndWrite(sWordsWithVariousCodePoints, sEmptyBigrams,
-                null /* shortcuts */, bufferType, formatOptions,
-                "unigram with various code points"));
-    }
-
-    // Unit test for CharEncoding.readString and CharEncoding.writeString.
-    public void testCharEncoding() {
-        // the max length of a word in sWords is less than 50.
-        // See generateWords.
-        final byte[] buffer = new byte[50 * 3];
-        final DictBuffer dictBuffer = new ByteArrayDictBuffer(buffer);
-        for (final String word : sWords) {
-            Arrays.fill(buffer, (byte) 0);
-            CharEncoding.writeString(buffer, 0, word);
-            dictBuffer.position(0);
-            final String str = CharEncoding.readString(dictBuffer);
-            assertEquals(word, str);
-        }
-    }
-
-    public void testReadAndWriteWithByteBuffer() {
-        final List<String> results = new ArrayList<>();
-
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
-                BinaryDictUtils.VERSION2_OPTIONS);
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
-                BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
-                BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
-        for (final String result : results) {
-            Log.d(TAG, result);
-        }
-    }
-
-    public void testReadAndWriteWithByteArray() {
-        final List<String> results = new ArrayList<>();
-
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
-                BinaryDictUtils.VERSION2_OPTIONS);
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
-                BinaryDictUtils.VERSION4_OPTIONS_WITHOUT_TIMESTAMP);
-        runReadAndWriteTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
-                BinaryDictUtils.VERSION4_OPTIONS_WITH_TIMESTAMP);
-
-        for (final String result : results) {
-            Log.d(TAG, result);
-        }
-    }
-
-    // Tests for readUnigramsAndBigramsBinary
-
-    private void checkWordMap(final List<String> expectedWords,
-            final SparseArray<List<Integer>> expectedBigrams,
-            final TreeMap<Integer, String> resultWords,
-            final TreeMap<Integer, Integer> resultFrequencies,
-            final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams,
-            final boolean checkProbability) {
-        // check unigrams
-        final Set<String> actualWordsSet = new HashSet<>(resultWords.values());
-        final Set<String> expectedWordsSet = new HashSet<>(expectedWords);
-        assertEquals(actualWordsSet, expectedWordsSet);
-        if (checkProbability) {
-            for (int freq : resultFrequencies.values()) {
-                assertEquals(freq, UNIGRAM_FREQ);
-            }
-        }
-
-        // check bigrams
-        final HashMap<String, Set<String>> expBigrams = new HashMap<>();
-        for (int i = 0; i < expectedBigrams.size(); ++i) {
-            final String word1 = expectedWords.get(expectedBigrams.keyAt(i));
-            for (int w2 : expectedBigrams.valueAt(i)) {
-                if (expBigrams.get(word1) == null) {
-                    expBigrams.put(word1, new HashSet<String>());
-                }
-                expBigrams.get(word1).add(expectedWords.get(w2));
-            }
-        }
-
-        final HashMap<String, Set<String>> actBigrams = new HashMap<>();
-        for (Entry<Integer, ArrayList<PendingAttribute>> entry : resultBigrams.entrySet()) {
-            final String word1 = resultWords.get(entry.getKey());
-            final int unigramFreq = resultFrequencies.get(entry.getKey());
-            for (PendingAttribute attr : entry.getValue()) {
-                final String word2 = resultWords.get(attr.mAddress);
-                if (actBigrams.get(word1) == null) {
-                    actBigrams.put(word1, new HashSet<String>());
-                }
-                actBigrams.get(word1).add(word2);
-
-                if (checkProbability) {
-                    final int bigramFreq = BinaryDictIOUtils.reconstructBigramFrequency(
-                            unigramFreq, attr.mFrequency);
-                    assertTrue(Math.abs(bigramFreq - BIGRAM_FREQ) < TOLERANCE_OF_BIGRAM_FREQ);
-                }
-            }
-        }
-        assertEquals(actBigrams, expBigrams);
-    }
-
-    private long timeAndCheckReadUnigramsAndBigramsBinary(final File file, final List<String> words,
-            final SparseArray<List<Integer>> bigrams, final int bufferType,
-            final boolean checkProbability) {
-        final TreeMap<Integer, String> resultWords = new TreeMap<>();
-        final TreeMap<Integer, ArrayList<PendingAttribute>> resultBigrams = new TreeMap<>();
-        final TreeMap<Integer, Integer> resultFreqs = new TreeMap<>();
-
-        long now = -1, diff = -1;
-        try {
-            final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
-                    bufferType);
-            now = System.currentTimeMillis();
-            dictDecoder.readUnigramsAndBigramsBinary(resultWords, resultFreqs, resultBigrams);
-            diff = System.currentTimeMillis() - now;
-        } catch (IOException e) {
-            Log.e(TAG, "IOException", e);
-        } catch (UnsupportedFormatException e) {
-            Log.e(TAG, "UnsupportedFormatException", e);
-        }
-
-        checkWordMap(words, bigrams, resultWords, resultFreqs, resultBigrams, checkProbability);
-        return diff;
-    }
-
-    private String runReadUnigramsAndBigramsBinary(final ArrayList<String> words,
-            final SparseArray<List<Integer>> bigrams, final int bufferType,
-            final FormatSpec.FormatOptions formatOptions, final String message) {
-        final String dictName = "runReadUnigrams";
-        final String dictVersion = Long.toString(System.currentTimeMillis());
-        final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
-                getContext().getCacheDir());
-
-        // making the dictionary from lists of words.
-        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, null /* shortcutMap */);
-        addBigrams(dict, words, bigrams);
-
-        timeWritingDictToFile(file, dict, formatOptions);
-
-        // Caveat: Currently, the Java code to read a v4 dictionary doesn't calculate the
-        // probability when there's a timestamp for the entry.
-        // TODO: Abandon the Java code, and implement the v4 dictionary reading code in native.
-        long wordMap = timeAndCheckReadUnigramsAndBigramsBinary(file, words, bigrams, bufferType,
-                !formatOptions.mHasTimestamp /* checkProbability */);
-        long fullReading = timeReadingAndCheckDict(file, words, bigrams, null /* shortcutMap */,
-                bufferType);
-
-        return "readDictionaryBinary=" + fullReading + ", readUnigramsAndBigramsBinary=" + wordMap
-                + " : " + message + " : " + outputOptions(bufferType, formatOptions);
-    }
-
-    private void runReadUnigramsAndBigramsTests(final ArrayList<String> results,
-            final int bufferType, final FormatSpec.FormatOptions formatOptions) {
-        results.add(runReadUnigramsAndBigramsBinary(sWords, sEmptyBigrams, bufferType,
-                formatOptions, "unigram"));
-        results.add(runReadUnigramsAndBigramsBinary(sWords, sChainBigrams, bufferType,
-                formatOptions, "chain"));
-        results.add(runReadUnigramsAndBigramsBinary(sWords, sStarBigrams, bufferType,
-                formatOptions, "star"));
-    }
-
-    public void testReadUnigramsAndBigramsBinaryWithByteBuffer() {
-        final ArrayList<String> results = new ArrayList<>();
-
-        runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_BUFFER,
-                BinaryDictUtils.VERSION2_OPTIONS);
-
-        for (final String result : results) {
-            Log.d(TAG, result);
-        }
-    }
-
-    public void testReadUnigramsAndBigramsBinaryWithByteArray() {
-        final ArrayList<String> results = new ArrayList<>();
-
-        runReadUnigramsAndBigramsTests(results, BinaryDictUtils.USE_BYTE_ARRAY,
-                BinaryDictUtils.VERSION2_OPTIONS);
-
-        for (final String result : results) {
-            Log.d(TAG, result);
-        }
-    }
-
-    // Tests for getTerminalPosition
-    private String getWordFromBinary(final DictDecoder dictDecoder, final int address) {
-        if (dictDecoder.getPosition() != 0) dictDecoder.setPosition(0);
-
-        DictionaryHeader fileHeader = null;
-        try {
-            fileHeader = dictDecoder.readHeader();
-        } catch (IOException e) {
-            return null;
-        } catch (UnsupportedFormatException e) {
-            return null;
-        }
-        if (fileHeader == null) return null;
-        return BinaryDictDecoderUtils.getWordAtPosition(dictDecoder, fileHeader.mBodyOffset,
-                address).mWord;
-    }
-
-    private long checkGetTerminalPosition(final DictDecoder dictDecoder, final String word,
-            final boolean contained) {
-        long diff = -1;
-        int position = -1;
-        try {
-            final long now = System.nanoTime();
-            position = dictDecoder.getTerminalPosition(word);
-            diff = System.nanoTime() - now;
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while getTerminalPosition", e);
-        } catch (UnsupportedFormatException e) {
-            Log.e(TAG, "UnsupportedFormatException while getTerminalPosition", e);
-        }
-
-        assertEquals(FormatSpec.NOT_VALID_WORD != position, contained);
-        if (contained) assertEquals(getWordFromBinary(dictDecoder, position), word);
-        return diff;
-    }
-
-    private void runGetTerminalPosition(final ArrayList<String> words,
-            final SparseArray<List<Integer>> bigrams, final int bufferType,
-            final FormatOptions formatOptions, final String message) {
-        final String dictName = "testGetTerminalPosition";
-        final String dictVersion = Long.toString(System.currentTimeMillis());
-        final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
-                getContext().getCacheDir());
-
-        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(sWords.size(), dict, sWords, null /* shortcutMap */);
-        addBigrams(dict, words, bigrams);
-        timeWritingDictToFile(file, dict, formatOptions);
-
-        final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(file, 0, file.length(),
-                DictDecoder.USE_BYTEARRAY);
-        try {
-            dictDecoder.openDictBuffer();
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while opening the buffer", e);
-        } catch (UnsupportedFormatException e) {
-            Log.e(TAG, "IOException while opening the buffer", e);
-        }
-        assertTrue("Can't get the buffer", dictDecoder.isDictBufferOpen());
-
-        try {
-            // too long word
-            final String longWord = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
-            assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(longWord));
-
-            // null
-            assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(null));
-
-            // empty string
-            assertEquals(FormatSpec.NOT_VALID_WORD, dictDecoder.getTerminalPosition(""));
-        } catch (IOException e) {
-        } catch (UnsupportedFormatException e) {
-        }
-
-        // Test a word that is contained within the dictionary.
-        long sum = 0;
-        for (int i = 0; i < sWords.size(); ++i) {
-            final long time = checkGetTerminalPosition(dictDecoder, sWords.get(i), true);
-            sum += time == -1 ? 0 : time;
-        }
-        Log.d(TAG, "per search : " + (((double)sum) / sWords.size() / 1000000) + " : " + message
-                + " : " + outputOptions(bufferType, formatOptions));
-
-        // Test a word that isn't contained within the dictionary.
-        final Random random = new Random((int)System.currentTimeMillis());
-        final int[] codePointSet = CodePointUtils.generateCodePointSet(DEFAULT_CODE_POINT_SET_SIZE,
-                random);
-        for (int i = 0; i < 1000; ++i) {
-            final String word = CodePointUtils.generateWord(random, codePointSet);
-            if (sWords.indexOf(word) != -1) continue;
-            checkGetTerminalPosition(dictDecoder, word, false);
-        }
-    }
-
-    private void runGetTerminalPositionTests(final int bufferType,
-            final FormatOptions formatOptions) {
-        runGetTerminalPosition(sWords, sEmptyBigrams, bufferType, formatOptions, "unigram");
-    }
-
-    public void testGetTerminalPosition() {
-        final ArrayList<String> results = new ArrayList<>();
-
-        runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_ARRAY,
-                BinaryDictUtils.VERSION2_OPTIONS);
-        runGetTerminalPositionTests(BinaryDictUtils.USE_BYTE_BUFFER,
-                BinaryDictUtils.VERSION2_OPTIONS);
-
-        for (final String result : results) {
-            Log.d(TAG, result);
-        }
-    }
-
-    public void testVer2DictGetWordProperty() {
-        final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
-        final ArrayList<String> words = sWords;
-        final HashMap<String, List<String>> shortcuts = sShortcuts;
-        final String dictName = "testGetWordProperty";
-        final String dictVersion = Long.toString(System.currentTimeMillis());
-        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
-        addBigrams(dict, words, sEmptyBigrams);
-        final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
-                getContext().getCacheDir());
-        file.delete();
-        timeWritingDictToFile(file, dict, formatOptions);
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(file.getAbsolutePath(),
-                0 /* offset */, file.length(), true /* useFullEditDistance */,
-                Locale.ENGLISH, dictName, false /* isUpdatable */);
-        for (final String word : words) {
-            final WordProperty wordProperty = binaryDictionary.getWordProperty(word,
-                    false /* isBeginningOfSentence */);
-            assertEquals(word, wordProperty.mWord);
-            assertEquals(UNIGRAM_FREQ, wordProperty.getProbability());
-            if (shortcuts.containsKey(word)) {
-                assertEquals(shortcuts.get(word).size(), wordProperty.mShortcutTargets.size());
-                final List<String> shortcutList = shortcuts.get(word);
-                assertTrue(wordProperty.mHasShortcuts);
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    assertTrue(shortcutList.contains(shortcutTarget.mWord));
-                    assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
-                    shortcutList.remove(shortcutTarget.mWord);
-                }
-                assertTrue(shortcutList.isEmpty());
-            }
-        }
-    }
-
-    public void testVer2DictIteration() {
-        final FormatOptions formatOptions = BinaryDictUtils.VERSION2_OPTIONS;
-        final ArrayList<String> words = sWords;
-        final HashMap<String, List<String>> shortcuts = sShortcuts;
-        final SparseArray<List<Integer>> bigrams = sEmptyBigrams;
-        final String dictName = "testGetWordProperty";
-        final String dictVersion = Long.toString(System.currentTimeMillis());
-        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
-                BinaryDictUtils.makeDictionaryOptions(dictName, dictVersion, formatOptions));
-        addUnigrams(words.size(), dict, words, shortcuts);
-        addBigrams(dict, words, bigrams);
-        final File file = BinaryDictUtils.getDictFile(dictName, dictVersion, formatOptions,
-                getContext().getCacheDir());
-        timeWritingDictToFile(file, dict, formatOptions);
-        Log.d(TAG, file.getAbsolutePath());
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(file.getAbsolutePath(),
-                0 /* offset */, file.length(), true /* useFullEditDistance */,
-                Locale.ENGLISH, dictName, false /* isUpdatable */);
-
-        final HashSet<String> wordSet = new HashSet<>(words);
-        final HashSet<Pair<String, String>> bigramSet = new HashSet<>();
-
-        for (int i = 0; i < words.size(); i++) {
-            final List<Integer> bigramList = bigrams.get(i);
-            if (bigramList != null) {
-                for (final Integer word1Index : bigramList) {
-                    final String word1 = words.get(word1Index);
-                    bigramSet.add(new Pair<>(words.get(i), word1));
-                }
-            }
-        }
-        int token = 0;
-        do {
-            final BinaryDictionary.GetNextWordPropertyResult result =
-                    binaryDictionary.getNextWordProperty(token);
-            final WordProperty wordProperty = result.mWordProperty;
-            final String word0 = wordProperty.mWord;
-            assertEquals(UNIGRAM_FREQ, wordProperty.mProbabilityInfo.mProbability);
-            wordSet.remove(word0);
-            if (shortcuts.containsKey(word0)) {
-                assertEquals(shortcuts.get(word0).size(), wordProperty.mShortcutTargets.size());
-                final List<String> shortcutList = shortcuts.get(word0);
-                assertNotNull(wordProperty.mShortcutTargets);
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    assertTrue(shortcutList.contains(shortcutTarget.mWord));
-                    assertEquals(UNIGRAM_FREQ, shortcutTarget.getProbability());
-                    shortcutList.remove(shortcutTarget.mWord);
-                }
-                assertTrue(shortcutList.isEmpty());
-            }
-            for (int j = 0; j < wordProperty.mBigrams.size(); j++) {
-                final String word1 = wordProperty.mBigrams.get(j).mWord;
-                final Pair<String, String> bigram = new Pair<>(word0, word1);
-                assertTrue(bigramSet.contains(bigram));
-                bigramSet.remove(bigram);
-            }
-            token = result.mNextToken;
-        } while (token != 0);
-        assertTrue(wordSet.isEmpty());
-        assertTrue(bigramSet.isEmpty());
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 96604a1..be75565 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -17,11 +17,16 @@
 package com.android.inputmethod.latin.makedict;
 
 import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import javax.annotation.Nonnull;
 
 /**
  * Decodes binary files for a FusionDictionary.
@@ -109,15 +114,20 @@
      * A class grouping utility function for our specific character encoding.
      */
     static final class CharEncoding {
-        private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20;
-        private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF;
 
         /**
          * Helper method to find out whether this code fits on one byte
          */
-        private static boolean fitsOnOneByte(final int character) {
-            return character >= MINIMAL_ONE_BYTE_CHARACTER_VALUE
-                    && character <= MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
+        private static boolean fitsOnOneByte(final int character,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+            int codePoint = character;
+            if (codePointToOneByteCodeMap != null) {
+                if (codePointToOneByteCodeMap.containsKey(character)) {
+                    codePoint = codePointToOneByteCodeMap.get(character);
+                }
+            }
+            return codePoint >= FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE
+                    && codePoint <= FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
         }
 
         /**
@@ -137,9 +147,10 @@
          * @param character the character code.
          * @return the size in binary encoded-form, either 1 or 3 bytes.
          */
-        static int getCharSize(final int character) {
+        static int getCharSize(final int character,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
             // See char encoding in FusionDictionary.java
-            if (fitsOnOneByte(character)) return 1;
+            if (fitsOnOneByte(character, codePointToOneByteCodeMap)) return 1;
             if (FormatSpec.INVALID_CHARACTER == character) return 1;
             return 3;
         }
@@ -147,9 +158,10 @@
         /**
          * Compute the byte size of a character array.
          */
-        static int getCharArraySize(final int[] chars) {
+        static int getCharArraySize(final int[] chars,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
             int size = 0;
-            for (int character : chars) size += getCharSize(character);
+            for (int character : chars) size += getCharSize(character, codePointToOneByteCodeMap);
             return size;
         }
 
@@ -158,12 +170,21 @@
          *
          * @param codePoints the code point array to write.
          * @param buffer the byte buffer to write to.
-         * @param index the index in buffer to write the character array to.
+         * @param fromIndex the index in buffer to write the character array to.
+         * @param codePointToOneByteCodeMap the map to convert the code point.
          * @return the index after the last character.
          */
-        static int writeCharArray(final int[] codePoints, final byte[] buffer, int index) {
+        static int writeCharArray(final int[] codePoints, final byte[] buffer, final int fromIndex,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+            int index = fromIndex;
             for (int codePoint : codePoints) {
-                if (1 == getCharSize(codePoint)) {
+                if (codePointToOneByteCodeMap != null) {
+                    if (codePointToOneByteCodeMap.containsKey(codePoint)) {
+                        // Convert code points
+                        codePoint = codePointToOneByteCodeMap.get(codePoint);
+                    }
+                }
+                if (1 == getCharSize(codePoint, codePointToOneByteCodeMap)) {
                     buffer[index++] = (byte)codePoint;
                 } else {
                     buffer[index++] = (byte)(0xFF & (codePoint >> 16));
@@ -184,12 +205,19 @@
          * @param word the string to write.
          * @return the size written, in bytes.
          */
-        static int writeString(final byte[] buffer, final int origin, final String word) {
+        static int writeString(final byte[] buffer, final int origin, final String word,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
             final int length = word.length();
             int index = origin;
             for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
-                final int codePoint = word.codePointAt(i);
-                if (1 == getCharSize(codePoint)) {
+                int codePoint = word.codePointAt(i);
+                if (codePointToOneByteCodeMap != null) {
+                    if (codePointToOneByteCodeMap.containsKey(codePoint)) {
+                        // Convert code points
+                        codePoint = codePointToOneByteCodeMap.get(codePoint);
+                    }
+                }
+                if (1 == getCharSize(codePoint, codePointToOneByteCodeMap)) {
                     buffer[index++] = (byte)codePoint;
                 } else {
                     buffer[index++] = (byte)(0xFF & (codePoint >> 16));
@@ -210,12 +238,13 @@
          * @param word the string to write.
          * @return the size written, in bytes.
          */
-        static int writeString(final OutputStream stream, final String word) throws IOException {
+        static int writeString(final OutputStream stream, final String word,
+                final HashMap<Integer, Integer> codePointToOneByteCodeMap) throws IOException {
             final int length = word.length();
             int written = 0;
             for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
                 final int codePoint = word.codePointAt(i);
-                final int charSize = getCharSize(codePoint);
+                final int charSize = getCharSize(codePoint, codePointToOneByteCodeMap);
                 if (1 == charSize) {
                     stream.write((byte) codePoint);
                 } else {
@@ -253,7 +282,7 @@
          */
         static int readChar(final DictBuffer dictBuffer) {
             int character = dictBuffer.readUnsignedByte();
-            if (!fitsOnOneByte(character)) {
+            if (!fitsOnOneByte(character, null)) {
                 if (FormatSpec.PTNODE_CHARACTERS_TERMINATOR == character) {
                     return FormatSpec.INVALID_CHARACTER;
                 }
@@ -271,10 +300,9 @@
         final int msb = dictBuffer.readUnsignedByte();
         if (FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT >= msb) {
             return msb;
-        } else {
-            return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
-                    + dictBuffer.readUnsignedByte();
         }
+        return ((FormatSpec.MAX_PTNODES_FOR_ONE_BYTE_PTNODE_COUNT & msb) << 8)
+                + dictBuffer.readUnsignedByte();
     }
 
     /**
@@ -338,6 +366,43 @@
     }
 
     /**
+     * Helper method that brutally decodes a header from a byte array.
+     *
+     * @param headerBuffer a buffer containing the bytes of the header.
+     * @return a hashmap of the attributes stored in the header
+     */
+    @Nonnull
+    public static HashMap<String, String> decodeHeaderAttributes(@Nonnull final byte[] headerBuffer)
+            throws UnsupportedFormatException {
+        final StringBuilder sb = new StringBuilder();
+        final LinkedList<String> keyValues = new LinkedList<>();
+        int index = 0;
+        while (index < headerBuffer.length) {
+            if (headerBuffer[index] == FormatSpec.PTNODE_CHARACTERS_TERMINATOR) {
+                keyValues.add(sb.toString());
+                sb.setLength(0);
+            } else if (CharEncoding.fitsOnOneByte(headerBuffer[index] & 0xFF,
+                    null /* codePointTable */)) {
+                sb.appendCodePoint(headerBuffer[index] & 0xFF);
+            } else {
+                sb.appendCodePoint(((headerBuffer[index] & 0xFF) << 16)
+                        + ((headerBuffer[index + 1] & 0xFF) << 8)
+                        + (headerBuffer[index + 2] & 0xFF));
+                index += 2;
+            }
+            index += 1;
+        }
+        if ((keyValues.size() & 1) != 0) {
+            throw new UnsupportedFormatException("Odd number of attributes");
+        }
+        final HashMap<String, String> attributes = new HashMap<>();
+        for (int i = 0; i < keyValues.size(); i += 2) {
+            attributes.put(keyValues.get(i), keyValues.get(i + 1));
+        }
+        return attributes;
+    }
+
+    /**
      * Helper method to pass a file name instead of a File object to isBinaryDictionary.
      */
     public static boolean isBinaryDictionary(final String filename) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index eabd8d7..bd51365 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -16,9 +16,7 @@
 
 package com.android.inputmethod.latin.makedict;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
@@ -27,6 +25,8 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map.Entry;
 
 /**
  * Encodes binary files for a FusionDictionary.
@@ -59,8 +59,9 @@
      * @param characters the character array
      * @return the size of the char array, including the terminator if any
      */
-    static int getPtNodeCharactersSize(final int[] characters) {
-        int size = CharEncoding.getCharArraySize(characters);
+    static int getPtNodeCharactersSize(final int[] characters,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+        int size = CharEncoding.getCharArraySize(characters, codePointToOneByteCodeMap);
         if (characters.length > 1) size += FormatSpec.PTNODE_TERMINATOR_SIZE;
         return size;
     }
@@ -74,8 +75,9 @@
      * @param ptNode the PtNode
      * @return the size of the char array, including the terminator if any
      */
-    private static int getPtNodeCharactersSize(final PtNode ptNode) {
-        return getPtNodeCharactersSize(ptNode.mChars);
+    private static int getPtNodeCharactersSize(final PtNode ptNode,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+        return getPtNodeCharactersSize(ptNode.mChars, codePointToOneByteCodeMap);
     }
 
     /**
@@ -88,49 +90,19 @@
     }
 
     /**
-     * Compute the size of a shortcut in bytes.
-     */
-    private static int getShortcutSize(final WeightedString shortcut) {
-        int size = FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE;
-        final String word = shortcut.mWord;
-        final int length = word.length();
-        for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) {
-            final int codePoint = word.codePointAt(i);
-            size += CharEncoding.getCharSize(codePoint);
-        }
-        size += FormatSpec.PTNODE_TERMINATOR_SIZE;
-        return size;
-    }
-
-    /**
-     * Compute the size of a shortcut list in bytes.
-     *
-     * This is known in advance and does not change according to position in the file
-     * like address lists do.
-     */
-    static int getShortcutListSize(final ArrayList<WeightedString> shortcutList) {
-        if (null == shortcutList || shortcutList.isEmpty()) return 0;
-        int size = FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
-        for (final WeightedString shortcut : shortcutList) {
-            size += getShortcutSize(shortcut);
-        }
-        return size;
-    }
-
-    /**
      * Compute the maximum size of a PtNode, assuming 3-byte addresses for everything.
      *
      * @param ptNode the PtNode to compute the size of.
      * @return the maximum size of the PtNode.
      */
-    private static int getPtNodeMaximumSize(final PtNode ptNode) {
-        int size = getNodeHeaderSize(ptNode);
+    private static int getPtNodeMaximumSize(final PtNode ptNode,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+        int size = getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
         if (ptNode.isTerminal()) {
             // If terminal, one byte for the frequency.
             size += FormatSpec.PTNODE_FREQUENCY_SIZE;
         }
         size += FormatSpec.PTNODE_MAX_ADDRESS_SIZE; // For children address
-        size += getShortcutListSize(ptNode.mShortcutTargets);
         if (null != ptNode.mBigrams) {
             size += (FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE
                     + FormatSpec.PTNODE_ATTRIBUTE_MAX_ADDRESS_SIZE)
@@ -146,10 +118,11 @@
      *
      * @param ptNodeArray the node array to compute the maximum size of.
      */
-    private static void calculatePtNodeArrayMaximumSize(final PtNodeArray ptNodeArray) {
+    private static void calculatePtNodeArrayMaximumSize(final PtNodeArray ptNodeArray,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         int size = getPtNodeCountSize(ptNodeArray);
         for (PtNode node : ptNodeArray.mData) {
-            final int nodeSize = getPtNodeMaximumSize(node);
+            final int nodeSize = getPtNodeMaximumSize(node, codePointToOneByteCodeMap);
             node.mCachedSize = nodeSize;
             size += nodeSize;
         }
@@ -161,8 +134,10 @@
      *
      * @param ptNode the PtNode of which to compute the size of the header
      */
-    private static int getNodeHeaderSize(final PtNode ptNode) {
-        return FormatSpec.PTNODE_FLAGS_SIZE + getPtNodeCharactersSize(ptNode);
+    private static int getNodeHeaderSize(final PtNode ptNode,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
+        return FormatSpec.PTNODE_FLAGS_SIZE + getPtNodeCharactersSize(ptNode,
+                codePointToOneByteCodeMap);
     }
 
     /**
@@ -188,8 +163,9 @@
         }
     }
 
-    static int writeUIntToBuffer(final byte[] buffer, int position, final int value,
+    static int writeUIntToBuffer(final byte[] buffer, final int fromPosition, final int value,
             final int size) {
+        int position = fromPosition;
         switch(size) {
             case 4:
                 buffer[position++] = (byte) ((value >> 24) & 0xFF);
@@ -229,27 +205,6 @@
         }
     }
 
-    @UsedForTesting
-    static void writeUIntToDictBuffer(final DictBuffer dictBuffer, final int value,
-            final int size) {
-        switch(size) {
-            case 4:
-                dictBuffer.put((byte) ((value >> 24) & 0xFF));
-                /* fall through */
-            case 3:
-                dictBuffer.put((byte) ((value >> 16) & 0xFF));
-                /* fall through */
-            case 2:
-                dictBuffer.put((byte) ((value >> 8) & 0xFF));
-                /* fall through */
-            case 1:
-                dictBuffer.put((byte) (value & 0xFF));
-                break;
-            default:
-                /* nop */
-        }
-    }
-
     // End utility methods
 
     // This method is responsible for finding a nice ordering of the nodes that favors run-time
@@ -313,11 +268,9 @@
             return targetNodeArray.mCachedAddressAfterUpdate
                     - (currentNodeArray.mCachedAddressAfterUpdate
                             + offsetFromStartOfCurrentNodeArray);
-        } else {
-            return targetNodeArray.mCachedAddressBeforeUpdate
-                    - (currentNodeArray.mCachedAddressBeforeUpdate
-                            + offsetFromStartOfCurrentNodeArray);
         }
+        return targetNodeArray.mCachedAddressBeforeUpdate
+                - (currentNodeArray.mCachedAddressBeforeUpdate + offsetFromStartOfCurrentNodeArray);
     }
 
     /**
@@ -345,9 +298,8 @@
             final int newOffsetBasePoint = currentNodeArray.mCachedAddressAfterUpdate
                     + offsetFromStartOfCurrentNodeArray;
             return targetPtNode.mCachedAddressAfterUpdate - newOffsetBasePoint;
-        } else {
-            return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
         }
+        return targetPtNode.mCachedAddressBeforeUpdate - oldOffsetBasePoint;
     }
 
     /**
@@ -365,7 +317,8 @@
      * @return false if none of the cached addresses inside the node array changed, true otherwise.
      */
     private static boolean computeActualPtNodeArraySize(final PtNodeArray ptNodeArray,
-            final FusionDictionary dict) {
+            final FusionDictionary dict,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         boolean changed = false;
         int size = getPtNodeCountSize(ptNodeArray);
         for (PtNode ptNode : ptNodeArray.mData) {
@@ -373,7 +326,7 @@
             if (ptNode.mCachedAddressAfterUpdate != ptNode.mCachedAddressBeforeUpdate) {
                 changed = true;
             }
-            int nodeSize = getNodeHeaderSize(ptNode);
+            int nodeSize = getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
             if (ptNode.isTerminal()) {
                 nodeSize += FormatSpec.PTNODE_FREQUENCY_SIZE;
             }
@@ -381,7 +334,6 @@
                 nodeSize += getByteSize(getOffsetToTargetNodeArrayDuringUpdate(ptNodeArray,
                         nodeSize + size, ptNode.mChildren));
             }
-            nodeSize += getShortcutListSize(ptNode.mShortcutTargets);
             if (null != ptNode.mBigrams) {
                 for (WeightedString bigram : ptNode.mBigrams) {
                     final int offset = getOffsetToTargetPtNodeDuringUpdate(ptNodeArray,
@@ -452,10 +404,11 @@
      * @return the same array it was passed. The nodes have been updated for address and size.
      */
     /* package */ static ArrayList<PtNodeArray> computeAddresses(final FusionDictionary dict,
-            final ArrayList<PtNodeArray> flatNodes) {
+            final ArrayList<PtNodeArray> flatNodes,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         // First get the worst possible sizes and offsets
         for (final PtNodeArray n : flatNodes) {
-            calculatePtNodeArrayMaximumSize(n);
+            calculatePtNodeArrayMaximumSize(n, codePointToOneByteCodeMap);
         }
         final int offset = initializePtNodeArraysCachedAddresses(flatNodes);
 
@@ -470,7 +423,8 @@
             for (final PtNodeArray ptNodeArray : flatNodes) {
                 ptNodeArray.mCachedAddressAfterUpdate = ptNodeArrayStartOffset;
                 final int oldNodeArraySize = ptNodeArray.mCachedSize;
-                final boolean changed = computeActualPtNodeArraySize(ptNodeArray, dict);
+                final boolean changed = computeActualPtNodeArraySize(ptNodeArray, dict,
+                        codePointToOneByteCodeMap);
                 final int newNodeArraySize = ptNodeArray.mCachedSize;
                 if (oldNodeArraySize < newNodeArraySize) {
                     throw new RuntimeException("Increased size ?!");
@@ -521,12 +475,13 @@
      * Helper method to write a children position to a file.
      *
      * @param buffer the buffer to write to.
-     * @param index the index in the buffer to write the address to.
+     * @param fromIndex the index in the buffer to write the address to.
      * @param position the position to write.
      * @return the size in bytes the address actually took.
      */
-    /* package */ static int writeChildrenPosition(final byte[] buffer, int index,
+    /* package */ static int writeChildrenPosition(final byte[] buffer, final int fromIndex,
             final int position) {
+        int index = fromIndex;
         switch (getByteSize(position)) {
         case 1:
             buffer[index++] = (byte)position;
@@ -548,42 +503,19 @@
     }
 
     /**
-     * Helper method to write a signed children position to a file.
-     *
-     * @param buffer the buffer to write to.
-     * @param index the index in the buffer to write the address to.
-     * @param position the position to write.
-     * @return the size in bytes the address actually took.
-     */
-    /* package */ static int writeSignedChildrenPosition(final byte[] buffer, int index,
-            final int position) {
-        if (!BinaryDictIOUtils.hasChildrenAddress(position)) {
-            buffer[index] = buffer[index + 1] = buffer[index + 2] = 0;
-        } else {
-            final int absPosition = Math.abs(position);
-            buffer[index++] =
-                    (byte)((position < 0 ? FormatSpec.MSB8 : 0) | (0xFF & (absPosition >> 16)));
-            buffer[index++] = (byte)(0xFF & (absPosition >> 8));
-            buffer[index++] = (byte)(0xFF & absPosition);
-        }
-        return 3;
-    }
-
-    /**
      * Makes the flag value for a PtNode.
      *
      * @param hasMultipleChars whether the PtNode has multiple chars.
      * @param isTerminal whether the PtNode is terminal.
      * @param childrenAddressSize the size of a children address.
-     * @param hasShortcuts whether the PtNode has shortcuts.
      * @param hasBigrams whether the PtNode has bigrams.
      * @param isNotAWord whether the PtNode is not a word.
-     * @param isBlackListEntry whether the PtNode is a blacklist entry.
+     * @param isPossiblyOffensive whether the PtNode is a possibly offensive entry.
      * @return the flags
      */
     static int makePtNodeFlags(final boolean hasMultipleChars, final boolean isTerminal,
-            final int childrenAddressSize, final boolean hasShortcuts, final boolean hasBigrams,
-            final boolean isNotAWord, final boolean isBlackListEntry) {
+            final int childrenAddressSize, final boolean hasBigrams,
+            final boolean isNotAWord, final boolean isPossiblyOffensive) {
         byte flags = 0;
         if (hasMultipleChars) flags |= FormatSpec.FLAG_HAS_MULTIPLE_CHARS;
         if (isTerminal) flags |= FormatSpec.FLAG_IS_TERMINAL;
@@ -603,19 +535,17 @@
             default:
                 throw new RuntimeException("Node with a strange address");
         }
-        if (hasShortcuts) flags |= FormatSpec.FLAG_HAS_SHORTCUT_TARGETS;
         if (hasBigrams) flags |= FormatSpec.FLAG_HAS_BIGRAMS;
         if (isNotAWord) flags |= FormatSpec.FLAG_IS_NOT_A_WORD;
-        if (isBlackListEntry) flags |= FormatSpec.FLAG_IS_BLACKLISTED;
+        if (isPossiblyOffensive) flags |= FormatSpec.FLAG_IS_POSSIBLY_OFFENSIVE;
         return flags;
     }
 
     /* package */ static byte makePtNodeFlags(final PtNode node, final int childrenOffset) {
         return (byte) makePtNodeFlags(node.mChars.length > 1, node.isTerminal(),
                 getByteSize(childrenOffset),
-                node.mShortcutTargets != null && !node.mShortcutTargets.isEmpty(),
                 node.mBigrams != null && !node.mBigrams.isEmpty(),
-                node.mIsNotAWord, node.mIsBlacklistEntry);
+                node.mIsNotAWord, node.mIsPossiblyOffensive);
     }
 
     /**
@@ -628,8 +558,8 @@
      * @param word the second bigram, for debugging purposes
      * @return the flags
      */
-    /* package */ static final int makeBigramFlags(final boolean more, final int offset,
-            int bigramFrequency, final int unigramFrequency, final String word) {
+    /* package */ static int makeBigramFlags(final boolean more, final int offset,
+            final int bigramFrequency, final int unigramFrequency, final String word) {
         int bigramFlags = (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
                 + (offset < 0 ? FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE : 0);
         switch (getByteSize(offset)) {
@@ -645,13 +575,16 @@
         default:
             throw new RuntimeException("Strange offset size");
         }
+        final int frequency;
         if (unigramFrequency > bigramFrequency) {
             MakedictLog.e("Unigram freq is superior to bigram freq for \"" + word
                     + "\". Bigram freq is " + bigramFrequency + ", unigram freq for "
                     + word + " is " + unigramFrequency);
-            bigramFrequency = unigramFrequency;
+            frequency = unigramFrequency;
+        } else {
+            frequency = bigramFrequency;
         }
-        bigramFlags += getBigramFrequencyDiff(unigramFrequency, bigramFrequency)
+        bigramFlags += getBigramFrequencyDiff(unigramFrequency, frequency)
                 & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY;
         return bigramFlags;
     }
@@ -694,21 +627,10 @@
         return discretizedFrequency > 0 ? discretizedFrequency : 0;
     }
 
-    /**
-     * Makes the flag value for a shortcut.
-     *
-     * @param more whether there are more attributes after this one.
-     * @param frequency the frequency of the attribute, 0..15
-     * @return the flags
-     */
-    static final int makeShortcutFlags(final boolean more, final int frequency) {
-        return (more ? FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT : 0)
-                + (frequency & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY);
-    }
-
-    /* package */ static final int getChildrenPosition(final PtNode ptNode) {
+    /* package */ static int getChildrenPosition(final PtNode ptNode,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         int positionOfChildrenPosField = ptNode.mCachedAddressAfterUpdate
-                + getNodeHeaderSize(ptNode);
+                + getNodeHeaderSize(ptNode, codePointToOneByteCodeMap);
         if (ptNode.isTerminal()) {
             // A terminal node has the frequency.
             // If positionOfChildrenPosField is incorrect, we may crash when jumping to the children
@@ -725,19 +647,16 @@
      * @param dict the dictionary the node array is a part of (for relative offsets).
      * @param dictEncoder the dictionary encoder.
      * @param ptNodeArray the node array to write.
+     * @param codePointToOneByteCodeMap the map to convert the code points.
      */
-    @SuppressWarnings("unused")
     /* package */ static void writePlacedPtNodeArray(final FusionDictionary dict,
-            final DictEncoder dictEncoder, final PtNodeArray ptNodeArray) {
+            final DictEncoder dictEncoder, final PtNodeArray ptNodeArray,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap) {
         // TODO: Make the code in common with BinaryDictIOUtils#writePtNode
         dictEncoder.setPosition(ptNodeArray.mCachedAddressAfterUpdate);
 
         final int ptNodeCount = ptNodeArray.mData.size();
         dictEncoder.writePtNodeCount(ptNodeCount);
-        final int parentPosition =
-                (ptNodeArray.mCachedParentAddress == FormatSpec.NO_PARENT_ADDRESS)
-                ? FormatSpec.NO_PARENT_ADDRESS
-                : ptNodeArray.mCachedParentAddress + ptNodeArray.mCachedAddressAfterUpdate;
         for (int i = 0; i < ptNodeCount; ++i) {
             final PtNode ptNode = ptNodeArray.mData.get(i);
             if (dictEncoder.getPosition() != ptNode.mCachedAddressAfterUpdate) {
@@ -751,7 +670,7 @@
                         + FormatSpec.MAX_TERMINAL_FREQUENCY
                         + " : " + ptNode.mProbabilityInfo.toString());
             }
-            dictEncoder.writePtNode(ptNode, dict);
+            dictEncoder.writePtNode(ptNode, dict, codePointToOneByteCodeMap);
         }
         if (dictEncoder.getPosition() != ptNodeArray.mCachedAddressAfterUpdate
                 + ptNodeArray.mCachedSize) {
@@ -817,18 +736,26 @@
      * @param destination the stream to write the file header to.
      * @param dict the dictionary to write.
      * @param formatOptions file format options.
+     * @param codePointOccurrenceArray code points ordered by occurrence count.
      * @return the size of the header.
      */
     /* package */ static int writeDictionaryHeader(final OutputStream destination,
-            final FusionDictionary dict, final FormatOptions formatOptions)
+            final FusionDictionary dict, final FormatOptions formatOptions,
+            final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray)
                     throws IOException, UnsupportedFormatException {
         final int version = formatOptions.mVersion;
-        if (version < FormatSpec.MINIMUM_SUPPORTED_VERSION
-                || version > FormatSpec.MAXIMUM_SUPPORTED_VERSION) {
+        if ((version >= FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION &&
+                version <= FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION) || (
+                version >= FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION &&
+                version <= FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION)) {
+            // Dictionary is valid
+        } else {
             throw new UnsupportedFormatException("Requested file format version " + version
-                    + ", but this implementation only supports versions "
-                    + FormatSpec.MINIMUM_SUPPORTED_VERSION + " through "
-                    + FormatSpec.MAXIMUM_SUPPORTED_VERSION);
+                    + ", but this implementation only supports static versions "
+                    + FormatSpec.MINIMUM_SUPPORTED_STATIC_VERSION + " through "
+                    + FormatSpec.MAXIMUM_SUPPORTED_STATIC_VERSION + " and dynamic versions "
+                    + FormatSpec.MINIMUM_SUPPORTED_DYNAMIC_VERSION + " through "
+                    + FormatSpec.MAXIMUM_SUPPORTED_DYNAMIC_VERSION);
         }
 
         ByteArrayOutputStream headerBuffer = new ByteArrayOutputStream(256);
@@ -856,8 +783,15 @@
         // Write out the options.
         for (final String key : dict.mOptions.mAttributes.keySet()) {
             final String value = dict.mOptions.mAttributes.get(key);
-            CharEncoding.writeString(headerBuffer, key);
-            CharEncoding.writeString(headerBuffer, value);
+            CharEncoding.writeString(headerBuffer, key, null);
+            CharEncoding.writeString(headerBuffer, value, null);
+        }
+        // Write out the codePointTable if there is codePointOccurrenceArray.
+        if (codePointOccurrenceArray != null) {
+            final String codePointTableString =
+                    encodeCodePointTable(codePointOccurrenceArray);
+            CharEncoding.writeString(headerBuffer, DictionaryHeader.CODE_POINT_TABLE_KEY, null);
+            CharEncoding.writeString(headerBuffer, codePointTableString, null);
         }
         final int size = headerBuffer.size();
         final byte[] bytes = headerBuffer.toByteArray();
@@ -871,4 +805,35 @@
         headerBuffer.close();
         return size;
     }
+
+    static final class CodePointTable {
+        final HashMap<Integer, Integer> mCodePointToOneByteCodeMap;
+        final ArrayList<Entry<Integer, Integer>> mCodePointOccurrenceArray;
+
+        // Let code point table empty for version 200 dictionary which used in test
+        CodePointTable() {
+            mCodePointToOneByteCodeMap = null;
+            mCodePointOccurrenceArray = null;
+        }
+
+        CodePointTable(final HashMap<Integer, Integer> codePointToOneByteCodeMap,
+                final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray) {
+            mCodePointToOneByteCodeMap = codePointToOneByteCodeMap;
+            mCodePointOccurrenceArray = codePointOccurrenceArray;
+        }
+    }
+
+    private static String encodeCodePointTable(
+            final ArrayList<Entry<Integer, Integer>> codePointOccurrenceArray) {
+        final StringBuilder codePointTableString = new StringBuilder();
+        int currentCodePointTableIndex = FormatSpec.MINIMAL_ONE_BYTE_CHARACTER_VALUE;
+        for (final Entry<Integer, Integer> entry : codePointOccurrenceArray) {
+            // Native reads the table as a string
+            codePointTableString.appendCodePoint(entry.getKey());
+            if (FormatSpec.MAXIMAL_ONE_BYTE_CHARACTER_VALUE < ++currentCodePointTableIndex) {
+                break;
+            }
+        }
+        return codePointTableString.toString();
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 9c3b373..da1b32a 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.latin.makedict;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
 
 import java.io.File;
@@ -43,22 +43,12 @@
      */
     public static DictDecoder getDictDecoder(final File dictFile, final long offset,
             final long length, final int bufferType) {
-        if (dictFile.isDirectory()) {
-            return new Ver4DictDecoder(dictFile, bufferType);
-        } else if (dictFile.isFile()) {
-            return new Ver2DictDecoder(dictFile, offset, length, bufferType);
-        }
-        return null;
+        return new Ver4DictDecoder(dictFile);
     }
 
     public static DictDecoder getDictDecoder(final File dictFile, final long offset,
             final long length, final DictionaryBufferFactory factory) {
-        if (dictFile.isDirectory()) {
-            return new Ver4DictDecoder(dictFile, factory);
-        } else if (dictFile.isFile()) {
-            return new Ver2DictDecoder(dictFile, offset, length, factory);
-        }
-        return null;
+        return new Ver4DictDecoder(dictFile);
     }
 
     public static DictDecoder getDictDecoder(final File dictFile, final long offset,
@@ -183,7 +173,7 @@
         dictDecoder.readHeader();
         int wordPos = 0;
         final int wordLen = word.codePointCount(0, word.length());
-        for (int depth = 0; depth < Constants.DICTIONARY_MAX_WORD_LENGTH; ++depth) {
+        for (int depth = 0; depth < DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH; ++depth) {
             if (wordPos >= wordLen) return FormatSpec.NOT_VALID_WORD;
 
             do {
@@ -206,11 +196,7 @@
                     if (same) {
                         // found the PtNode matches the word.
                         if (wordPos + currentInfo.mCharacters.length == wordLen) {
-                            if (!currentInfo.isTerminal()) {
-                                return FormatSpec.NOT_VALID_WORD;
-                            } else {
-                                return ptNodePos;
-                            }
+                            return currentInfo.isTerminal() ? ptNodePos : FormatSpec.NOT_VALID_WORD;
                         }
                         wordPos += currentInfo.mCharacters.length;
                         if (currentInfo.mChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
deleted file mode 100644
index 5a3eba8..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictUtils.java
+++ /dev/null
@@ -1,78 +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.makedict;
-
-import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-
-import java.io.File;
-import java.util.HashMap;
-
-public class BinaryDictUtils {
-    public static final int USE_BYTE_ARRAY = 1;
-    public static final int USE_BYTE_BUFFER = 2;
-
-    public static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-
-    public static final FormatSpec.FormatOptions VERSION2_OPTIONS =
-            new FormatSpec.FormatOptions(FormatSpec.VERSION2);
-    public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITHOUT_TIMESTAMP =
-            new FormatSpec.FormatOptions(FormatSpec.VERSION4, false /* hasTimestamp */);
-    public static final FormatSpec.FormatOptions VERSION4_OPTIONS_WITH_TIMESTAMP =
-            new FormatSpec.FormatOptions(FormatSpec.VERSION4, true /* hasTimestamp */);
-
-    public static DictionaryOptions makeDictionaryOptions(final String id, final String version,
-            final FormatSpec.FormatOptions formatOptions) {
-        final DictionaryOptions options = new DictionaryOptions(new HashMap<String, String>());
-        options.mAttributes.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, "en_US");
-        options.mAttributes.put(DictionaryHeader.DICTIONARY_ID_KEY, id);
-        options.mAttributes.put(DictionaryHeader.DICTIONARY_VERSION_KEY, version);
-        if (formatOptions.mHasTimestamp) {
-            options.mAttributes.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
-                    DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-            options.mAttributes.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
-                    DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        }
-        return options;
-    }
-
-    public static File getDictFile(final String name, final String version,
-            final FormatOptions formatOptions, final File directory) {
-        if (formatOptions.mVersion == FormatSpec.VERSION2) {
-            return new File(directory, name + "." + version + TEST_DICT_FILE_EXTENSION);
-        } else if (formatOptions.mVersion == FormatSpec.VERSION4) {
-            return new File(directory, name + "." + version);
-        } else {
-            throw new RuntimeException("the format option has a wrong version : "
-                    + formatOptions.mVersion);
-        }
-    }
-
-    public static DictEncoder getDictEncoder(final File file, final FormatOptions formatOptions) {
-        if (formatOptions.mVersion == FormatSpec.VERSION4) {
-            if (!file.isDirectory()) {
-                file.mkdir();
-            }
-            return new Ver4DictEncoder(file);
-        } else if (formatOptions.mVersion == FormatSpec.VERSION2) {
-            return new Ver2DictEncoder(file);
-        } else {
-            throw new RuntimeException("The format option has a wrong version : "
-                    + formatOptions.mVersion);
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java b/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
deleted file mode 100644
index a270ee7..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/CodePointUtils.java
+++ /dev/null
@@ -1,101 +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.makedict;
-
-import java.util.Random;
-
-// Utility methods related with code points used for tests.
-public class CodePointUtils {
-    private CodePointUtils() {
-        // This utility class is not publicly instantiable.
-    }
-
-    public static final int[] LATIN_ALPHABETS_LOWER = {
-        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-        0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
-        0x00E1 /* LATIN SMALL LETTER A WITH ACUTE */,
-        0x00E2 /* LATIN SMALL LETTER A WITH CIRCUMFLEX */,
-        0x00E3 /* LATIN SMALL LETTER A WITH TILDE */,
-        0x00E4 /* LATIN SMALL LETTER A WITH DIAERESIS */,
-        0x00E5 /* LATIN SMALL LETTER A WITH RING ABOVE */,
-        0x00E6 /* LATIN SMALL LETTER AE */,
-        0x00E7 /* LATIN SMALL LETTER C WITH CEDILLA */,
-        0x00E8 /* LATIN SMALL LETTER E WITH GRAVE */,
-        0x00E9 /* LATIN SMALL LETTER E WITH ACUTE */,
-        0x00EA /* LATIN SMALL LETTER E WITH CIRCUMFLEX */,
-        0x00EB /* LATIN SMALL LETTER E WITH DIAERESIS */,
-        0x00EC /* LATIN SMALL LETTER I WITH GRAVE */,
-        0x00ED /* LATIN SMALL LETTER I WITH ACUTE */,
-        0x00EE /* LATIN SMALL LETTER I WITH CIRCUMFLEX */,
-        0x00EF /* LATIN SMALL LETTER I WITH DIAERESIS */,
-        0x00F0 /* LATIN SMALL LETTER ETH */,
-        0x00F1 /* LATIN SMALL LETTER N WITH TILDE */,
-        0x00F2 /* LATIN SMALL LETTER O WITH GRAVE */,
-        0x00F3 /* LATIN SMALL LETTER O WITH ACUTE */,
-        0x00F4 /* LATIN SMALL LETTER O WITH CIRCUMFLEX */,
-        0x00F5 /* LATIN SMALL LETTER O WITH TILDE */,
-        0x00F6 /* LATIN SMALL LETTER O WITH DIAERESIS */,
-        0x00F7 /* LATIN SMALL LETTER O WITH STROKE */,
-        0x00F9 /* LATIN SMALL LETTER U WITH GRAVE */,
-        0x00FA /* LATIN SMALL LETTER U WITH ACUTE */,
-        0x00FB /* LATIN SMALL LETTER U WITH CIRCUMFLEX */,
-        0x00FC /* LATIN SMALL LETTER U WITH DIAERESIS */,
-        0x00FD /* LATIN SMALL LETTER Y WITH ACUTE */,
-        0x00FE /* LATIN SMALL LETTER THORN */,
-        0x00FF /* LATIN SMALL LETTER Y WITH DIAERESIS */
-    };
-
-    public static int[] generateCodePointSet(final int codePointSetSize, final Random random) {
-        final int[] codePointSet = new int[codePointSetSize];
-        for (int i = codePointSet.length - 1; i >= 0; ) {
-            final int r = Math.abs(random.nextInt());
-            if (r < 0) continue;
-            // Don't insert 0~0x20, but insert any other code point.
-            // Code points are in the range 0~0x10FFFF.
-            final int candidateCodePoint = 0x20 + r % (Character.MAX_CODE_POINT - 0x20);
-            // Code points between MIN_ and MAX_SURROGATE are not valid on their own.
-            if (candidateCodePoint >= Character.MIN_SURROGATE
-                    && candidateCodePoint <= Character.MAX_SURROGATE) continue;
-            codePointSet[i] = candidateCodePoint;
-            --i;
-        }
-        return codePointSet;
-    }
-
-    /**
-     * Generates a random word.
-     */
-    public static String generateWord(final Random random, final int[] codePointSet) {
-        StringBuilder builder = new StringBuilder();
-        // 8 * 4 = 32 chars max, but we do it the following way so as to bias the random toward
-        // longer words. This should be closer to natural language, and more importantly, it will
-        // exercise the algorithms in dicttool much more.
-        final int count = 1 + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5)
-                + (Math.abs(random.nextInt()) % 5);
-        while (builder.length() < count) {
-            builder.appendCodePoint(codePointSet[Math.abs(random.nextInt()) % codePointSet.length]);
-        }
-        return builder.toString();
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
index 678c5ca..10dd003 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/DictEncoder.java
@@ -21,6 +21,7 @@
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
 
 import java.io.IOException;
+import java.util.HashMap;
 
 /**
  * An interface of binary dictionary encoder.
@@ -33,6 +34,6 @@
     public void setPosition(final int position);
     public int getPosition();
     public void writePtNodeCount(final int ptNodeCount);
-    public void writeForwardLinkAddress(final int forwardLinkAddress);
-    public void writePtNode(final PtNode ptNode, final FusionDictionary dict);
+    public void writePtNode(final PtNode ptNode, final FusionDictionary dict,
+            final HashMap<Integer, Integer> codePointToOneByteCodeMap);
 }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index 4a8c178..6ba1ef9 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -17,7 +17,7 @@
 package com.android.inputmethod.latin.makedict;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
 
 import java.util.ArrayList;
@@ -82,14 +82,13 @@
     public static final class PtNode {
         private static final int NOT_A_TERMINAL = -1;
         final int mChars[];
-        ArrayList<WeightedString> mShortcutTargets;
         ArrayList<WeightedString> mBigrams;
         // null == mProbabilityInfo indicates this is not a terminal.
         ProbabilityInfo mProbabilityInfo;
         int mTerminalId; // NOT_A_TERMINAL == mTerminalId indicates this is not a terminal.
         PtNodeArray mChildren;
         boolean mIsNotAWord; // Only a shortcut
-        boolean mIsBlacklistEntry;
+        boolean mIsPossiblyOffensive;
         // mCachedSize and mCachedAddressBefore/AfterUpdate are helpers for binary dictionary
         // generation. Before and After always hold the same value except during dictionary
         // address compression, where the update process needs to know about both values at the
@@ -100,30 +99,27 @@
         int mCachedAddressBeforeUpdate; // The address of this PtNode (before update)
         int mCachedAddressAfterUpdate; // The address of this PtNode (after update)
 
-        public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
-                final boolean isNotAWord, final boolean isBlacklistEntry) {
+        public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+                final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+                final boolean isPossiblyOffensive) {
             mChars = chars;
             mProbabilityInfo = probabilityInfo;
             mTerminalId = probabilityInfo == null ? NOT_A_TERMINAL : probabilityInfo.mProbability;
-            mShortcutTargets = shortcutTargets;
             mBigrams = bigrams;
             mChildren = null;
             mIsNotAWord = isNotAWord;
-            mIsBlacklistEntry = isBlacklistEntry;
+            mIsPossiblyOffensive = isPossiblyOffensive;
         }
 
-        public PtNode(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final ProbabilityInfo probabilityInfo,
-                final boolean isNotAWord, final boolean isBlacklistEntry,
-                final PtNodeArray children) {
+        public PtNode(final int[] chars, final ArrayList<WeightedString> bigrams,
+                final ProbabilityInfo probabilityInfo, final boolean isNotAWord,
+                final boolean isPossiblyOffensive, final PtNodeArray children) {
             mChars = chars;
             mProbabilityInfo = probabilityInfo;
-            mShortcutTargets = shortcutTargets;
             mBigrams = bigrams;
             mChildren = children;
             mIsNotAWord = isNotAWord;
-            mIsBlacklistEntry = isBlacklistEntry;
+            mIsPossiblyOffensive = isPossiblyOffensive;
         }
 
         public void addChild(PtNode n) {
@@ -142,27 +138,15 @@
         }
 
         public int getProbability() {
-            if (isTerminal()) {
-                return mProbabilityInfo.mProbability;
-            } else {
-                return NOT_A_TERMINAL;
-            }
+            return isTerminal() ? mProbabilityInfo.mProbability : NOT_A_TERMINAL;
         }
 
         public boolean getIsNotAWord() {
             return mIsNotAWord;
         }
 
-        public boolean getIsBlacklistEntry() {
-            return mIsBlacklistEntry;
-        }
-
-        public ArrayList<WeightedString> getShortcutTargets() {
-            // We don't want write permission to escape outside the package, so we return a copy
-            if (null == mShortcutTargets) return null;
-            final ArrayList<WeightedString> copyOfShortcutTargets =
-                    new ArrayList<>(mShortcutTargets);
-            return copyOfShortcutTargets;
+        public boolean getIsPossiblyOffensive() {
+            return mIsPossiblyOffensive;
         }
 
         public ArrayList<WeightedString> getBigrams() {
@@ -195,24 +179,6 @@
         }
 
         /**
-         * Gets the shortcut target for the given word. Returns null if the word is not in the
-         * shortcut list.
-         */
-        public WeightedString getShortcut(final String word) {
-            // TODO: Don't do a linear search
-            if (mShortcutTargets != null) {
-                final int size = mShortcutTargets.size();
-                for (int i = 0; i < size; ++i) {
-                    WeightedString shortcut = mShortcutTargets.get(i);
-                    if (shortcut.mWord.equals(word)) {
-                        return shortcut;
-                    }
-                }
-            }
-            return null;
-        }
-
-        /**
          * Gets the bigram for the given word.
          * Returns null if the word is not in the bigrams list.
          */
@@ -235,28 +201,10 @@
          * the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only
          * updated if they are higher than the existing ones.
          */
-        private void update(final ProbabilityInfo probabilityInfo,
-                final ArrayList<WeightedString> shortcutTargets,
+        void update(final ProbabilityInfo probabilityInfo,
                 final ArrayList<WeightedString> bigrams,
-                final boolean isNotAWord, final boolean isBlacklistEntry) {
+                final boolean isNotAWord, final boolean isPossiblyOffensive) {
             mProbabilityInfo = ProbabilityInfo.max(mProbabilityInfo, probabilityInfo);
-            if (shortcutTargets != null) {
-                if (mShortcutTargets == null) {
-                    mShortcutTargets = shortcutTargets;
-                } else {
-                    final int size = shortcutTargets.size();
-                    for (int i = 0; i < size; ++i) {
-                        final WeightedString shortcut = shortcutTargets.get(i);
-                        final WeightedString existingShortcut = getShortcut(shortcut.mWord);
-                        if (existingShortcut == null) {
-                            mShortcutTargets.add(shortcut);
-                        } else {
-                            existingShortcut.mProbabilityInfo = ProbabilityInfo.max(
-                                    existingShortcut.mProbabilityInfo, shortcut.mProbabilityInfo);
-                        }
-                    }
-                }
-            }
             if (bigrams != null) {
                 if (mBigrams == null) {
                     mBigrams = bigrams;
@@ -275,7 +223,7 @@
                 }
             }
             mIsNotAWord = isNotAWord;
-            mIsBlacklistEntry = isBlacklistEntry;
+            mIsPossiblyOffensive = isPossiblyOffensive;
         }
     }
 
@@ -316,31 +264,16 @@
      * Helper method to add a word as a string.
      *
      * This method adds a word to the dictionary with the given frequency. Optional
-     * lists of bigrams and shortcuts can be passed here. For each word inside,
+     * lists of bigrams can be passed here. For each word inside,
      * they will be added to the dictionary as necessary.
-     *
-     * @param word the word to add.
+     *  @param word the word to add.
      * @param probabilityInfo probability information of the word.
-     * @param shortcutTargets a list of shortcut targets for this word, or null.
      * @param isNotAWord true if this should not be considered a word (e.g. shortcut only)
+     * @param isPossiblyOffensive true if this word is possibly offensive
      */
     public void add(final String word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord) {
-        add(getCodePoints(word), probabilityInfo, shortcutTargets, isNotAWord,
-                false /* isBlacklistEntry */);
-    }
-
-    /**
-     * Helper method to add a blacklist entry as a string.
-     *
-     * @param word the word to add as a blacklist entry.
-     * @param shortcutTargets a list of shortcut targets for this word, or null.
-     * @param isNotAWord true if this is not a word for spellcheking purposes (shortcut only or so)
-     */
-    public void addBlacklistEntry(final String word,
-            final ArrayList<WeightedString> shortcutTargets, final boolean isNotAWord) {
-        add(getCodePoints(word), new ProbabilityInfo(0), shortcutTargets, isNotAWord,
-                true /* isBlacklistEntry */);
+            final boolean isNotAWord, final boolean isPossiblyOffensive) {
+        add(getCodePoints(word), probabilityInfo, isNotAWord, isPossiblyOffensive);
     }
 
     /**
@@ -349,15 +282,15 @@
      * This method checks that all PtNodes in a node array are ordered as expected.
      * If they are, nothing happens. If they aren't, an exception is thrown.
      */
-    private void checkStack(PtNodeArray ptNodeArray) {
+    private static void checkStack(PtNodeArray ptNodeArray) {
         ArrayList<PtNode> stack = ptNodeArray.mData;
         int lastValue = -1;
         for (int i = 0; i < stack.size(); ++i) {
             int currentValue = stack.get(i).mChars[0];
-            if (currentValue <= lastValue)
+            if (currentValue <= lastValue) {
                 throw new RuntimeException("Invalid stack");
-            else
-                lastValue = currentValue;
+            }
+            lastValue = currentValue;
         }
     }
 
@@ -374,8 +307,8 @@
         if (ptNode0 != null) {
             final PtNode ptNode1 = findWordInTree(mRootNodeArray, word1);
             if (ptNode1 == null) {
-                add(getCodePoints(word1), new ProbabilityInfo(0), null, false /* isNotAWord */,
-                        false /* isBlacklistEntry */);
+                add(getCodePoints(word1), new ProbabilityInfo(0), false /* isNotAWord */,
+                        false /* isPossiblyOffensive */);
                 // The PtNode for the first word may have moved by the above insertion,
                 // if word1 and word2 share a common stem that happens not to have been
                 // a cutting point until now. In this case, we need to refresh ptNode.
@@ -392,18 +325,15 @@
      *
      * The shortcuts, if any, have to be in the dictionary already. If they aren't,
      * an exception is thrown.
-     *
-     * @param word the word, as an int array.
+     *  @param word the word, as an int array.
      * @param probabilityInfo the probability information of the word.
-     * @param shortcutTargets an optional list of shortcut targets for this word (null if none).
-     * @param isNotAWord true if this is not a word for spellcheking purposes (shortcut only or so)
-     * @param isBlacklistEntry true if this is a blacklisted word, false otherwise
+     * @param isNotAWord true if this is not a word for spellchecking purposes (shortcut only or so)
+     * @param isPossiblyOffensive true if this word is possibly offensive
      */
     private void add(final int[] word, final ProbabilityInfo probabilityInfo,
-            final ArrayList<WeightedString> shortcutTargets,
-            final boolean isNotAWord, final boolean isBlacklistEntry) {
+            final boolean isNotAWord, final boolean isPossiblyOffensive) {
         assert(probabilityInfo.mProbability <= FormatSpec.MAX_TERMINAL_FREQUENCY);
-        if (word.length >= Constants.DICTIONARY_MAX_WORD_LENGTH) {
+        if (word.length >= DecoderSpecificConstants.DICTIONARY_MAX_WORD_LENGTH) {
             MakedictLog.w("Ignoring a word that is too long: word.length = " + word.length);
             return;
         }
@@ -430,8 +360,8 @@
             // No node at this point to accept the word. Create one.
             final int insertionIndex = findInsertionIndex(currentNodeArray, word[charIndex]);
             final PtNode newPtNode = new PtNode(Arrays.copyOfRange(word, charIndex, word.length),
-                    shortcutTargets, null /* bigrams */, probabilityInfo, isNotAWord,
-                    isBlacklistEntry);
+                    null /* bigrams */, probabilityInfo, isNotAWord,
+                    isPossiblyOffensive);
             currentNodeArray.mData.add(insertionIndex, newPtNode);
             if (DBG) checkStack(currentNodeArray);
         } else {
@@ -441,15 +371,15 @@
                     // The new word is a prefix of an existing word, but the node on which it
                     // should end already exists as is. Since the old PtNode was not a terminal,
                     // make it one by filling in its frequency and other attributes
-                    currentPtNode.update(probabilityInfo, shortcutTargets, null, isNotAWord,
-                            isBlacklistEntry);
+                    currentPtNode.update(probabilityInfo, null, isNotAWord,
+                            isPossiblyOffensive);
                 } else {
                     // The new word matches the full old word and extends past it.
                     // We only have to create a new node and add it to the end of this.
                     final PtNode newNode = new PtNode(
                             Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length),
-                                    shortcutTargets, null /* bigrams */, probabilityInfo,
-                                    isNotAWord, isBlacklistEntry);
+                                    null /* bigrams */, probabilityInfo,
+                                    isNotAWord, isPossiblyOffensive);
                     currentPtNode.mChildren = new PtNodeArray();
                     currentPtNode.mChildren.mData.add(newNode);
                 }
@@ -457,18 +387,18 @@
                 if (0 == differentCharIndex) {
                     // Exact same word. Update the frequency if higher. This will also add the
                     // new shortcuts to the existing shortcut list if it already exists.
-                    currentPtNode.update(probabilityInfo, shortcutTargets, null,
+                    currentPtNode.update(probabilityInfo, null,
                             currentPtNode.mIsNotAWord && isNotAWord,
-                            currentPtNode.mIsBlacklistEntry || isBlacklistEntry);
+                            currentPtNode.mIsPossiblyOffensive || isPossiblyOffensive);
                 } else {
                     // Partial prefix match only. We have to replace the current node with a node
                     // containing the current prefix and create two new ones for the tails.
                     PtNodeArray newChildren = new PtNodeArray();
                     final PtNode newOldWord = new PtNode(
                             Arrays.copyOfRange(currentPtNode.mChars, differentCharIndex,
-                                    currentPtNode.mChars.length), currentPtNode.mShortcutTargets,
+                                    currentPtNode.mChars.length),
                             currentPtNode.mBigrams, currentPtNode.mProbabilityInfo,
-                            currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry,
+                            currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive,
                             currentPtNode.mChildren);
                     newChildren.mData.add(newOldWord);
 
@@ -476,18 +406,18 @@
                     if (charIndex + differentCharIndex >= word.length) {
                         newParent = new PtNode(
                                 Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
-                                shortcutTargets, null /* bigrams */, probabilityInfo,
-                                isNotAWord, isBlacklistEntry, newChildren);
+                                null /* bigrams */, probabilityInfo,
+                                isNotAWord, isPossiblyOffensive, newChildren);
                     } else {
                         newParent = new PtNode(
                                 Arrays.copyOfRange(currentPtNode.mChars, 0, differentCharIndex),
-                                null /* shortcutTargets */, null /* bigrams */,
-                                null /* probabilityInfo */, false /* isNotAWord */,
-                                false /* isBlacklistEntry */, newChildren);
+                                null /* bigrams */, null /* probabilityInfo */,
+                                false /* isNotAWord */, false /* isPossiblyOffensive */,
+                                newChildren);
                         final PtNode newWord = new PtNode(Arrays.copyOfRange(word,
                                 charIndex + differentCharIndex, word.length),
-                                shortcutTargets, null /* bigrams */, probabilityInfo,
-                                isNotAWord, isBlacklistEntry);
+                                null /* bigrams */, probabilityInfo,
+                                isNotAWord, isPossiblyOffensive);
                         final int addIndex = word[charIndex + differentCharIndex]
                                 > currentPtNode.mChars[differentCharIndex] ? 1 : 0;
                         newChildren.mData.add(addIndex, newWord);
@@ -533,14 +463,14 @@
      * is ignored.
      * This comparator imposes orderings that are inconsistent with equals.
      */
-    static private final class PtNodeComparator implements java.util.Comparator<PtNode> {
+    static final class PtNodeComparator implements java.util.Comparator<PtNode> {
         @Override
         public int compare(PtNode p1, PtNode p2) {
             if (p1.mChars[0] == p2.mChars[0]) return 0;
             return p1.mChars[0] < p2.mChars[0] ? -1 : 1;
         }
     }
-    final static private PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
+    final static PtNodeComparator PTNODE_COMPARATOR = new PtNodeComparator();
 
     /**
      * Finds the insertion index of a character within a node array.
@@ -548,8 +478,8 @@
     private static int findInsertionIndex(final PtNodeArray nodeArray, int character) {
         final ArrayList<PtNode> data = nodeArray.mData;
         final PtNode reference = new PtNode(new int[] { character },
-                null /* shortcutTargets */, null /* bigrams */, null /* probabilityInfo */,
-                false /* isNotAWord */, false /* isBlacklistEntry */);
+                null /* bigrams */, null /* probabilityInfo */,
+                false /* isNotAWord */, false /* isPossiblyOffensive */);
         int result = Collections.binarySearch(data, reference, PTNODE_COMPARATOR);
         return result >= 0 ? result : -result - 1;
     }
@@ -571,7 +501,8 @@
     /**
      * Helper method to find a word in a given branch.
      */
-    public static PtNode findWordInTree(PtNodeArray nodeArray, final String string) {
+    public static PtNode findWordInTree(final PtNodeArray rootNodeArray, final String string) {
+        PtNodeArray nodeArray = rootNodeArray;
         int index = 0;
         final StringBuilder checker = DBG ? new StringBuilder() : null;
         final int[] codePoints = getCodePoints(string);
@@ -684,9 +615,8 @@
                     }
                     if (currentPtNode.isTerminal()) {
                         return new WordProperty(mCurrentString.toString(),
-                                currentPtNode.mProbabilityInfo,
-                                currentPtNode.mShortcutTargets, currentPtNode.mBigrams,
-                                currentPtNode.mIsNotAWord, currentPtNode.mIsBlacklistEntry);
+                                currentPtNode.mProbabilityInfo, currentPtNode.mBigrams,
+                                currentPtNode.mIsNotAWord, currentPtNode.mIsPossiblyOffensive);
                     }
                 } else {
                     mPositions.removeLast();
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
deleted file mode 100644
index 65b84d5..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoder.java
+++ /dev/null
@@ -1,321 +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.makedict;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * An implementation of DictDecoder for version 2 binary dictionary.
- */
-// TODO: Separate logics that are used only for testing.
-@UsedForTesting
-public class Ver2DictDecoder extends AbstractDictDecoder {
-    /**
-     * A utility class for reading a PtNode.
-     */
-    protected static class PtNodeReader {
-        private static ProbabilityInfo readProbabilityInfo(final DictBuffer dictBuffer) {
-            // Ver2 dicts don't contain historical information.
-            return new ProbabilityInfo(dictBuffer.readUnsignedByte());
-        }
-
-        protected static int readPtNodeOptionFlags(final DictBuffer dictBuffer) {
-            return dictBuffer.readUnsignedByte();
-        }
-
-        protected static int readChildrenAddress(final DictBuffer dictBuffer,
-                final int ptNodeFlags) {
-            switch (ptNodeFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
-                case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
-                    return dictBuffer.readUnsignedByte();
-                case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_TWOBYTES:
-                    return dictBuffer.readUnsignedShort();
-                case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_THREEBYTES:
-                    return dictBuffer.readUnsignedInt24();
-                case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_NOADDRESS:
-                default:
-                    return FormatSpec.NO_CHILDREN_ADDRESS;
-            }
-        }
-
-        // Reads shortcuts and returns the read length.
-        protected static int readShortcut(final DictBuffer dictBuffer,
-                final ArrayList<WeightedString> shortcutTargets) {
-            final int pointerBefore = dictBuffer.position();
-            dictBuffer.readUnsignedShort(); // skip the size
-            while (true) {
-                final int targetFlags = dictBuffer.readUnsignedByte();
-                final String word = CharEncoding.readString(dictBuffer);
-                shortcutTargets.add(new WeightedString(word,
-                        targetFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY));
-                if (0 == (targetFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
-            }
-            return dictBuffer.position() - pointerBefore;
-        }
-
-        protected static int readBigramAddresses(final DictBuffer dictBuffer,
-                final ArrayList<PendingAttribute> bigrams, final int baseAddress) {
-            int readLength = 0;
-            int bigramCount = 0;
-            while (bigramCount++ < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
-                final int bigramFlags = dictBuffer.readUnsignedByte();
-                ++readLength;
-                final int sign = 0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_ATTR_OFFSET_NEGATIVE)
-                        ? 1 : -1;
-                int bigramAddress = baseAddress + readLength;
-                switch (bigramFlags & FormatSpec.MASK_BIGRAM_ATTR_ADDRESS_TYPE) {
-                    case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_ONEBYTE:
-                        bigramAddress += sign * dictBuffer.readUnsignedByte();
-                        readLength += 1;
-                        break;
-                    case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_TWOBYTES:
-                        bigramAddress += sign * dictBuffer.readUnsignedShort();
-                        readLength += 2;
-                        break;
-                    case FormatSpec.FLAG_BIGRAM_ATTR_ADDRESS_TYPE_THREEBYTES:
-                        bigramAddress += sign * dictBuffer.readUnsignedInt24();
-                        readLength += 3;
-                        break;
-                    default:
-                        throw new RuntimeException("Has bigrams with no address");
-                }
-                bigrams.add(new PendingAttribute(
-                        bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_FREQUENCY,
-                        bigramAddress));
-                if (0 == (bigramFlags & FormatSpec.FLAG_BIGRAM_SHORTCUT_ATTR_HAS_NEXT)) break;
-            }
-            return readLength;
-        }
-    }
-
-    protected final File mDictionaryBinaryFile;
-    protected final long mOffset;
-    protected final long mLength;
-    // TODO: Remove mBufferFactory and mDictBuffer from this class members because they are now
-    // used only for testing.
-    private final DictionaryBufferFactory mBufferFactory;
-    protected DictBuffer mDictBuffer;
-
-    @UsedForTesting
-    /* package */ Ver2DictDecoder(final File file, final long offset, final long length,
-            final int factoryFlag) {
-        mDictionaryBinaryFile = file;
-        mOffset = offset;
-        mLength = length;
-        mDictBuffer = null;
-        if ((factoryFlag & MASK_DICTBUFFER) == USE_READONLY_BYTEBUFFER) {
-            mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory();
-        } else if ((factoryFlag  & MASK_DICTBUFFER) == USE_BYTEARRAY) {
-            mBufferFactory = new DictionaryBufferFromByteArrayFactory();
-        } else if ((factoryFlag & MASK_DICTBUFFER) == USE_WRITABLE_BYTEBUFFER) {
-            mBufferFactory = new DictionaryBufferFromWritableByteBufferFactory();
-        } else {
-            mBufferFactory = new DictionaryBufferFromReadOnlyByteBufferFactory();
-        }
-    }
-
-    /* package */ Ver2DictDecoder(final File file, final long offset, final long length,
-            final DictionaryBufferFactory factory) {
-        mDictionaryBinaryFile = file;
-        mOffset = offset;
-        mLength = length;
-        mBufferFactory = factory;
-    }
-
-    @Override
-    public void openDictBuffer() throws FileNotFoundException, IOException {
-        mDictBuffer = mBufferFactory.getDictionaryBuffer(mDictionaryBinaryFile);
-    }
-
-    @Override
-    public boolean isDictBufferOpen() {
-        return mDictBuffer != null;
-    }
-
-    /* package */ DictBuffer getDictBuffer() {
-        return mDictBuffer;
-    }
-
-    @UsedForTesting
-    /* package */ DictBuffer openAndGetDictBuffer() throws FileNotFoundException, IOException {
-        openDictBuffer();
-        return getDictBuffer();
-    }
-
-    @Override
-    public DictionaryHeader readHeader() throws IOException, UnsupportedFormatException {
-        // dictType is not being used in dicttool. Passing an empty string.
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(
-                mDictionaryBinaryFile.getAbsolutePath(), mOffset, mLength,
-                true /* useFullEditDistance */, null /* locale */, "" /* dictType */,
-                false /* isUpdatable */);
-        final DictionaryHeader header = binaryDictionary.getHeader();
-        binaryDictionary.close();
-        if (header == null) {
-            throw new IOException("Cannot read the dictionary header.");
-        }
-        if (header.mFormatOptions.mVersion != FormatSpec.VERSION2) {
-            throw new UnsupportedFormatException("File header has a wrong version : "
-                    + header.mFormatOptions.mVersion);
-        }
-        if (!isDictBufferOpen()) {
-            openDictBuffer();
-        }
-        // Advance buffer reading position to the head of dictionary body.
-        setPosition(header.mBodyOffset);
-        return header;
-    }
-
-    // TODO: Make this buffer multi thread safe.
-    private final int[] mCharacterBuffer = new int[FormatSpec.MAX_WORD_LENGTH];
-    @Override
-    public PtNodeInfo readPtNode(final int ptNodePos) {
-        int addressPointer = ptNodePos;
-        final int flags = PtNodeReader.readPtNodeOptionFlags(mDictBuffer);
-        addressPointer += FormatSpec.PTNODE_FLAGS_SIZE;
-        final int characters[];
-        if (0 != (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS)) {
-            int index = 0;
-            int character = CharEncoding.readChar(mDictBuffer);
-            addressPointer += CharEncoding.getCharSize(character);
-            while (FormatSpec.INVALID_CHARACTER != character) {
-                // FusionDictionary is making sure that the length of the word is smaller than
-                // MAX_WORD_LENGTH.
-                // So we'll never write past the end of mCharacterBuffer.
-                mCharacterBuffer[index++] = character;
-                character = CharEncoding.readChar(mDictBuffer);
-                addressPointer += CharEncoding.getCharSize(character);
-            }
-            characters = Arrays.copyOfRange(mCharacterBuffer, 0, index);
-        } else {
-            final int character = CharEncoding.readChar(mDictBuffer);
-            addressPointer += CharEncoding.getCharSize(character);
-            characters = new int[] { character };
-        }
-        final ProbabilityInfo probabilityInfo;
-        if (0 != (FormatSpec.FLAG_IS_TERMINAL & flags)) {
-            probabilityInfo = PtNodeReader.readProbabilityInfo(mDictBuffer);
-            addressPointer += FormatSpec.PTNODE_FREQUENCY_SIZE;
-        } else {
-            probabilityInfo = null;
-        }
-        int childrenAddress = PtNodeReader.readChildrenAddress(mDictBuffer, flags);
-        if (childrenAddress != FormatSpec.NO_CHILDREN_ADDRESS) {
-            childrenAddress += addressPointer;
-        }
-        addressPointer += BinaryDictIOUtils.getChildrenAddressSize(flags);
-        final ArrayList<WeightedString> shortcutTargets;
-        if (0 != (flags & FormatSpec.FLAG_HAS_SHORTCUT_TARGETS)) {
-            // readShortcut will add shortcuts to shortcutTargets.
-            shortcutTargets = new ArrayList<>();
-            addressPointer += PtNodeReader.readShortcut(mDictBuffer, shortcutTargets);
-        } else {
-            shortcutTargets = null;
-        }
-
-        final ArrayList<PendingAttribute> bigrams;
-        if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) {
-            bigrams = new ArrayList<>();
-            addressPointer += PtNodeReader.readBigramAddresses(mDictBuffer, bigrams,
-                    addressPointer);
-            if (bigrams.size() >= FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
-                throw new RuntimeException("Too many bigrams in a PtNode (" + bigrams.size()
-                        + " but max is " + FormatSpec.MAX_BIGRAMS_IN_A_PTNODE + ")");
-            }
-        } else {
-            bigrams = null;
-        }
-        return new PtNodeInfo(ptNodePos, addressPointer, flags, characters, probabilityInfo,
-                childrenAddress, shortcutTargets, bigrams);
-    }
-
-    @Override
-    public FusionDictionary readDictionaryBinary(final boolean deleteDictIfBroken)
-            throws FileNotFoundException, IOException, UnsupportedFormatException {
-        // dictType is not being used in dicttool. Passing an empty string.
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(
-                mDictionaryBinaryFile.getAbsolutePath(), 0 /* offset */,
-                mDictionaryBinaryFile.length() /* length */, true /* useFullEditDistance */,
-                null /* locale */, "" /* dictType */, false /* isUpdatable */);
-        final DictionaryHeader header = readHeader();
-        final FusionDictionary fusionDict =
-                new FusionDictionary(new FusionDictionary.PtNodeArray(), header.mDictionaryOptions);
-        int token = 0;
-        final ArrayList<WordProperty> wordProperties = new ArrayList<>();
-        do {
-            final BinaryDictionary.GetNextWordPropertyResult result =
-                    binaryDictionary.getNextWordProperty(token);
-            final WordProperty wordProperty = result.mWordProperty;
-            if (wordProperty == null) {
-                binaryDictionary.close();
-                if (deleteDictIfBroken) {
-                    mDictionaryBinaryFile.delete();
-                }
-                return null;
-            }
-            wordProperties.add(wordProperty);
-            token = result.mNextToken;
-        } while (token != 0);
-
-        // Insert unigrams into the fusion dictionary.
-        for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mIsBlacklistEntry) {
-                fusionDict.addBlacklistEntry(wordProperty.mWord, wordProperty.mShortcutTargets,
-                        wordProperty.mIsNotAWord);
-            } else {
-                fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
-                        wordProperty.mShortcutTargets, wordProperty.mIsNotAWord);
-            }
-        }
-        // Insert bigrams into the fusion dictionary.
-        for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mBigrams == null) {
-                continue;
-            }
-            final String word0 = wordProperty.mWord;
-            for (final WeightedString bigram : wordProperty.mBigrams) {
-                fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
-            }
-        }
-        binaryDictionary.close();
-        return fusionDict;
-    }
-
-    @Override
-    public void setPosition(int newPos) {
-        mDictBuffer.position(newPos);
-    }
-
-    @Override
-    public int getPosition() {
-        return mDictBuffer.position();
-    }
-
-    @Override
-    public int readPtNodeCount() {
-        return BinaryDictDecoderUtils.readPtNodeCount(mDictBuffer);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java
deleted file mode 100644
index 3882c2c..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictDecoderTests.java
+++ /dev/null
@@ -1,150 +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.makedict;
-
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer;
-import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFactory;
-import com.android.inputmethod.latin.makedict.DictDecoder.DictionaryBufferFromByteArrayFactory;
-import com.android.inputmethod.latin.makedict.DictDecoder.
-        DictionaryBufferFromReadOnlyByteBufferFactory;
-import com.android.inputmethod.latin.makedict.DictDecoder.
-        DictionaryBufferFromWritableByteBufferFactory;
-
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Unit tests for Ver2DictDecoder
- */
-public class Ver2DictDecoderTests extends AndroidTestCase {
-    private static final String TAG = Ver2DictDecoderTests.class.getSimpleName();
-
-    private final byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
-
-    // Utilities for testing
-    public void writeDataToFile(final File file) {
-        FileOutputStream outStream = null;
-        try {
-            outStream = new FileOutputStream(file);
-            outStream.write(data);
-        } catch (IOException e) {
-            fail ("Can't write data to the test file");
-        } finally {
-            if (outStream != null) {
-                try {
-                    outStream.close();
-                } catch (IOException e) {
-                    Log.e(TAG, "Failed to close the output stream", e);
-                }
-            }
-        }
-    }
-
-    public void runTestOpenBuffer(final String testName, final DictionaryBufferFactory factory) {
-        File testFile = null;
-        try {
-            testFile = File.createTempFile(testName, ".tmp", getContext().getCacheDir());
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while the creating temporary file", e);
-        }
-
-        assertNotNull(testFile);
-        final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(),
-                factory);
-        try {
-            dictDecoder.openDictBuffer();
-        } catch (Exception e) {
-            Log.e(TAG, "Failed to open the buffer", e);
-        }
-
-        writeDataToFile(testFile);
-
-        try {
-            dictDecoder.openDictBuffer();
-        } catch (Exception e) {
-            Log.e(TAG, "Raised the exception while opening buffer", e);
-        }
-
-        assertEquals(testFile.length(), dictDecoder.getDictBuffer().capacity());
-    }
-
-    public void testOpenBufferWithByteBuffer() {
-        runTestOpenBuffer("testOpenBufferWithByteBuffer",
-                new DictionaryBufferFromReadOnlyByteBufferFactory());
-    }
-
-    public void testOpenBufferWithByteArray() {
-        runTestOpenBuffer("testOpenBufferWithByteArray",
-                new DictionaryBufferFromByteArrayFactory());
-    }
-
-    public void testOpenBufferWithWritableByteBuffer() {
-        runTestOpenBuffer("testOpenBufferWithWritableByteBuffer",
-                new DictionaryBufferFromWritableByteBufferFactory());
-    }
-
-    public void runTestGetBuffer(final String testName, final DictionaryBufferFactory factory) {
-        File testFile = null;
-        try {
-            testFile = File.createTempFile(testName, ".tmp", getContext().getCacheDir());
-        } catch (IOException e) {
-            Log.e(TAG, "IOException while the creating temporary file", e);
-        }
-
-        final Ver2DictDecoder dictDecoder = new Ver2DictDecoder(testFile, 0, testFile.length(),
-                factory);
-
-        // the default return value of getBuffer() must be null.
-        assertNull("the default return value of getBuffer() is not null",
-                dictDecoder.getDictBuffer());
-
-        writeDataToFile(testFile);
-        assertTrue(testFile.exists());
-        Log.d(TAG, "file length = " + testFile.length());
-
-        DictBuffer dictBuffer = null;
-        try {
-            dictBuffer = dictDecoder.openAndGetDictBuffer();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to open and get the buffer", e);
-        }
-        assertNotNull("the buffer must not be null", dictBuffer);
-
-        for (int i = 0; i < data.length; ++i) {
-            assertEquals(data[i], dictBuffer.readUnsignedByte());
-        }
-    }
-
-    public void testGetBufferWithByteBuffer() {
-        runTestGetBuffer("testGetBufferWithByteBuffer",
-                new DictionaryBufferFromReadOnlyByteBufferFactory());
-    }
-
-    public void testGetBufferWithByteArray() {
-        runTestGetBuffer("testGetBufferWithByteArray",
-                new DictionaryBufferFromByteArrayFactory());
-    }
-
-    public void testGetBufferWithWritableByteBuffer() {
-        runTestGetBuffer("testGetBufferWithWritableByteBuffer",
-                new DictionaryBufferFromWritableByteBufferFactory());
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
deleted file mode 100644
index a286190..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
+++ /dev/null
@@ -1,240 +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.makedict;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * An implementation of DictEncoder for version 2 binary dictionary.
- */
-@UsedForTesting
-public class Ver2DictEncoder implements DictEncoder {
-
-    private final File mDictFile;
-    private OutputStream mOutStream;
-    private byte[] mBuffer;
-    private int mPosition;
-
-    @UsedForTesting
-    public Ver2DictEncoder(final File dictFile) {
-        mDictFile = dictFile;
-        mOutStream = null;
-        mBuffer = null;
-    }
-
-    // This constructor is used only by BinaryDictOffdeviceUtilsTests.
-    // If you want to use this in the production code, you should consider keeping consistency of
-    // the interface of Ver3DictDecoder by using factory.
-    @UsedForTesting
-    public Ver2DictEncoder(final OutputStream outStream) {
-        mDictFile = null;
-        mOutStream = outStream;
-    }
-
-    private void openStream() throws FileNotFoundException {
-        mOutStream = new FileOutputStream(mDictFile);
-    }
-
-    private void close() throws IOException {
-        if (mOutStream != null) {
-            mOutStream.close();
-            mOutStream = null;
-        }
-    }
-
-    @Override
-    public void writeDictionary(final FusionDictionary dict, final FormatOptions formatOptions)
-            throws IOException, UnsupportedFormatException {
-        if (formatOptions.mVersion > FormatSpec.VERSION2) {
-            throw new UnsupportedFormatException(
-                    "The given format options has wrong version number : "
-                    + formatOptions.mVersion);
-        }
-
-        if (mOutStream == null) {
-            openStream();
-        }
-        BinaryDictEncoderUtils.writeDictionaryHeader(mOutStream, dict, formatOptions);
-
-        // Addresses are limited to 3 bytes, but since addresses can be relative to each node
-        // array, the structure itself is not limited to 16MB. However, if it is over 16MB deciding
-        // the order of the PtNode arrays becomes a quite complicated problem, because though the
-        // dictionary itself does not have a size limit, each node array must still be within 16MB
-        // of all its children and parents. As long as this is ensured, the dictionary file may
-        // grow to any size.
-
-        // Leave the choice of the optimal node order to the flattenTree function.
-        MakedictLog.i("Flattening the tree...");
-        ArrayList<PtNodeArray> flatNodes = BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
-
-        MakedictLog.i("Computing addresses...");
-        BinaryDictEncoderUtils.computeAddresses(dict, flatNodes);
-        MakedictLog.i("Checking PtNode array...");
-        if (MakedictLog.DBG) BinaryDictEncoderUtils.checkFlatPtNodeArrayList(flatNodes);
-
-        // Create a buffer that matches the final dictionary size.
-        final PtNodeArray lastNodeArray = flatNodes.get(flatNodes.size() - 1);
-        final int bufferSize = lastNodeArray.mCachedAddressAfterUpdate + lastNodeArray.mCachedSize;
-        mBuffer = new byte[bufferSize];
-
-        MakedictLog.i("Writing file...");
-
-        for (PtNodeArray nodeArray : flatNodes) {
-            BinaryDictEncoderUtils.writePlacedPtNodeArray(dict, this, nodeArray);
-        }
-        if (MakedictLog.DBG) BinaryDictEncoderUtils.showStatistics(flatNodes);
-        mOutStream.write(mBuffer, 0, mPosition);
-
-        MakedictLog.i("Done");
-        close();
-    }
-
-    @Override
-    public void setPosition(final int position) {
-        if (mBuffer == null || position < 0 || position >= mBuffer.length) return;
-        mPosition = position;
-    }
-
-    @Override
-    public int getPosition() {
-        return mPosition;
-    }
-
-    @Override
-    public void writePtNodeCount(final int ptNodeCount) {
-        final int countSize = BinaryDictIOUtils.getPtNodeCountSize(ptNodeCount);
-        if (countSize != 1 && countSize != 2) {
-            throw new RuntimeException("Strange size from getGroupCountSize : " + countSize);
-        }
-        final int encodedPtNodeCount = (countSize == 2) ?
-                (ptNodeCount | FormatSpec.LARGE_PTNODE_ARRAY_SIZE_FIELD_SIZE_FLAG) : ptNodeCount;
-        mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, encodedPtNodeCount,
-                countSize);
-    }
-
-    private void writePtNodeFlags(final PtNode ptNode) {
-        final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
-        mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition,
-                BinaryDictEncoderUtils.makePtNodeFlags(ptNode, childrenPos),
-                FormatSpec.PTNODE_FLAGS_SIZE);
-    }
-
-    private void writeCharacters(final int[] codePoints, final boolean hasSeveralChars) {
-        mPosition = CharEncoding.writeCharArray(codePoints, mBuffer, mPosition);
-        if (hasSeveralChars) {
-            mBuffer[mPosition++] = FormatSpec.PTNODE_CHARACTERS_TERMINATOR;
-        }
-    }
-
-    private void writeFrequency(final int frequency) {
-        if (frequency >= 0) {
-            mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, frequency,
-                    FormatSpec.PTNODE_FREQUENCY_SIZE);
-        }
-    }
-
-    private void writeChildrenPosition(final PtNode ptNode) {
-        final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode);
-        mPosition += BinaryDictEncoderUtils.writeChildrenPosition(mBuffer, mPosition,
-                childrenPos);
-    }
-
-    /**
-     * Write a shortcut attributes list to mBuffer.
-     *
-     * @param shortcuts the shortcut attributes list.
-     */
-    private void writeShortcuts(final ArrayList<WeightedString> shortcuts) {
-        if (null == shortcuts || shortcuts.isEmpty()) return;
-
-        final int indexOfShortcutByteSize = mPosition;
-        mPosition += FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE;
-        final Iterator<WeightedString> shortcutIterator = shortcuts.iterator();
-        while (shortcutIterator.hasNext()) {
-            final WeightedString target = shortcutIterator.next();
-            final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags(
-                    shortcutIterator.hasNext(),
-                    target.getProbability());
-            mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, shortcutFlags,
-                    FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
-            final int shortcutShift = CharEncoding.writeString(mBuffer, mPosition, target.mWord);
-            mPosition += shortcutShift;
-        }
-        final int shortcutByteSize = mPosition - indexOfShortcutByteSize;
-        if (shortcutByteSize > FormatSpec.MAX_SHORTCUT_LIST_SIZE_IN_A_PTNODE) {
-            throw new RuntimeException("Shortcut list too large");
-        }
-        BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, indexOfShortcutByteSize, shortcutByteSize,
-                FormatSpec.PTNODE_SHORTCUT_LIST_SIZE_SIZE);
-    }
-
-    /**
-     * Write a bigram attributes list to mBuffer.
-     *
-     * @param bigrams the bigram attributes list.
-     * @param dict the dictionary the node array is a part of (for relative offsets).
-     */
-    private void writeBigrams(final ArrayList<WeightedString> bigrams,
-            final FusionDictionary dict) {
-        if (bigrams == null) return;
-
-        final Iterator<WeightedString> bigramIterator = bigrams.iterator();
-        while (bigramIterator.hasNext()) {
-            final WeightedString bigram = bigramIterator.next();
-            final PtNode target =
-                    FusionDictionary.findWordInTree(dict.mRootNodeArray, bigram.mWord);
-            final int addressOfBigram = target.mCachedAddressAfterUpdate;
-            final int unigramFrequencyForThisWord = target.getProbability();
-            final int offset = addressOfBigram
-                    - (mPosition + FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
-            final int bigramFlags = BinaryDictEncoderUtils.makeBigramFlags(bigramIterator.hasNext(),
-                    offset, bigram.getProbability(), unigramFrequencyForThisWord, bigram.mWord);
-            mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, bigramFlags,
-                    FormatSpec.PTNODE_ATTRIBUTE_FLAGS_SIZE);
-            mPosition += BinaryDictEncoderUtils.writeChildrenPosition(mBuffer, mPosition,
-                    Math.abs(offset));
-        }
-    }
-
-    @Override
-    public void writeForwardLinkAddress(final int forwardLinkAddress) {
-        mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition, forwardLinkAddress,
-                FormatSpec.FORWARD_LINK_ADDRESS_SIZE);
-    }
-
-    @Override
-    public void writePtNode(final PtNode ptNode, final FusionDictionary dict) {
-        writePtNodeFlags(ptNode);
-        writeCharacters(ptNode.mChars, ptNode.hasSeveralChars());
-        writeFrequency(ptNode.getProbability());
-        writeChildrenPosition(ptNode);
-        writeShortcuts(ptNode.mShortcutTargets);
-        writeBigrams(ptNode.mBigrams, dict);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 5e8417e..746431d 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -18,7 +18,7 @@
 
 import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.common.FileUtils;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -33,12 +33,7 @@
     final File mDictDirectory;
 
     @UsedForTesting
-    /* package */ Ver4DictDecoder(final File dictDirectory, final int factoryFlag) {
-        this(dictDirectory, null /* factory */);
-    }
-
-    @UsedForTesting
-    /* package */ Ver4DictDecoder(final File dictDirectory, final DictionaryBufferFactory factory) {
+    /* package */ Ver4DictDecoder(final File dictDirectory) {
         mDictDirectory = dictDirectory;
 
     }
@@ -88,21 +83,18 @@
 
         // Insert unigrams into the fusion dictionary.
         for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mIsBlacklistEntry) {
-                fusionDict.addBlacklistEntry(wordProperty.mWord, wordProperty.mShortcutTargets,
-                        wordProperty.mIsNotAWord);
-            } else {
-                fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
-                        wordProperty.mShortcutTargets, wordProperty.mIsNotAWord);
-            }
+            fusionDict.add(wordProperty.mWord, wordProperty.mProbabilityInfo,
+                    wordProperty.mIsNotAWord,
+                    wordProperty.mIsPossiblyOffensive);
         }
         // Insert bigrams into the fusion dictionary.
+        // TODO: Support ngrams.
         for (final WordProperty wordProperty : wordProperties) {
-            if (wordProperty.mBigrams == null) {
+            if (!wordProperty.mHasNgrams) {
                 continue;
             }
             final String word0 = wordProperty.mWord;
-            for (final WeightedString bigram : wordProperty.mBigrams) {
+            for (final WeightedString bigram : wordProperty.getBigrams()) {
                 fusionDict.setBigram(word0, bigram.mWord, bigram.mProbabilityInfo);
             }
         }
diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
deleted file mode 100644
index 76eaef4..0000000
--- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ /dev/null
@@ -1,150 +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.makedict;
-
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
-import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.LocaleUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * An implementation of DictEncoder for version 4 binary dictionary.
- */
-@UsedForTesting
-public class Ver4DictEncoder implements DictEncoder {
-    private final File mDictPlacedDir;
-
-    @UsedForTesting
-    public Ver4DictEncoder(final File dictPlacedDir) {
-        mDictPlacedDir = dictPlacedDir;
-    }
-
-    // TODO: This builds a FusionDictionary first and iterates it to add words to the binary
-    // dictionary. However, it is possible to just add words directly to the binary dictionary
-    // instead.
-    // In the long run, when we stop supporting version 2, FusionDictionary will become deprecated
-    // and we can remove it. Then we'll be able to just call BinaryDictionary directly.
-    @Override
-    public void writeDictionary(FusionDictionary dict, FormatOptions formatOptions)
-            throws IOException, UnsupportedFormatException {
-        if (formatOptions.mVersion != FormatSpec.VERSION4) {
-            throw new UnsupportedFormatException("File header has a wrong version number : "
-                    + formatOptions.mVersion);
-        }
-        if (!mDictPlacedDir.isDirectory()) {
-            throw new UnsupportedFormatException("Given path is not a directory.");
-        }
-        if (!BinaryDictionaryUtils.createEmptyDictFile(mDictPlacedDir.getAbsolutePath(),
-                FormatSpec.VERSION4, LocaleUtils.constructLocaleFromString(
-                dict.mOptions.mAttributes.get(DictionaryHeader.DICTIONARY_LOCALE_KEY)),
-                dict.mOptions.mAttributes)) {
-            throw new IOException("Cannot create dictionary file : "
-                + mDictPlacedDir.getAbsolutePath());
-        }
-        final BinaryDictionary binaryDict = new BinaryDictionary(mDictPlacedDir.getAbsolutePath(),
-                0l, mDictPlacedDir.length(), true /* useFullEditDistance */,
-                LocaleUtils.constructLocaleFromString(dict.mOptions.mAttributes.get(
-                        DictionaryHeader.DICTIONARY_LOCALE_KEY)),
-                Dictionary.TYPE_USER /* Dictionary type. Does not matter for us */,
-                true /* isUpdatable */);
-        if (!binaryDict.isValidDictionary()) {
-            // Somehow createEmptyDictFile returned true, but the file was not created correctly
-            throw new IOException("Cannot create dictionary file");
-        }
-        for (final WordProperty wordProperty : dict) {
-            // TODO: switch to addMultipleDictionaryEntries when they support shortcuts
-            if (null == wordProperty.mShortcutTargets || wordProperty.mShortcutTargets.isEmpty()) {
-                if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(),
-                        null /* shortcutTarget */, 0 /* shortcutProbability */,
-                        wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
-                        wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
-                    MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord);
-                }
-            } else {
-                for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) {
-                    if (!binaryDict.addUnigramEntry(wordProperty.mWord,
-                            wordProperty.getProbability(),
-                            shortcutTarget.mWord, shortcutTarget.getProbability(),
-                            wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord,
-                            wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) {
-                        MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord
-                                + ", shortcutTarget: " + shortcutTarget.mWord);
-                        return;
-                    }
-                }
-            }
-            if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
-                if (!binaryDict.flushWithGC()) {
-                    MakedictLog.e("Cannot flush dict with GC.");
-                    return;
-                }
-            }
-        }
-        for (final WordProperty word0Property : dict) {
-            if (null == word0Property.mBigrams) continue;
-            for (final WeightedString word1 : word0Property.mBigrams) {
-                final PrevWordsInfo prevWordsInfo =
-                        new PrevWordsInfo(new PrevWordsInfo.WordInfo(word0Property.mWord));
-                if (!binaryDict.addNgramEntry(prevWordsInfo, word1.mWord,
-                        word1.getProbability(), 0 /* timestamp */)) {
-                    MakedictLog.e("Cannot add n-gram entry for "
-                            + prevWordsInfo + " -> " + word1.mWord);
-                    return;
-                }
-                if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) {
-                    if (!binaryDict.flushWithGC()) {
-                        MakedictLog.e("Cannot flush dict with GC.");
-                        return;
-                    }
-                }
-            }
-        }
-        if (!binaryDict.flushWithGC()) {
-            MakedictLog.e("Cannot flush dict with GC.");
-            return;
-        }
-        binaryDict.close();
-    }
-
-    @Override
-    public void setPosition(int position) {
-    }
-
-    @Override
-    public int getPosition() {
-        return 0;
-    }
-
-    @Override
-    public void writePtNodeCount(int ptNodeCount) {
-    }
-
-    @Override
-    public void writeForwardLinkAddress(int forwardLinkAddress) {
-    }
-
-    @Override
-    public void writePtNode(PtNode ptNode, FusionDictionary dict) {
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
new file mode 100644
index 0000000..8f24cdb
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/network/BlockingHttpClientTests.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.network.BlockingHttpClient.ResponseProcessor;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Tests for {@link BlockingHttpClient}.
+ */
+@SmallTest
+public class BlockingHttpClientTests extends AndroidTestCase {
+    @Mock HttpURLConnection mMockHttpConnection;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testError_badGateway() throws IOException, AuthException {
+        when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_BAD_GATEWAY);
+        final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+        final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+        try {
+            client.execute(null /* empty request */, processor);
+            fail("Expecting an HttpException");
+        } catch (HttpException e) {
+            // expected HttpException
+            assertEquals(HttpURLConnection.HTTP_BAD_GATEWAY, e.getHttpStatusCode());
+        }
+    }
+
+    public void testError_clientTimeout() throws Exception {
+        when(mMockHttpConnection.getResponseCode()).thenReturn(
+                HttpURLConnection.HTTP_CLIENT_TIMEOUT);
+        final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+        final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+        try {
+            client.execute(null /* empty request */, processor);
+            fail("Expecting an HttpException");
+        } catch (HttpException e) {
+            // expected HttpException
+            assertEquals(HttpURLConnection.HTTP_CLIENT_TIMEOUT, e.getHttpStatusCode());
+        }
+    }
+
+    public void testError_forbiddenWithRequest() throws Exception {
+        final OutputStream mockOutputStream = Mockito.mock(OutputStream.class);
+        when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_FORBIDDEN);
+        when(mMockHttpConnection.getOutputStream()).thenReturn(mockOutputStream);
+        final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+        final FakeErrorResponseProcessor processor = new FakeErrorResponseProcessor();
+
+        try {
+            client.execute(new byte[100], processor);
+            fail("Expecting an HttpException");
+        } catch (HttpException e) {
+            assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getHttpStatusCode());
+        }
+        verify(mockOutputStream).write(any(byte[].class), eq(0), eq(100));
+    }
+
+    public void testSuccess_emptyRequest() throws Exception {
+        final Random rand = new Random();
+        byte[] response = new byte[100];
+        rand.nextBytes(response);
+        when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
+        when(mMockHttpConnection.getInputStream()).thenReturn(new ByteArrayInputStream(response));
+        final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+        final FakeSuccessResponseProcessor processor =
+                new FakeSuccessResponseProcessor(response);
+
+        client.execute(null /* empty request */, processor);
+        assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
+    }
+
+    public void testSuccess() throws Exception {
+        final OutputStream mockOutputStream = Mockito.mock(OutputStream.class);
+        final Random rand = new Random();
+        byte[] response = new byte[100];
+        rand.nextBytes(response);
+        when(mMockHttpConnection.getOutputStream()).thenReturn(mockOutputStream);
+        when(mMockHttpConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
+        when(mMockHttpConnection.getInputStream()).thenReturn(new ByteArrayInputStream(response));
+        final BlockingHttpClient client = new BlockingHttpClient(mMockHttpConnection);
+        final FakeSuccessResponseProcessor processor =
+                new FakeSuccessResponseProcessor(response);
+
+        client.execute(new byte[100], processor);
+        assertTrue("ResponseProcessor was not invoked", processor.mInvoked);
+    }
+
+    static class FakeErrorResponseProcessor implements ResponseProcessor<Void> {
+        @Override
+        public Void onSuccess(InputStream response) {
+            fail("Expected an error but received success");
+            return null;
+        }
+    }
+
+    private static class FakeSuccessResponseProcessor implements ResponseProcessor<Void> {
+        private final byte[] mExpectedResponse;
+
+        boolean mInvoked;
+
+        FakeSuccessResponseProcessor(byte[] expectedResponse) {
+            mExpectedResponse = expectedResponse;
+        }
+
+        @Override
+        public Void onSuccess(InputStream response) {
+            try {
+                mInvoked = true;
+                BufferedInputStream in = new BufferedInputStream(response);
+                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+                int read = 0;
+                while ((read = in.read()) != -1) {
+                    buffer.write(read);
+                }
+                byte[] actualResponse = buffer.toByteArray();
+                in.close();
+                assertTrue("Response doesn't match",
+                        Arrays.equals(mExpectedResponse, actualResponse));
+            } catch (IOException ex) {
+                fail("IOException in onSuccess");
+            }
+            return null;
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java b/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java
new file mode 100644
index 0000000..5b3e78e
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/network/HttpUrlConnectionBuilderTests.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2014 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.network;
+
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_BI_DIRECTIONAL;
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_DOWNLOAD_ONLY;
+import static com.android.inputmethod.latin.network.HttpUrlConnectionBuilder.MODE_UPLOAD_ONLY;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+
+
+/**
+ * Tests for {@link HttpUrlConnectionBuilder}.
+ */
+@SmallTest
+public class HttpUrlConnectionBuilderTests extends AndroidTestCase {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testSetUrl_malformed() {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        try {
+            builder.setUrl("dadasd!@%@!:11");
+            fail("Expected a MalformedURLException.");
+        } catch (MalformedURLException e) {
+            // Expected
+        }
+    }
+
+    public void testSetConnectTimeout_invalid() {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        try {
+            builder.setConnectTimeout(-1);
+            fail("Expected an IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    public void testSetConnectTimeout() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("https://www.example.com");
+        builder.setConnectTimeout(8765);
+        HttpURLConnection connection = builder.build();
+        assertEquals(8765, connection.getConnectTimeout());
+    }
+
+    public void testSetReadTimeout_invalid() {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        try {
+            builder.setReadTimeout(-1);
+            fail("Expected an IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    public void testSetReadTimeout() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("https://www.example.com");
+        builder.setReadTimeout(8765);
+        HttpURLConnection connection = builder.build();
+        assertEquals(8765, connection.getReadTimeout());
+    }
+
+    public void testAddHeader() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("http://www.example.com");
+        builder.addHeader("some-random-key", "some-random-value");
+        HttpURLConnection connection = builder.build();
+        assertEquals("some-random-value", connection.getRequestProperty("some-random-key"));
+    }
+
+    public void testSetUseCache_notSet() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("http://www.example.com");
+        HttpURLConnection connection = builder.build();
+        assertFalse(connection.getUseCaches());
+    }
+
+    public void testSetUseCache_false() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("http://www.example.com");
+        HttpURLConnection connection = builder.build();
+        connection.setUseCaches(false);
+        assertFalse(connection.getUseCaches());
+    }
+
+    public void testSetUseCache_true() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("http://www.example.com");
+        HttpURLConnection connection = builder.build();
+        connection.setUseCaches(true);
+        assertTrue(connection.getUseCaches());
+    }
+
+    public void testSetMode_uploadOnly() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("http://www.example.com");
+        builder.setMode(MODE_UPLOAD_ONLY);
+        HttpURLConnection connection = builder.build();
+        assertTrue(connection.getDoInput());
+        assertFalse(connection.getDoOutput());
+    }
+
+    public void testSetMode_downloadOnly() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("https://www.example.com");
+        builder.setMode(MODE_DOWNLOAD_ONLY);
+        HttpURLConnection connection = builder.build();
+        assertFalse(connection.getDoInput());
+        assertTrue(connection.getDoOutput());
+    }
+
+    public void testSetMode_bidirectional() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("https://www.example.com");
+        builder.setMode(MODE_BI_DIRECTIONAL);
+        HttpURLConnection connection = builder.build();
+        assertTrue(connection.getDoInput());
+        assertTrue(connection.getDoOutput());
+    }
+
+    public void testSetAuthToken() throws IOException {
+        HttpUrlConnectionBuilder builder = new HttpUrlConnectionBuilder();
+        builder.setUrl("https://www.example.com");
+        builder.setAuthToken("some-random-auth-token");
+        HttpURLConnection connection = builder.build();
+        assertEquals("some-random-auth-token",
+                connection.getRequestProperty(HttpUrlConnectionBuilder.HTTP_HEADER_AUTHORIZATION));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
deleted file mode 100644
index 565fadb..0000000
--- a/tests/src/com/android/inputmethod/latin/personalization/ContextualDictionaryTests.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-/**
- * Unit tests for contextual dictionary
- */
-@LargeTest
-public class ContextualDictionaryTests extends AndroidTestCase {
-    private static final String TAG = ContextualDictionaryTests.class.getSimpleName();
-
-    private static final Locale LOCALE_EN_US = new Locale("en", "US");
-
-    private DictionaryFacilitator getDictionaryFacilitator() {
-        final ArrayList<String> dictTypes = new ArrayList<>();
-        dictTypes.add(Dictionary.TYPE_CONTEXTUAL);
-        final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
-        dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
-                new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
-        return dictionaryFacilitator;
-    }
-
-    public void testAddPhrase() {
-        final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
-        final String[] phrase = new String[] {"a", "b", "c", "d"};
-        final int probability = 100;
-        final int bigramProbabilityForWords = 150;
-        final int bigramProbabilityForPhrases = 200;
-        dictionaryFacilitator.addPhraseToContextualDictionary(
-                phrase, probability, bigramProbabilityForWords, bigramProbabilityForPhrases);
-        final ExpandableBinaryDictionary contextualDictionary =
-                dictionaryFacilitator.getSubDictForTesting(Dictionary.TYPE_CONTEXTUAL);
-        contextualDictionary.waitAllTasksForTests();
-        // Word
-        assertTrue(contextualDictionary.isInDictionary("a"));
-        assertTrue(contextualDictionary.isInDictionary("b"));
-        assertTrue(contextualDictionary.isInDictionary("c"));
-        assertTrue(contextualDictionary.isInDictionary("d"));
-        // Phrase
-        assertTrue(contextualDictionary.isInDictionary("a b c d"));
-        assertTrue(contextualDictionary.isInDictionary("b c d"));
-        assertTrue(contextualDictionary.isInDictionary("c d"));
-        assertFalse(contextualDictionary.isInDictionary("a b c"));
-        assertFalse(contextualDictionary.isInDictionary("abcd"));
-        // TODO: Add tests for probability.
-        // TODO: Add tests for n-grams.
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
deleted file mode 100644
index 0f2f981..0000000
--- a/tests/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryTests.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2014 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 java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.DictionaryFacilitator;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback;
-import com.android.inputmethod.latin.makedict.CodePointUtils;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-/**
- * Unit tests for personalization dictionary
- */
-@LargeTest
-public class PersonalizationDictionaryTests extends AndroidTestCase {
-    private static final String TAG = PersonalizationDictionaryTests.class.getSimpleName();
-
-    private static final Locale LOCALE_EN_US = new Locale("en", "US");
-    private static final String DUMMY_PACKAGE_NAME = "test.package.name";
-    private static final long TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS = 120;
-
-    private DictionaryFacilitator getDictionaryFacilitator() {
-        final ArrayList<String> dictTypes = new ArrayList<>();
-        dictTypes.add(Dictionary.TYPE_MAIN);
-        dictTypes.add(Dictionary.TYPE_PERSONALIZATION);
-        final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
-        dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes,
-                new HashMap<String, File>(), new HashMap<String, Map<String, String>>());
-        return dictionaryFacilitator;
-    }
-
-    public void testAddManyTokens() {
-        final DictionaryFacilitator dictionaryFacilitator = getDictionaryFacilitator();
-        dictionaryFacilitator.clearPersonalizationDictionary();
-        final int dataChunkCount = 20;
-        final int wordCountInOneChunk = 2000;
-        final Random random = new Random(System.currentTimeMillis());
-        final int[] codePointSet = CodePointUtils.LATIN_ALPHABETS_LOWER;
-
-        final SpacingAndPunctuations spacingAndPunctuations =
-                new SpacingAndPunctuations(getContext().getResources());
-
-        final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
-                System.currentTimeMillis());
-
-        for (int i = 0; i < dataChunkCount; i++) {
-            final ArrayList<String> tokens = new ArrayList<>();
-            for (int j = 0; j < wordCountInOneChunk; j++) {
-                tokens.add(CodePointUtils.generateWord(random, codePointSet));
-            }
-            final PersonalizationDataChunk personalizationDataChunk = new PersonalizationDataChunk(
-                    true /* inputByUser */, tokens, timeStampInSeconds, DUMMY_PACKAGE_NAME);
-            final CountDownLatch countDownLatch = new CountDownLatch(1);
-            final AddMultipleDictionaryEntriesCallback callback =
-                    new AddMultipleDictionaryEntriesCallback() {
-                        @Override
-                        public void onFinished() {
-                            countDownLatch.countDown();
-                        }
-                    };
-            dictionaryFacilitator.addEntriesToPersonalizationDictionary(personalizationDataChunk,
-                    spacingAndPunctuations, callback);
-            try {
-                countDownLatch.await(TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS,
-                        TimeUnit.SECONDS);
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
-            }
-        }
-        dictionaryFacilitator.flushPersonalizationDictionary();
-        try {
-            dictionaryFacilitator.waitForLoadingDictionariesForTesting(
-                    TIMEOUT_TO_WAIT_DICTIONARY_OPERATIONS_IN_SECONDS, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Interrupted while waiting for finishing dictionary operations.", e);
-        }
-        final String dictName = ExpandableBinaryDictionary.getDictName(
-                PersonalizationDictionary.NAME, LOCALE_EN_US, null /* dictFile */);
-        final File dictFile = ExpandableBinaryDictionary.getDictFile(
-                getContext(), dictName, null /* dictFile */);
-
-        final BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(),
-                0 /* offset */, 0 /* size */,
-                true /* useFullEditDistance */, LOCALE_EN_US, Dictionary.TYPE_PERSONALIZATION,
-                true /* isUpdatable */);
-        assertTrue(binaryDictionary.isValidDictionary());
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
index f87f3b4..559f286 100644
--- a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTests.java
@@ -21,19 +21,11 @@
 import android.util.Log;
 
 import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.PrevWordsInfo.WordInfo;
 import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
-import com.android.inputmethod.latin.utils.DistracterFilter;
-import com.android.inputmethod.latin.utils.FileUtils;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Locale;
 import java.util.Random;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Unit tests for UserHistoryDictionary
@@ -41,22 +33,47 @@
 @LargeTest
 public class UserHistoryDictionaryTests extends AndroidTestCase {
     private static final String TAG = UserHistoryDictionaryTests.class.getSimpleName();
-
-    private static final String[] CHARACTERS = {
-        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
-        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
-    };
+    private static final int WAIT_FOR_WRITING_FILE_IN_MILLISECONDS = 3000;
+    private static final String TEST_ACCOUNT = "account@example.com";
 
     private int mCurrentTime = 0;
 
+    private static void printAllFiles(final File dir) {
+        Log.d(TAG, dir.getAbsolutePath());
+        for (final File file : dir.listFiles()) {
+            Log.d(TAG, "  " + file.getName());
+        }
+    }
+
+    private static void assertDictionaryExists(final UserHistoryDictionary dict,
+            final File dictFile) {
+        Log.d(TAG, "waiting for writing ...");
+        dict.waitAllTasksForTests();
+        if (!dictFile.exists()) {
+            try {
+                Log.d(TAG, dictFile + " is not existing. Wait "
+                        + WAIT_FOR_WRITING_FILE_IN_MILLISECONDS + " ms for writing.");
+                printAllFiles(dictFile.getParentFile());
+                Thread.sleep(WAIT_FOR_WRITING_FILE_IN_MILLISECONDS);
+            } catch (final InterruptedException e) {
+                Log.e(TAG, "Interrupted during waiting for writing the dict file.");
+            }
+        }
+        assertTrue("Following dictionary file doesn't exist: " + dictFile, dictFile.exists());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         resetCurrentTimeForTestMode();
+        UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
+                UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
     }
 
     @Override
     protected void tearDown() throws Exception {
+        UserHistoryDictionaryTestsHelper.removeAllTestDictFiles(
+                UserHistoryDictionaryTestsHelper.TEST_LOCALE_PREFIX, mContext);
         stopTestModeInNativeCode();
         super.tearDown();
     }
@@ -66,20 +83,6 @@
         setCurrentTimeForTestMode(mCurrentTime);
     }
 
-    private void forcePassingShortTime() {
-        // 3 days.
-        final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(3);
-        mCurrentTime += timeToElapse;
-        setCurrentTimeForTestMode(mCurrentTime);
-    }
-
-    private void forcePassingLongTime() {
-        // 365 days.
-        final int timeToElapse = (int)TimeUnit.DAYS.toSeconds(365);
-        mCurrentTime += timeToElapse;
-        setCurrentTimeForTestMode(mCurrentTime);
-    }
-
     private static int setCurrentTimeForTestMode(final int currentTime) {
         return BinaryDictionaryUtils.setCurrentTimeForTest(currentTime);
     }
@@ -89,199 +92,122 @@
     }
 
     /**
-     * Generates a random word.
-     */
-    private static String generateWord(final int value) {
-        final int lengthOfChars = CHARACTERS.length;
-        StringBuilder builder = new StringBuilder();
-        long lvalue = Math.abs((long)value);
-        while (lvalue > 0) {
-            builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
-            lvalue /= lengthOfChars;
-        }
-        return builder.toString();
-    }
-
-    private static List<String> generateWords(final int number, final Random random) {
-        final HashSet<String> wordSet = new HashSet<>();
-        while (wordSet.size() < number) {
-            wordSet.add(generateWord(random.nextInt()));
-        }
-        return new ArrayList<>(wordSet);
-    }
-
-    private static void addToDict(final UserHistoryDictionary dict, final List<String> words) {
-        PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-        for (String word : words) {
-            UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true,
-                    (int)TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()),
-                    DistracterFilter.EMPTY_DISTRACTER_FILTER);
-            prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
-        }
-    }
-
-    /**
-     * @param checkContents if true, checks whether written words are actually in the dictionary
-     * or not.
-     */
-    private void addAndWriteRandomWords(final Locale locale, final int numberOfWords,
-            final Random random, final boolean checkContents) {
-        final List<String> words = generateWords(numberOfWords, random);
-        final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
-                mContext, locale);
-        // Add random words to the user history dictionary.
-        addToDict(dict, words);
-        if (checkContents) {
-            dict.waitAllTasksForTests();
-            for (int i = 0; i < numberOfWords; ++i) {
-                final String word = words.get(i);
-                assertTrue(dict.isInDictionary(word));
-            }
-        }
-        // write to file.
-        dict.close();
-    }
-
-    /**
      * Clear all entries in the user history dictionary.
-     * @param locale dummy locale for testing.
+     * @param dict the user history dictionary.
      */
-    private void clearHistory(final Locale locale) {
-        final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
-                mContext, locale);
+    private static void clearHistory(final UserHistoryDictionary dict) {
         dict.waitAllTasksForTests();
         dict.clear();
         dict.close();
         dict.waitAllTasksForTests();
     }
 
-    /**
-     * Shut down executer and wait until all operations of user history are done.
-     * @param locale dummy locale for testing.
-     */
-    private void waitForWriting(final Locale locale) {
-        final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
-                mContext, locale);
-        dict.waitAllTasksForTests();
-    }
-
-    public void testRandomWords() {
+    private void doTestRandomWords(final String testAccount) {
         Log.d(TAG, "This test can be used for profiling.");
         Log.d(TAG, "Usage: please set UserHistoryDictionary.PROFILE_SAVE_RESTORE to true.");
-        final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
-        final String dictName = ExpandableBinaryDictionary.getDictName(
-                UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+        final Locale dummyLocale = UserHistoryDictionaryTestsHelper.getDummyLocale("random_words");
+        final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+                UserHistoryDictionary.NAME, dummyLocale,
+                null /* dictFile */,
+                testAccount /* account */);
         final File dictFile = ExpandableBinaryDictionary.getDictFile(
                 mContext, dictName, null /* dictFile */);
+        final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+                getContext(), dummyLocale, testAccount);
+        clearHistory(dict);
 
         final int numberOfWords = 1000;
         final Random random = new Random(123456);
+        assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(
+                dict, numberOfWords, random, true /* checksContents */, mCurrentTime));
+        assertDictionaryExists(dict, dictFile);
+    }
 
-        try {
-            clearHistory(dummyLocale);
-            addAndWriteRandomWords(dummyLocale, numberOfWords, random,
-                    true /* checksContents */);
-        } finally {
-            Log.d(TAG, "waiting for writing ...");
-            waitForWriting(dummyLocale);
-            assertTrue("check exisiting of " + dictFile, dictFile.exists());
-            FileUtils.deleteRecursively(dictFile);
-        }
+    public void testRandomWords_NullAccount() {
+        doTestRandomWords(null /* testAccount */);
+    }
+
+    public void testRandomWords() {
+        doTestRandomWords(TEST_ACCOUNT);
     }
 
     public void testStressTestForSwitchingLanguagesAndAddingWords() {
+        doTestStressTestForSwitchingLanguagesAndAddingWords(TEST_ACCOUNT);
+    }
+
+    public void testStressTestForSwitchingLanguagesAndAddingWords_NullAccount() {
+        doTestStressTestForSwitchingLanguagesAndAddingWords(null /* testAccount */);
+    }
+
+    private void doTestStressTestForSwitchingLanguagesAndAddingWords(final String testAccount) {
         final int numberOfLanguages = 2;
         final int numberOfLanguageSwitching = 80;
         final int numberOfWordsInsertedForEachLanguageSwitch = 100;
 
         final File dictFiles[] = new File[numberOfLanguages];
-        final Locale dummyLocales[] = new Locale[numberOfLanguages];
+        final UserHistoryDictionary dicts[] = new UserHistoryDictionary[numberOfLanguages];
+
         try {
             final Random random = new Random(123456);
 
             // Create filename suffixes for this test.
             for (int i = 0; i < numberOfLanguages; i++) {
-                dummyLocales[i] = new Locale("test_switching_languages" + i);
-                final String dictName = ExpandableBinaryDictionary.getDictName(
-                        UserHistoryDictionary.NAME, dummyLocales[i], null /* dictFile */);
+                final Locale dummyLocale =
+                        UserHistoryDictionaryTestsHelper.getDummyLocale("switching_languages" + i);
+                final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+                        UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */,
+                        testAccount /* account */);
                 dictFiles[i] = ExpandableBinaryDictionary.getDictFile(
                         mContext, dictName, null /* dictFile */);
-                clearHistory(dummyLocales[i]);
+                dicts[i] = PersonalizationHelper.getUserHistoryDictionary(getContext(),
+                        dummyLocale, testAccount);
+                clearHistory(dicts[i]);
             }
 
             final long start = System.currentTimeMillis();
 
             for (int i = 0; i < numberOfLanguageSwitching; i++) {
                 final int index = i % numberOfLanguages;
-                // Switch languages to testFilenameSuffixes[index].
-                addAndWriteRandomWords(dummyLocales[index],
-                        numberOfWordsInsertedForEachLanguageSwitch, random,
-                        false /* checksContents */);
+                // Switch to dicts[index].
+                assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dicts[index],
+                        numberOfWordsInsertedForEachLanguageSwitch,
+                        random,
+                        false /* checksContents */,
+                        mCurrentTime));
             }
 
             final long end = System.currentTimeMillis();
             Log.d(TAG, "testStressTestForSwitchingLanguageAndAddingWords took "
                     + (end - start) + " ms");
         } finally {
-            Log.d(TAG, "waiting for writing ...");
             for (int i = 0; i < numberOfLanguages; i++) {
-                waitForWriting(dummyLocales[i]);
-            }
-            for (final File dictFile : dictFiles) {
-                assertTrue("check exisiting of " + dictFile, dictFile.exists());
-                FileUtils.deleteRecursively(dictFile);
+                assertDictionaryExists(dicts[i], dictFiles[i]);
             }
         }
     }
 
     public void testAddManyWords() {
-        final Locale dummyLocale = new Locale("test_random_words" + System.currentTimeMillis());
-        final String dictName = ExpandableBinaryDictionary.getDictName(
-                UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */);
+        doTestAddManyWords(TEST_ACCOUNT);
+    }
+
+    public void testAddManyWords_NullAccount() {
+        doTestAddManyWords(null /* testAccount */);
+    }
+
+    private void doTestAddManyWords(final String testAccount) {
+        final Locale dummyLocale =
+                UserHistoryDictionaryTestsHelper.getDummyLocale("many_random_words");
+        final String dictName = UserHistoryDictionary.getUserHistoryDictName(
+                UserHistoryDictionary.NAME, dummyLocale, null /* dictFile */, testAccount);
         final File dictFile = ExpandableBinaryDictionary.getDictFile(
                 mContext, dictName, null /* dictFile */);
         final int numberOfWords = 10000;
         final Random random = new Random(123456);
-        clearHistory(dummyLocale);
-        try {
-            addAndWriteRandomWords(dummyLocale, numberOfWords, random, true /* checksContents */);
-        } finally {
-            Log.d(TAG, "waiting for writing ...");
-            waitForWriting(dummyLocale);
-            assertTrue("check exisiting of " + dictFile, dictFile.exists());
-            FileUtils.deleteRecursively(dictFile);
-        }
+        final UserHistoryDictionary dict = PersonalizationHelper.getUserHistoryDictionary(
+                getContext(), dummyLocale, testAccount);
+        clearHistory(dict);
+        assertTrue(UserHistoryDictionaryTestsHelper.addAndWriteRandomWords(dict,
+                numberOfWords, random, true /* checksContents */, mCurrentTime));
+        assertDictionaryExists(dict, dictFile);
     }
-
-    public void testDecaying() {
-        final Locale dummyLocale = new Locale("test_decaying" + System.currentTimeMillis());
-        final int numberOfWords = 5000;
-        final Random random = new Random(123456);
-        resetCurrentTimeForTestMode();
-        clearHistory(dummyLocale);
-        final List<String> words = generateWords(numberOfWords, random);
-        final UserHistoryDictionary dict =
-                PersonalizationHelper.getUserHistoryDictionary(getContext(), dummyLocale);
-        dict.waitAllTasksForTests();
-        PrevWordsInfo prevWordsInfo = PrevWordsInfo.EMPTY_PREV_WORDS_INFO;
-        for (final String word : words) {
-            UserHistoryDictionary.addToDictionary(dict, prevWordsInfo, word, true, mCurrentTime,
-                    DistracterFilter.EMPTY_DISTRACTER_FILTER);
-            prevWordsInfo = prevWordsInfo.getNextPrevWordsInfo(new WordInfo(word));
-            dict.waitAllTasksForTests();
-            assertTrue(dict.isInDictionary(word));
-        }
-        forcePassingShortTime();
-        dict.runGCIfRequired();
-        dict.waitAllTasksForTests();
-        for (final String word : words) {
-            assertTrue(dict.isInDictionary(word));
-        }
-        forcePassingLongTime();
-        dict.runGCIfRequired();
-        dict.waitAllTasksForTests();
-        for (final String word : words) {
-            assertFalse(dict.isInDictionary(word));
-        }
-    }
-}
+}
\ No newline at end of file
diff --git a/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java
new file mode 100644
index 0000000..4b7b9bc
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/personalization/UserHistoryDictionaryTestsHelper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 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 android.content.Context;
+
+import com.android.inputmethod.latin.BinaryDictionary;
+import com.android.inputmethod.latin.NgramContext;
+import com.android.inputmethod.latin.NgramContext.WordInfo;
+import com.android.inputmethod.latin.common.FileUtils;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Random;
+
+/**
+ * Utility class for helping while running tests involving {@link UserHistoryDictionary}.
+ */
+public class UserHistoryDictionaryTestsHelper {
+
+    /**
+     * Locale prefix for generating dummy locales for tests.
+     */
+    public static final String TEST_LOCALE_PREFIX = "test-";
+
+    /**
+     * Characters for generating random words.
+     */
+    private static final String[] CHARACTERS = {
+        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
+        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
+    };
+
+    /**
+     * Remove all the test dictionary files created for the given locale.
+     */
+    public static void removeAllTestDictFiles(final String filter, final Context context) {
+        final FilenameFilter filenameFilter = new FilenameFilter() {
+            @Override
+            public boolean accept(final File dir, final String filename) {
+                return filename.startsWith(UserHistoryDictionary.NAME + "." + filter);
+            }
+        };
+        FileUtils.deleteFilteredFiles(context.getFilesDir(), filenameFilter);
+    }
+
+    /**
+     * Generates and writes random words to dictionary. Caller can be assured
+     * that the write tasks would be finished; and its success would be reflected
+     * in the returned boolean.
+     *
+     * @param dict {@link UserHistoryDictionary} to which words should be added.
+     * @param numberOfWords number of words to be added.
+     * @param random helps generate random words.
+     * @param checkContents if true, checks whether written words are actually in the dictionary.
+     * @param currentTime timestamp that would be used for adding the words.
+     * @returns true if all words have been written to dictionary successfully.
+     */
+    public static boolean addAndWriteRandomWords(final UserHistoryDictionary dict,
+            final int numberOfWords, final Random random, final boolean checkContents,
+            final int currentTime) {
+        final List<String> words = generateWords(numberOfWords, random);
+        // Add random words to the user history dictionary.
+        addWordsToDictionary(dict, words, currentTime);
+        boolean success = true;
+        if (checkContents) {
+            dict.waitAllTasksForTests();
+            for (int i = 0; i < numberOfWords; ++i) {
+                final String word = words.get(i);
+                if (!dict.isInDictionary(word)) {
+                    success = false;
+                    break;
+                }
+            }
+        }
+        // write to file.
+        dict.close();
+        dict.waitAllTasksForTests();
+        return success;
+    }
+
+    private static void addWordsToDictionary(final UserHistoryDictionary dict,
+            final List<String> words, final int timestamp) {
+        NgramContext ngramContext = NgramContext.getEmptyPrevWordsContext(
+                BinaryDictionary.MAX_PREV_WORD_COUNT_FOR_N_GRAM);
+        for (final String word : words) {
+            UserHistoryDictionary.addToDictionary(dict, ngramContext, word, true, timestamp);
+            ngramContext = ngramContext.getNextNgramContext(new WordInfo(word));
+        }
+    }
+
+    /**
+     * Creates unique test locale for using within tests.
+     */
+    public static Locale getDummyLocale(final String name) {
+        return new Locale(TEST_LOCALE_PREFIX + name + System.currentTimeMillis());
+    }
+
+    /**
+     * Generates random words.
+     *
+     * @param numberOfWords number of words to generate.
+     * @param random salt used for generating random words.
+     */
+    public static List<String> generateWords(final int numberOfWords, final Random random) {
+        final HashSet<String> wordSet = new HashSet<>();
+        while (wordSet.size() < numberOfWords) {
+            wordSet.add(generateWord(random.nextInt()));
+        }
+        return new ArrayList<>(wordSet);
+    }
+
+    /**
+     * Generates a random word.
+     */
+    private static String generateWord(final int value) {
+        final int lengthOfChars = CHARACTERS.length;
+        final StringBuilder builder = new StringBuilder();
+        long lvalue = Math.abs((long)value);
+        while (lvalue > 0) {
+            builder.append(CHARACTERS[(int)(lvalue % lengthOfChars)]);
+            lvalue /= lengthOfChars;
+        }
+        return builder.toString();
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
new file mode 100644
index 0000000..7a019c3
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 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.settings;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.widget.ListView;
+
+import com.android.inputmethod.latin.utils.ManagedProfileUtils;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@MediumTest
+public class AccountsSettingsFragmentTests
+        extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
+    private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
+    private static final long TEST_TIMEOUT_MILLIS = 5000;
+
+    @Mock private ManagedProfileUtils mManagedProfileUtils;
+
+    public AccountsSettingsFragmentTests() {
+        super(TestFragmentActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Initialize the mocks.
+        MockitoAnnotations.initMocks(this);
+        ManagedProfileUtils.setTestInstance(mManagedProfileUtils);
+
+        Intent intent = new Intent();
+        intent.putExtra(TestFragmentActivity.EXTRA_SHOW_FRAGMENT, FRAG_NAME);
+        setActivityIntent(intent);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        ManagedProfileUtils.setTestInstance(null);
+        super.tearDown();
+    }
+
+    public void testEmptyAccounts() {
+        final AccountsSettingsFragment fragment =
+                (AccountsSettingsFragment) getActivity().mFragment;
+        try {
+            fragment.createAccountPicker(new String[0], null, null /* listener */);
+            fail("Expected IllegalArgumentException, never thrown");
+        } catch (IllegalArgumentException expected) {
+            // Expected.
+        }
+    }
+
+    private static class DialogHolder {
+        AlertDialog mDialog;
+        DialogHolder() {}
+    }
+
+    public void testMultipleAccounts_noSettingsForManagedProfile() {
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(true);
+
+        final AccountsSettingsFragment fragment =
+                (AccountsSettingsFragment) getActivity().mFragment;
+        final AlertDialog dialog = initDialog(fragment, null).mDialog;
+        final ListView lv = dialog.getListView();
+
+        // Nothing to check/uncheck.
+        assertNull(fragment.findPreference(AccountsSettingsFragment.PREF_ACCCOUNT_SWITCHER));
+    }
+
+    public void testMultipleAccounts_noCurrentAccount() {
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
+
+        final AccountsSettingsFragment fragment =
+                (AccountsSettingsFragment) getActivity().mFragment;
+        final AlertDialog dialog = initDialog(fragment, null).mDialog;
+        final ListView lv = dialog.getListView();
+
+        // The 1st account should be checked by default.
+        assertEquals("checked-item", 0, lv.getCheckedItemPosition());
+        // There should be 4 accounts in the list.
+        assertEquals("count", 4, lv.getCount());
+        // The sign-out button shouldn't exist
+        assertEquals(View.GONE,
+                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+    }
+
+    public void testMultipleAccounts_currentAccount() {
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
+
+        final AccountsSettingsFragment fragment =
+                (AccountsSettingsFragment) getActivity().mFragment;
+        final AlertDialog dialog = initDialog(fragment, "3@example.com").mDialog;
+        final ListView lv = dialog.getListView();
+
+        // The 3rd account should be checked by default.
+        assertEquals("checked-item", 2, lv.getCheckedItemPosition());
+        // There should be 4 accounts in the list.
+        assertEquals("count", 4, lv.getCount());
+        // The sign-out button should be shown
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+    }
+
+    private DialogHolder initDialog(
+            final AccountsSettingsFragment fragment,
+            final String selectedAccount) {
+        final DialogHolder dialogHolder = new DialogHolder();
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final AlertDialog dialog = fragment.createAccountPicker(
+                        new String[] {
+                                "1@example.com",
+                                "2@example.com",
+                                "3@example.com",
+                                "4@example.com"},
+                        selectedAccount, null /* positiveButtonListner */);
+                dialog.show();
+                dialogHolder.mDialog = dialog;
+                latch.countDown();
+            }
+        });
+
+        try {
+            latch.await(TEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException ex) {
+            fail();
+        }
+        getInstrumentation().waitForIdleSync();
+        return dialogHolder;
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
index eb76032..ed632db 100644
--- a/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
@@ -20,9 +20,8 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.utils.RunInLocale;
 
 import junit.framework.AssertionFailedError;
@@ -37,13 +36,11 @@
     private int mScreenMetrics;
 
     private boolean isPhone() {
-        return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_PHONE
-                || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_PHONE;
+        return Constants.isPhone(mScreenMetrics);
     }
 
     private boolean isTablet() {
-        return mScreenMetrics == Constants.SCREEN_METRICS_SMALL_TABLET
-                || mScreenMetrics == Constants.SCREEN_METRICS_LARGE_TABLET;
+        return Constants.isTablet(mScreenMetrics);
     }
 
     private SpacingAndPunctuations ENGLISH;
@@ -70,7 +67,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mScreenMetrics = mContext.getResources().getInteger(R.integer.config_screen_metrics);
+        mScreenMetrics = Settings.readScreenMetrics(getContext().getResources());
 
         // Language only
         ENGLISH = getSpacingAndPunctuations(Locale.ENGLISH);
diff --git a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
index 2272d6b..e7c48da 100644
--- a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
+++ b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
@@ -53,14 +53,8 @@
         sleep(1000);
 
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
-        // If no span, the following will crash
-        final String[] suggestions = span.getSuggestions();
-        // For this test we consider "годп" should yield at least 2 suggestions (at this moment
-        // it yields 5).
-        assertTrue(suggestions.length >= 2);
-        // We also assume the top suggestion should be "года", which is the top word in the
-        // Russian dictionary.
-        assertEquals("", "года", suggestions[0]);
+        // We don't ship with Russian LM
+        assertNull(span.getSpan());
     }
 
     public void testSpellcheckWithPeriods() {
diff --git a/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java b/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java
new file mode 100644
index 0000000..e5c8139
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/spellcheck/UserDictionaryLookupTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015 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.spellcheck;
+
+import android.annotation.SuppressLint;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.UserDictionary;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import java.util.HashSet;
+import java.util.Locale;
+
+/**
+ * Unit tests for {@link UserDictionaryLookup}.
+ *
+ * Note, this test doesn't mock out the ContentResolver, in order to make sure UserDictionaryLookup
+ * works in a real setting.
+ */
+@SmallTest
+public class UserDictionaryLookupTest extends AndroidTestCase {
+    private static final String TAG = UserDictionaryLookupTest.class.getSimpleName();
+
+    private ContentResolver mContentResolver;
+    private HashSet<Uri> mAddedBackup;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContentResolver = mContext.getContentResolver();
+        mAddedBackup = new HashSet<Uri>();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Remove all entries added during this test.
+        for (Uri row : mAddedBackup) {
+            mContentResolver.delete(row, null, null);
+        }
+        mAddedBackup.clear();
+
+        super.tearDown();
+    }
+
+    /**
+     * Adds the given word to UserDictionary.
+     *
+     * @param word the word to add
+     * @param locale the locale of the word to add
+     * @param frequency the frequency of the word to add
+     * @return the Uri for the given word
+     */
+    @SuppressLint("NewApi")
+    private Uri addWord(final String word, final Locale locale, int frequency) {
+        // Add the given word for the given locale.
+        UserDictionary.Words.addWord(mContext, word, frequency, null, locale);
+        // Obtain an Uri for the given word.
+        Cursor cursor = mContentResolver.query(UserDictionary.Words.CONTENT_URI, null,
+                UserDictionary.Words.WORD + "='" + word + "'", null, null);
+        assertTrue(cursor.moveToFirst());
+        Uri uri = Uri.withAppendedPath(UserDictionary.Words.CONTENT_URI,
+                cursor.getString(cursor.getColumnIndex(UserDictionary.Words._ID)));
+        // Add the row to the backup for later clearing.
+        mAddedBackup.add(uri);
+        return uri;
+    }
+
+    /**
+     * Deletes the entry for the given word from UserDictionary.
+     *
+     * @param uri the Uri for the word as returned by addWord
+     */
+    private void deleteWord(Uri uri) {
+        // Remove the word from the backup so that it's not cleared again later.
+        mAddedBackup.remove(uri);
+        // Remove the word from UserDictionary.
+        mContentResolver.delete(uri, null, null);
+    }
+
+    public void testExactLocaleMatch() {
+        Log.d(TAG, "testExactLocaleMatch");
+
+        // Insert "Foo" as capitalized in the UserDictionary under en_US locale.
+        addWord("Foo", Locale.US, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // Any capitalization variation should match.
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+        assertTrue(lookup.isValidWord("Foo", Locale.US));
+        assertTrue(lookup.isValidWord("FOO", Locale.US));
+        // But similar looking words don't match.
+        assertFalse(lookup.isValidWord("fo", Locale.US));
+        assertFalse(lookup.isValidWord("fop", Locale.US));
+        assertFalse(lookup.isValidWord("fooo", Locale.US));
+        // Other locales, including more general locales won't match.
+        assertFalse(lookup.isValidWord("foo", Locale.ENGLISH));
+        assertFalse(lookup.isValidWord("foo", Locale.UK));
+        assertFalse(lookup.isValidWord("foo", Locale.FRENCH));
+        assertFalse(lookup.isValidWord("foo", new Locale("")));
+
+        lookup.close();
+    }
+
+    public void testSubLocaleMatch() {
+        Log.d(TAG, "testSubLocaleMatch");
+
+        // Insert "Foo" as capitalized in the UserDictionary under the en locale.
+        addWord("Foo", Locale.ENGLISH, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // Any capitalization variation should match for both en and en_US.
+        assertTrue(lookup.isValidWord("foo", Locale.ENGLISH));
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+        assertTrue(lookup.isValidWord("Foo", Locale.US));
+        assertTrue(lookup.isValidWord("FOO", Locale.US));
+        // But similar looking words don't match.
+        assertFalse(lookup.isValidWord("fo", Locale.US));
+        assertFalse(lookup.isValidWord("fop", Locale.US));
+        assertFalse(lookup.isValidWord("fooo", Locale.US));
+
+        lookup.close();
+    }
+
+    public void testAllLocalesMatch() {
+        Log.d(TAG, "testAllLocalesMatch");
+
+        // Insert "Foo" as capitalized in the UserDictionary under the all locales.
+        addWord("Foo", null, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // Any capitalization variation should match for fr, en and en_US.
+        assertTrue(lookup.isValidWord("foo", new Locale("")));
+        assertTrue(lookup.isValidWord("foo", Locale.FRENCH));
+        assertTrue(lookup.isValidWord("foo", Locale.ENGLISH));
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+        assertTrue(lookup.isValidWord("Foo", Locale.US));
+        assertTrue(lookup.isValidWord("FOO", Locale.US));
+        // But similar looking words don't match.
+        assertFalse(lookup.isValidWord("fo", Locale.US));
+        assertFalse(lookup.isValidWord("fop", Locale.US));
+        assertFalse(lookup.isValidWord("fooo", Locale.US));
+
+        lookup.close();
+    }
+
+    public void testMultipleLocalesMatch() {
+        Log.d(TAG, "testMultipleLocalesMatch");
+
+        // Insert "Foo" as capitalized in the UserDictionary under the en_US and en_CA and fr
+        // locales.
+        addWord("Foo", Locale.US, 17);
+        addWord("foO", Locale.CANADA, 17);
+        addWord("fOo", Locale.FRENCH, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // Both en_CA and en_US match.
+        assertTrue(lookup.isValidWord("foo", Locale.CANADA));
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+        assertTrue(lookup.isValidWord("foo", Locale.FRENCH));
+        // Other locales, including more general locales won't match.
+        assertFalse(lookup.isValidWord("foo", Locale.ENGLISH));
+        assertFalse(lookup.isValidWord("foo", Locale.UK));
+        assertFalse(lookup.isValidWord("foo", new Locale("")));
+
+        lookup.close();
+    }
+
+    public void testReload() {
+        Log.d(TAG, "testReload");
+
+        // Insert "foo".
+        Uri uri = addWord("foo", Locale.US, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // "foo" should match.
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+
+        // "bar" shouldn't match.
+        assertFalse(lookup.isValidWord("bar", Locale.US));
+
+        // Now delete "foo" and add "bar".
+        deleteWord(uri);
+        addWord("bar", Locale.US, 18);
+
+        // Wait a little bit before expecting a change. The time we wait should be greater than
+        // UserDictionaryLookup.RELOAD_DELAY_MS.
+        try {
+            Thread.sleep(UserDictionaryLookup.RELOAD_DELAY_MS + 1000);
+        } catch (InterruptedException e) {
+        }
+
+        // Perform lookups again. Reload should have occured.
+        //
+        // "foo" should not match.
+        assertFalse(lookup.isValidWord("foo", Locale.US));
+
+        // "bar" should match.
+        assertTrue(lookup.isValidWord("bar", Locale.US));
+
+        lookup.close();
+    }
+
+    public void testClose() {
+        Log.d(TAG, "testClose");
+
+        // Insert "foo".
+        Uri uri = addWord("foo", Locale.US, 17);
+
+        // Create the UserDictionaryLookup and wait until it's loaded.
+        UserDictionaryLookup lookup = new UserDictionaryLookup(mContext);
+        while (!lookup.isLoaded()) {
+        }
+
+        // "foo" should match.
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+
+        // "bar" shouldn't match.
+        assertFalse(lookup.isValidWord("bar", Locale.US));
+
+        // Now close (prevents further reloads).
+        lookup.close();
+
+        // Now delete "foo" and add "bar".
+        deleteWord(uri);
+        addWord("bar", Locale.US, 18);
+
+        // Wait a little bit before expecting a change. The time we wait should be greater than
+        // UserDictionaryLookup.RELOAD_DELAY_MS.
+        try {
+            Thread.sleep(UserDictionaryLookup.RELOAD_DELAY_MS + 1000);
+        } catch (InterruptedException e) {
+        }
+
+        // Perform lookups again. Reload should not have occurred.
+        //
+        // "foo" should stil match.
+        assertTrue(lookup.isValidWord("foo", Locale.US));
+
+        // "bar" should still not match.
+        assertFalse(lookup.isValidWord("bar", Locale.US));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
new file mode 100644
index 0000000..ad6bcc3
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.touchinputconsumer;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for GestureConsumer.NULL_GESTURE_CONSUMER.
+ */
+@SmallTest
+public class NullGestureConsumerTests extends AndroidTestCase {
+    /**
+     * Tests that GestureConsumer.NULL_GESTURE_CONSUMER indicates that it won't consume gesture data
+     * and that its methods don't raise exceptions even for invalid data.
+     */
+    public void testNullGestureConsumer() {
+        assertFalse(GestureConsumer.NULL_GESTURE_CONSUMER.willConsume());
+        GestureConsumer.NULL_GESTURE_CONSUMER.onInit(null, null);
+        GestureConsumer.NULL_GESTURE_CONSUMER.onGestureStarted(null, null);
+        GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCanceled();
+        GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCompleted(null);
+        GestureConsumer.NULL_GESTURE_CONSUMER.onImeSuggestionsProcessed(null, -1, -1, null);
+    }
+
+    /**
+     * Tests that newInstance returns NULL_GESTURE_CONSUMER for invalid input.
+     */
+    public void testNewInstanceGivesNullGestureConsumerForInvalidInputs() {
+        assertSame(GestureConsumer.NULL_GESTURE_CONSUMER,
+                GestureConsumer.newInstance(null, null, null, null));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
index 91c9c37..1db8395 100644
--- a/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java
@@ -16,6 +16,13 @@
 
 package com.android.inputmethod.latin.utils;
 
+import static com.android.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
+import static com.android.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
+
 import android.content.Context;
 import android.os.Build;
 import android.test.AndroidTestCase;
@@ -26,14 +33,6 @@
 
 import java.util.Locale;
 
-import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.ASCII_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.EMOJI_CAPABLE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
-import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue
-        .UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME;
-
 @SmallTest
 public class AdditionalSubtypeUtilsTests extends AndroidTestCase {
 
@@ -151,25 +150,25 @@
     }
 
     public void testRestorable() {
-        final InputMethodSubtype EN_UK_DVORAK =
+        final InputMethodSubtype EN_US_DVORAK =
                 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
                         Locale.US.toString(), "dvorak");
         final InputMethodSubtype ZZ_AZERTY =
                 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
                         SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
-        assertEnUsDvorak(EN_UK_DVORAK);
+        assertEnUsDvorak(EN_US_DVORAK);
         assertAzerty(ZZ_AZERTY);
 
         // Make sure the subtype can be stored and restored in a deterministic manner.
-        final InputMethodSubtype[] subtypes = { EN_UK_DVORAK, ZZ_AZERTY };
+        final InputMethodSubtype[] subtypes = { EN_US_DVORAK, ZZ_AZERTY };
         final String prefSubtype = AdditionalSubtypeUtils.createPrefSubtypes(subtypes);
         final InputMethodSubtype[] restoredSubtypes =
                 AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype);
         assertEquals(2, restoredSubtypes.length);
-        final InputMethodSubtype restored_EN_UK_DVORAK = restoredSubtypes[0];
+        final InputMethodSubtype restored_EN_US_DVORAK = restoredSubtypes[0];
         final InputMethodSubtype restored_ZZ_AZERTY = restoredSubtypes[1];
 
-        assertEnUsDvorak(restored_EN_UK_DVORAK);
+        assertEnUsDvorak(restored_EN_US_DVORAK);
         assertAzerty(restored_ZZ_AZERTY);
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
index 1501e94..170d643 100644
--- a/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java
@@ -22,14 +22,14 @@
 
 @MediumTest
 public class AsyncResultHolderTests extends AndroidTestCase {
-    private static final String TAG = AsyncResultHolderTests.class.getSimpleName();
+    static final String TAG = AsyncResultHolderTests.class.getSimpleName();
 
     private static final int TIMEOUT_IN_MILLISECONDS = 500;
     private static final int MARGIN_IN_MILLISECONDS = 250;
     private static final int DEFAULT_VALUE = 2;
     private static final int SET_VALUE = 1;
 
-    private <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
+    private static <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value,
             final long time) {
         new Thread(new Runnable() {
             @Override
diff --git a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
deleted file mode 100644
index a333ee9..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtilsTests.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.android.inputmethod.latin.BinaryDictionary;
-import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.makedict.FormatSpec;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-@LargeTest
-public class BinaryDictionaryUtilsTests extends AndroidTestCase {
-    private static final String TEST_DICT_FILE_EXTENSION = ".testDict";
-    private static final String TEST_LOCALE = "test";
-
-    private File createEmptyDictionaryAndGetFile(final String dictId,
-            final int formatVersion) throws IOException {
-        if (formatVersion == FormatSpec.VERSION4) {
-            return createEmptyVer4DictionaryAndGetFile(dictId);
-        } else {
-            throw new IOException("Dictionary format version " + formatVersion
-                    + " is not supported.");
-        }
-    }
-
-    private File createEmptyVer4DictionaryAndGetFile(final String dictId) throws IOException {
-        final File file = getDictFile(dictId);
-        FileUtils.deleteRecursively(file);
-        Map<String, String> attributeMap = new HashMap<>();
-        attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, dictId);
-        attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
-                String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
-        attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
-                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
-        if (BinaryDictionaryUtils.createEmptyDictFile(file.getAbsolutePath(), FormatSpec.VERSION4,
-                LocaleUtils.constructLocaleFromString(TEST_LOCALE), attributeMap)) {
-            return file;
-        } else {
-            throw new IOException("Empty dictionary " + file.getAbsolutePath()
-                    + " cannot be created.");
-        }
-    }
-
-    private File getDictFile(final String dictId) {
-        return new File(getContext().getCacheDir(), dictId + TEST_DICT_FILE_EXTENSION);
-    }
-
-    public void testRenameDictionary() {
-        final int formatVersion = FormatSpec.VERSION4;
-        File dictFile0 = null;
-        try {
-            dictFile0 = createEmptyDictionaryAndGetFile("MoveFromDictionary", formatVersion);
-        } catch (IOException e) {
-            fail("IOException while writing an initial dictionary : " + e);
-        }
-        final File dictFile1 = getDictFile("MoveToDictionary");
-        FileUtils.deleteRecursively(dictFile1);
-        assertTrue(BinaryDictionaryUtils.renameDict(dictFile0, dictFile1));
-        assertFalse(dictFile0.exists());
-        assertTrue(dictFile1.exists());
-        BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile1.getAbsolutePath(),
-                0 /* offset */, dictFile1.length(), true /* useFullEditDistance */,
-                Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */);
-        assertTrue(binaryDictionary.isValidDictionary());
-        assertTrue(binaryDictionary.getFormatVersion() == formatVersion);
-        binaryDictionary.close();
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
index c746c83..9680d85 100644
--- a/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/CapsModeUtilsTests.java
@@ -21,8 +21,8 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
 
+import com.android.inputmethod.latin.common.LocaleUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
-import com.android.inputmethod.latin.utils.LocaleUtils;
 
 import java.util.Locale;
 
@@ -124,5 +124,29 @@
         allPathsForCaps("Word. ", c | w, sp, false);
         // Armenian period : capitalize if MODE_SENTENCES
         allPathsForCaps("Word\u0589 ", c | w | s, sp, false);
+
+        // Test for sentence terminators
+        sp = job.runInLocale(res, Locale.ENGLISH);
+        allPathsForCaps("Word? ", c | w | s, sp, false);
+        allPathsForCaps("Word?", c | w | s, sp, true);
+        allPathsForCaps("Word?", c, sp, false);
+        allPathsForCaps("Word! ", c | w | s, sp, false);
+        allPathsForCaps("Word!", c | w | s, sp, true);
+        allPathsForCaps("Word!", c, sp, false);
+        allPathsForCaps("Word; ", c | w, sp, false);
+        allPathsForCaps("Word;", c | w, sp, true);
+        allPathsForCaps("Word;", c, sp, false);
+        // Test for sentence terminators in Greek
+        sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("el"));
+        allPathsForCaps("Word? ", c | w | s, sp, false);
+        allPathsForCaps("Word?", c | w | s, sp, true);
+        allPathsForCaps("Word?", c, sp, false);
+        allPathsForCaps("Word! ", c | w | s, sp, false);
+        allPathsForCaps("Word!", c | w | s, sp, true);
+        allPathsForCaps("Word!", c, sp, false);
+        // In Greek ";" is the question mark and it terminates the sentence
+        allPathsForCaps("Word; ", c | w | s, sp, false);
+        allPathsForCaps("Word;", c | w | s, sp, true);
+        allPathsForCaps("Word;", c, sp, false);
     }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
new file mode 100644
index 0000000..47fd5fe
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.common.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Tests for {@link CollectionUtils}.
+ */
+@SmallTest
+public class CollectionUtilsTests extends AndroidTestCase {
+    /**
+     * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} fails as expected
+     * with some invalid inputs.
+     */
+    public void testArrayAsListFailure() {
+        final String[] array = { "0", "1" };
+        // Negative start
+        try {
+            CollectionUtils.arrayAsList(array, -1, 1);
+            fail("Failed to catch start < 0");
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Invalid start: -1 end: 1 with array.length: 2", e.getMessage());
+        }
+        // start > end
+        try {
+            CollectionUtils.arrayAsList(array, 1, -1);
+            fail("Failed to catch start > end");
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Invalid start: 1 end: -1 with array.length: 2", e.getMessage());
+        }
+        // end > array.length
+        try {
+            CollectionUtils.arrayAsList(array, 1, 3);
+            fail("Failed to catch end > array.length");
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Invalid start: 1 end: 3 with array.length: 2", e.getMessage());
+        }
+    }
+
+    /**
+     * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} gives the expected
+     * results for a few valid inputs.
+     */
+    public void testArrayAsList() {
+        final ArrayList<String> empty = new ArrayList<>();
+        assertEquals(empty, CollectionUtils.arrayAsList(new String[] { }, 0, 0));
+        final String[] array = { "0", "1", "2", "3", "4" };
+        assertEquals(empty, CollectionUtils.arrayAsList(array, 0, 0));
+        assertEquals(empty, CollectionUtils.arrayAsList(array, 1, 1));
+        assertEquals(empty, CollectionUtils.arrayAsList(array, array.length, array.length));
+        final ArrayList<String> expected123 = new ArrayList<>(Arrays.asList("1", "2", "3"));
+        assertEquals(expected123, CollectionUtils.arrayAsList(array, 1, 4));
+    }
+
+    /**
+     * Tests that {@link CollectionUtils#isNullOrEmpty(java.util.Collection)} gives the expected
+     * results for a few cases.
+     */
+    public void testIsNullOrEmpty() {
+        assertTrue(CollectionUtils.isNullOrEmpty(null));
+        assertTrue(CollectionUtils.isNullOrEmpty(new ArrayList<>()));
+        assertTrue(CollectionUtils.isNullOrEmpty(Collections.EMPTY_SET));
+        assertFalse(CollectionUtils.isNullOrEmpty(Collections.singleton("Not empty")));
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
index 6e71607..812353c 100644
--- a/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/DictionaryInfoUtilsTests.java
@@ -20,6 +20,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.inputmethod.latin.common.LocaleUtils;
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 
 import java.util.Locale;
@@ -44,4 +45,21 @@
                 sp));
         assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("!!!", sp));
     }
+
+    public void testGetMainDictId() {
+        assertEquals("main:en",
+                DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en")));
+        assertEquals("main:en_us",
+                DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_US")));
+        assertEquals("main:en_gb",
+                DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_GB")));
+
+        assertEquals("main:es",
+                DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es")));
+        assertEquals("main:es_us",
+                DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es_US")));
+
+        assertEquals("main:en_us_posix", DictionaryInfoUtils.getMainDictId(
+                        LocaleUtils.constructLocaleFromString("en_US_POSIX")));
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java b/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
deleted file mode 100644
index 5831226..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/EditDistanceTests.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-@SmallTest
-public class EditDistanceTests extends AndroidTestCase {
-    /*
-     * dist(kitten, sitting) == 3
-     *
-     * kitten-
-     * .|||.|
-     * sitting
-     */
-    public void testExample1() {
-        final int dist = BinaryDictionaryUtils.editDistance("kitten", "sitting");
-        assertEquals("edit distance between 'kitten' and 'sitting' is 3",
-                3, dist);
-    }
-
-    /*
-     * dist(Sunday, Saturday) == 3
-     *
-     * Saturday
-     * |  |.|||
-     * S--unday
-     */
-    public void testExample2() {
-        final int dist = BinaryDictionaryUtils.editDistance("Saturday", "Sunday");
-        assertEquals("edit distance between 'Saturday' and 'Sunday' is 3",
-                3, dist);
-    }
-
-    public void testBothEmpty() {
-        final int dist = BinaryDictionaryUtils.editDistance("", "");
-        assertEquals("when both string are empty, no edits are needed",
-                0, dist);
-    }
-
-    public void testFirstArgIsEmpty() {
-        final int dist = BinaryDictionaryUtils.editDistance("", "aaaa");
-        assertEquals("when only one string of the arguments is empty,"
-                 + " the edit distance is the length of the other.",
-                 4, dist);
-    }
-
-    public void testSecoondArgIsEmpty() {
-        final int dist = BinaryDictionaryUtils.editDistance("aaaa", "");
-        assertEquals("when only one string of the arguments is empty,"
-                 + " the edit distance is the length of the other.",
-                 4, dist);
-    }
-
-    public void testSameStrings() {
-        final String arg1 = "The quick brown fox jumps over the lazy dog.";
-        final String arg2 = "The quick brown fox jumps over the lazy dog.";
-        final int dist = BinaryDictionaryUtils.editDistance(arg1, arg2);
-        assertEquals("when same strings are passed, distance equals 0.",
-                0, dist);
-    }
-
-    public void testSameReference() {
-        final String arg = "The quick brown fox jumps over the lazy dog.";
-        final int dist = BinaryDictionaryUtils.editDistance(arg, arg);
-        assertEquals("when same string references are passed, the distance equals 0.",
-                0, dist);
-    }
-
-    public void testNullArg() {
-        try {
-            BinaryDictionaryUtils.editDistance(null, "aaa");
-            fail("IllegalArgumentException should be thrown.");
-        } catch (Exception e) {
-            assertTrue(e instanceof IllegalArgumentException);
-        }
-        try {
-            BinaryDictionaryUtils.editDistance("aaa", null);
-            fail("IllegalArgumentException should be thrown.");
-        } catch (Exception e) {
-            assertTrue(e instanceof IllegalArgumentException);
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
index ae2623d..8692305 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ExecutorUtilsTests.java
@@ -25,18 +25,18 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
- * Unit tests for ExecutorUtils.
+ * Unit tests for {@link ExecutorUtils}.
  */
 @MediumTest
 public class ExecutorUtilsTests extends AndroidTestCase {
     private static final String TAG = ExecutorUtilsTests.class.getSimpleName();
 
-    private static final String TEST_EXECUTOR_ID = "test";
     private static final int NUM_OF_TASKS = 10;
     private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500;
 
     public void testExecute() {
-        final ExecutorService executor = ExecutorUtils.getExecutor(TEST_EXECUTOR_ID);
+        final ExecutorService executor =
+                ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD);
         final AtomicInteger v = new AtomicInteger(0);
         for (int i = 0; i < NUM_OF_TASKS; ++i) {
             executor.execute(new Runnable() {
diff --git a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
index 819d763..e361c77 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
@@ -16,24 +16,32 @@
 
 package com.android.inputmethod.latin.utils;
 
-import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE;
 import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_IMPORTANT_NOTICE_VERSION;
+import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
 
+import com.android.inputmethod.latin.settings.SettingsValues;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 import java.util.concurrent.TimeUnit;
 
-@SmallTest
+@MediumTest
 public class ImportantNoticeUtilsTests extends AndroidTestCase {
     // This should be aligned with R.integer.config_important_notice_version.
     private static final int CURRENT_IMPORTANT_NOTICE_VERSION = 1;
 
     private ImportantNoticePreferences mImportantNoticePreferences;
 
+    @Mock private SettingsValues mMockSettingsValues;
+
     private static class ImportantNoticePreferences {
         private final SharedPreferences mPref;
 
@@ -97,8 +105,10 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        MockitoAnnotations.initMocks(this);
         mImportantNoticePreferences = new ImportantNoticePreferences(getContext());
         mImportantNoticePreferences.save();
+        when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true);
     }
 
     @Override
@@ -112,11 +122,33 @@
                 ImportantNoticeUtils.getCurrentImportantNoticeVersion(getContext()));
     }
 
+    public void testStateAfterFreshInstall() {
+        mImportantNoticePreferences.clear();
+
+        // Check internal state of {@link ImportantNoticeUtils.shouldShowImportantNotice(Context)}
+        // after fresh install.
+        assertEquals("Has new important notice after fresh install", true,
+                ImportantNoticeUtils.hasNewImportantNotice(getContext()));
+        assertEquals("Next important notice title after fresh install", false, TextUtils.isEmpty(
+                ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
+        assertEquals("Is in system setup wizard after fresh install", false,
+                ImportantNoticeUtils.isInSystemSetupWizard(getContext()));
+        final long currentTimeMillis = System.currentTimeMillis();
+        assertEquals("Has timeout passed after fresh install", false,
+                ImportantNoticeUtils.hasTimeoutPassed(getContext(), currentTimeMillis));
+        assertEquals("Timestamp of first important notice after fresh install",
+                (Long)currentTimeMillis,
+                mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
+
+        assertEquals("Current boolean before update", true,
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+    }
+
     public void testUpdateVersion() {
         mImportantNoticePreferences.clear();
 
         assertEquals("Current boolean before update", true,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version before update", 0,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version before update ", 1,
@@ -129,7 +161,7 @@
         ImportantNoticeUtils.updateLastImportantNoticeVersion(getContext());
 
         assertEquals("Current boolean after update", false,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version after update", 1,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version after update", 2,
@@ -158,12 +190,12 @@
 
         // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout.
         assertEquals("Current boolean before timeout 1", true,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version before timeout 1", 0,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version before timeout 1", 1,
                 ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
-        assertEquals("Last time before timeout 1", (Long)lastTime,
+        assertEquals("Timestamp of first important notice before timeout 1", (Long)lastTime,
                 mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
         assertEquals("Current title before timeout 1", false, TextUtils.isEmpty(
                 ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -175,12 +207,12 @@
         // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout
         // again.
         assertEquals("Current boolean before timeout 2", true,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version before timeout 2", 0,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version before timeout 2", 1,
                 ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
-        assertEquals("Last time before timeout 2", (Long)lastTime,
+        assertEquals("Timestamp of first important notice before timeout 2", (Long)lastTime,
                 mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
         assertEquals("Current title before timeout 2", false, TextUtils.isEmpty(
                 ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -191,12 +223,12 @@
 
         // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout.
         assertEquals("Current boolean after timeout 1", false,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version after timeout 1", 1,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version after timeout 1", 2,
                 ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
-        assertEquals("Last time aflter timeout 1", null,
+        assertEquals("Timestamp of first important notice after timeout 1", null,
                 mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
         assertEquals("Current title after timeout 1", true, TextUtils.isEmpty(
                 ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
@@ -207,16 +239,30 @@
 
         // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout again.
         assertEquals("Current boolean after timeout 2", false,
-                ImportantNoticeUtils.shouldShowImportantNotice(getContext()));
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
         assertEquals("Last version after timeout 2", 1,
                 ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
         assertEquals("Next version after timeout 2", 2,
                 ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
-        assertEquals("Last time aflter timeout 2", null,
+        assertEquals("Timestamp of first important notice after timeout 2", null,
                 mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
         assertEquals("Current title after timeout 2", true, TextUtils.isEmpty(
                 ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
         assertEquals("Current contents after timeout 2", true, TextUtils.isEmpty(
                 ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
     }
+
+    public void testPersonalizationSetting() {
+        mImportantNoticePreferences.clear();
+
+        // Personalization enabled.
+        when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true);
+        assertEquals("Current boolean with personalization enabled", true,
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+
+        // Personalization disabled.
+        when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(false);
+        assertEquals("Current boolean with personalization disabled", false,
+                ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java
new file mode 100644
index 0000000..1941120
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/JsonUtilsTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SmallTest
+public class JsonUtilsTests extends AndroidTestCase {
+    public void testJsonUtils() {
+        final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
+        final List<Object> objArray = Arrays.asList(objs);
+        final String str = JsonUtils.listToJsonStr(objArray);
+        final List<Object> newObjArray = JsonUtils.jsonStrToList(str);
+        for (int i = 0; i < objs.length; ++i) {
+            assertEquals(objs[i], newObjArray.get(i));
+        }
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java
new file mode 100644
index 0000000..e4b6a66
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE;
+import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_LANGUAGE_ONLY;
+import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_NONE;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
+import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
+import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+import javax.annotation.Nonnull;
+
+@SmallTest
+public class LanguageOnSpacebarUtilsTests extends AndroidTestCase {
+    private RichInputMethodManager mRichImm;
+
+    RichInputMethodSubtype EN_US_QWERTY;
+    RichInputMethodSubtype EN_GB_QWERTY;
+    RichInputMethodSubtype FR_AZERTY;
+    RichInputMethodSubtype FR_CA_QWERTY;
+    RichInputMethodSubtype FR_CH_SWISS;
+    RichInputMethodSubtype FR_CH_QWERTY;
+    RichInputMethodSubtype FR_CH_QWERTZ;
+    RichInputMethodSubtype IW_HEBREW;
+    RichInputMethodSubtype ZZ_QWERTY;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final Context context = getContext();
+        RichInputMethodManager.init(context);
+        mRichImm = RichInputMethodManager.getInstance();
+
+        EN_US_QWERTY = findSubtypeOf(Locale.US.toString(), "qwerty");
+        EN_GB_QWERTY = findSubtypeOf(Locale.UK.toString(), "qwerty");
+        FR_AZERTY = findSubtypeOf(Locale.FRENCH.toString(), "azerty");
+        FR_CA_QWERTY = findSubtypeOf(Locale.CANADA_FRENCH.toString(), "qwerty");
+        FR_CH_SWISS = findSubtypeOf("fr_CH", "swiss");
+        FR_CH_QWERTZ = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwertz"));
+        FR_CH_QWERTY = new RichInputMethodSubtype(
+                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwerty"));
+        IW_HEBREW = findSubtypeOf("iw", "hebrew");
+        ZZ_QWERTY = findSubtypeOf(SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
+    }
+
+    @Nonnull
+    private RichInputMethodSubtype findSubtypeOf(final String localeString,
+            final String keyboardLayoutSetName) {
+        final InputMethodSubtype subtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                localeString, keyboardLayoutSetName);
+        if (subtype == null) {
+            throw new RuntimeException("Can't find subtype of " + localeString + " with "
+                    + keyboardLayoutSetName);
+        }
+        return new RichInputMethodSubtype(subtype);
+    }
+
+    private static void enableSubtypes(final RichInputMethodSubtype ... subtypes) {
+        final ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>();
+        for (final RichInputMethodSubtype subtype : subtypes) {
+            enabledSubtypes.add(subtype.getRawSubtype());
+        }
+        LanguageOnSpacebarUtils.setEnabledSubtypes(enabledSubtypes);
+    }
+
+    private static void assertFormatType(final RichInputMethodSubtype subtype,
+            final boolean implicitlyEnabledSubtype, final Locale systemLocale,
+            final int expectedFormat) {
+        LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale);
+        assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype
+                + " in " + systemLocale, expectedFormat,
+                LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype));
+    }
+
+    public void testOneSubtypeImplicitlyEnabled() {
+        enableSubtypes(EN_US_QWERTY);
+        assertFormatType(EN_US_QWERTY, true, Locale.US,            FORMAT_TYPE_NONE);
+
+        enableSubtypes(EN_GB_QWERTY);
+        assertFormatType(EN_GB_QWERTY, true, Locale.UK,            FORMAT_TYPE_NONE);
+
+        enableSubtypes(FR_AZERTY);
+        assertFormatType(FR_AZERTY,    true, Locale.FRANCE,        FORMAT_TYPE_NONE);
+
+        enableSubtypes(FR_CA_QWERTY);
+        assertFormatType(FR_CA_QWERTY, true, Locale.CANADA_FRENCH, FORMAT_TYPE_NONE);
+    }
+
+    public void testOneSubtypeExplicitlyEnabled() {
+        enableSubtypes(EN_US_QWERTY);
+        assertFormatType(EN_US_QWERTY, false, Locale.UK,     FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        enableSubtypes(EN_GB_QWERTY);
+        assertFormatType(EN_GB_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(EN_GB_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        enableSubtypes(FR_AZERTY);
+        assertFormatType(FR_AZERTY,    false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        enableSubtypes(FR_CA_QWERTY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE,        FORMAT_TYPE_LANGUAGE_ONLY);
+    }
+
+    public void testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype() {
+        final Locale Locale_IW = new Locale("iw");
+        enableSubtypes(IW_HEBREW, ZZ_QWERTY);
+        // TODO: Should this be FORMAT_TYPE_NONE?
+        assertFormatType(IW_HEBREW,    true, Locale_IW, FORMAT_TYPE_LANGUAGE_ONLY);
+        // TODO: Should this be FORMAT_TYPE_NONE?
+        assertFormatType(ZZ_QWERTY,    true, Locale_IW, FORMAT_TYPE_FULL_LOCALE);
+    }
+
+    public void testTwoSubtypesExplicitlyEnabled() {
+        enableSubtypes(EN_US_QWERTY, FR_AZERTY);
+        assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_AZERTY,    false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(EN_US_QWERTY, false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_AZERTY,    false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
+
+        enableSubtypes(EN_US_QWERTY, ZZ_QWERTY);
+        assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(ZZ_QWERTY,    false, Locale.US,     FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(ZZ_QWERTY,    false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+
+    }
+
+    public void testMultiSubtypeWithSameLanuageAndSameLayout() {
+        // Explicitly enable en_US, en_GB, fr_FR, and no language keyboards.
+        enableSubtypes(EN_US_QWERTY, EN_GB_QWERTY, FR_CA_QWERTY, ZZ_QWERTY);
+
+        assertFormatType(EN_US_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(EN_GB_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CA_QWERTY, false, Locale.US,    FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(ZZ_QWERTY,    false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
+
+        assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(EN_GB_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(ZZ_QWERTY,    false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+    }
+
+    public void testMultiSubtypesWithSameLanguageButHaveDifferentLayout() {
+        enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTZ);
+
+        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+    }
+
+    public void testMultiSubtypesWithSameLanguageAndMayHaveSameLayout() {
+        enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ);
+
+        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
+
+        assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+        assertFormatType(FR_CH_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
+        assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
index a3f2ce5..9b82683 100644
--- a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
@@ -19,7 +19,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.common.Constants;
 
 import java.util.Locale;
 
diff --git a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java b/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
deleted file mode 100644
index 8f58e68..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/ResizableIntArrayTests.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.Arrays;
-
-@SmallTest
-public class ResizableIntArrayTests extends AndroidTestCase {
-    private static final int DEFAULT_CAPACITY = 48;
-
-    public void testNewInstance() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int[] array = src.getPrimitiveArray();
-        assertEquals("new instance length", 0, src.getLength());
-        assertNotNull("new instance array", array);
-        assertEquals("new instance array length", DEFAULT_CAPACITY, array.length);
-    }
-
-    public void testAdd() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int[] array = src.getPrimitiveArray();
-        int[] array2 = null, array3 = null;
-        final int limit = DEFAULT_CAPACITY * 2 + 10;
-        for (int i = 0; i < limit; i++) {
-            final int value = i;
-            src.add(value);
-            assertEquals("length after add " + i, i + 1, src.getLength());
-            if (i == DEFAULT_CAPACITY) {
-                array2 = src.getPrimitiveArray();
-            }
-            if (i == DEFAULT_CAPACITY * 2) {
-                array3 = src.getPrimitiveArray();
-            }
-            if (i < DEFAULT_CAPACITY) {
-                assertSame("array after add " + i, array, src.getPrimitiveArray());
-            } else if (i < DEFAULT_CAPACITY * 2) {
-                assertSame("array after add " + i, array2, src.getPrimitiveArray());
-            } else if (i < DEFAULT_CAPACITY * 3) {
-                assertSame("array after add " + i, array3, src.getPrimitiveArray());
-            }
-        }
-        for (int i = 0; i < limit; i++) {
-            final int value = i;
-            assertEquals("value at " + i, value, src.get(i));
-        }
-    }
-
-    public void testAddAt() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int limit = DEFAULT_CAPACITY * 10, step = DEFAULT_CAPACITY * 2;
-        for (int i = 0; i < limit; i += step) {
-            final int value = i;
-            src.addAt(i, value);
-            assertEquals("length after add at " + i, i + 1, src.getLength());
-        }
-        for (int i = 0; i < limit; i += step) {
-            final int value = i;
-            assertEquals("value at " + i, value, src.get(i));
-        }
-    }
-
-    public void testGet() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        try {
-            final int value = src.get(0);
-            fail("get(0) shouldn't succeed");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            // success
-        }
-        try {
-            final int value = src.get(DEFAULT_CAPACITY);
-            fail("get(DEFAULT_CAPACITY) shouldn't succeed");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            // success
-        }
-
-        final int index = DEFAULT_CAPACITY / 2;
-        final int valueAddAt = 100;
-        src.addAt(index, valueAddAt);
-        assertEquals("legth after add at " + index, index + 1, src.getLength());
-        assertEquals("value after add at " + index, valueAddAt, src.get(index));
-        assertEquals("value after add at 0", 0, src.get(0));
-        try {
-            final int value = src.get(src.getLength());
-            fail("get(length) shouldn't succeed");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            // success
-        }
-    }
-
-    public void testReset() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int[] array = src.getPrimitiveArray();
-        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
-            final int value = i;
-            src.add(value);
-            assertEquals("length after add " + i, i + 1, src.getLength());
-        }
-
-        final int smallerLength = DEFAULT_CAPACITY / 2;
-        src.reset(smallerLength);
-        final int[] array2 = src.getPrimitiveArray();
-        assertEquals("length after reset", 0, src.getLength());
-        assertNotSame("array after reset", array, array2);
-
-        int[] array3 = null;
-        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
-            final int value = i;
-            src.add(value);
-            assertEquals("length after add " + i, i + 1, src.getLength());
-            if (i == smallerLength) {
-                array3 = src.getPrimitiveArray();
-            }
-            if (i < smallerLength) {
-                assertSame("array after add " + i, array2, src.getPrimitiveArray());
-            } else if (i < smallerLength * 2) {
-                assertSame("array after add " + i, array3, src.getPrimitiveArray());
-            }
-        }
-    }
-
-    public void testSetLength() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int[] array = src.getPrimitiveArray();
-        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
-            final int value = i;
-            src.add(value);
-            assertEquals("length after add " + i, i + 1, src.getLength());
-        }
-
-        final int largerLength = DEFAULT_CAPACITY * 2;
-        src.setLength(largerLength);
-        final int[] array2 = src.getPrimitiveArray();
-        assertEquals("length after larger setLength", largerLength, src.getLength());
-        assertNotSame("array after larger setLength", array, array2);
-        assertEquals("array length after larger setLength", largerLength, array2.length);
-        for (int i = 0; i < largerLength; i++) {
-            final int value = i;
-            if (i < DEFAULT_CAPACITY) {
-                assertEquals("value at " + i, value, src.get(i));
-            } else {
-                assertEquals("value at " + i, 0, src.get(i));
-            }
-        }
-
-        final int smallerLength = DEFAULT_CAPACITY / 2;
-        src.setLength(smallerLength);
-        final int[] array3 = src.getPrimitiveArray();
-        assertEquals("length after smaller setLength", smallerLength, src.getLength());
-        assertSame("array after smaller setLength", array2, array3);
-        assertEquals("array length after smaller setLength", largerLength, array3.length);
-        for (int i = 0; i < smallerLength; i++) {
-            final int value = i;
-            assertEquals("value at " + i, value, src.get(i));
-        }
-    }
-
-    public void testSet() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int limit = DEFAULT_CAPACITY * 2 + 10;
-        for (int i = 0; i < limit; i++) {
-            final int value = i;
-            src.add(value);
-        }
-
-        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY);
-        dst.set(src);
-        assertEquals("length after set", dst.getLength(), src.getLength());
-        assertSame("array after set", dst.getPrimitiveArray(), src.getPrimitiveArray());
-    }
-
-    public void testCopy() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
-            final int value =  i;
-            src.add(value);
-        }
-
-        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int[] array = dst.getPrimitiveArray();
-        dst.copy(src);
-        assertEquals("length after copy", dst.getLength(), src.getLength());
-        assertSame("array after copy", array, dst.getPrimitiveArray());
-        assertNotSame("array after copy", dst.getPrimitiveArray(), src.getPrimitiveArray());
-        assertIntArrayEquals("values after copy",
-                dst.getPrimitiveArray(), 0, src.getPrimitiveArray(), 0, dst.getLength());
-
-        final int smallerLength = DEFAULT_CAPACITY / 2;
-        dst.reset(smallerLength);
-        final int[] array2 = dst.getPrimitiveArray();
-        dst.copy(src);
-        final int[] array3 = dst.getPrimitiveArray();
-        assertEquals("length after copy to smaller", dst.getLength(), src.getLength());
-        assertNotSame("array after copy to smaller", array2, array3);
-        assertNotSame("array after copy to smaller", array3, src.getPrimitiveArray());
-        assertIntArrayEquals("values after copy to smaller",
-                dst.getPrimitiveArray(), 0, src.getPrimitiveArray(), 0, dst.getLength());
-    }
-
-    public void testAppend() {
-        final int srcLength = DEFAULT_CAPACITY;
-        final ResizableIntArray src = new ResizableIntArray(srcLength);
-        for (int i = 0; i < srcLength; i++) {
-            final int value = i;
-            src.add(value);
-        }
-        final ResizableIntArray dst = new ResizableIntArray(DEFAULT_CAPACITY * 2);
-        final int[] array = dst.getPrimitiveArray();
-        final int dstLength = DEFAULT_CAPACITY / 2;
-        for (int i = 0; i < dstLength; i++) {
-            final int value = -i - 1;
-            dst.add(value);
-        }
-        final ResizableIntArray dstCopy = new ResizableIntArray(dst.getLength());
-        dstCopy.copy(dst);
-
-        final int startPos = 0;
-        dst.append(src, startPos, 0 /* length */);
-        assertEquals("length after append zero", dstLength, dst.getLength());
-        assertSame("array after append zero", array, dst.getPrimitiveArray());
-        assertIntArrayEquals("values after append zero", dstCopy.getPrimitiveArray(), startPos,
-                dst.getPrimitiveArray(), startPos, dstLength);
-
-        dst.append(src, startPos, srcLength);
-        assertEquals("length after append", dstLength + srcLength, dst.getLength());
-        assertSame("array after append", array, dst.getPrimitiveArray());
-        assertTrue("primitive length after append",
-                dst.getPrimitiveArray().length >= dstLength + srcLength);
-        assertIntArrayEquals("original values after append", dstCopy.getPrimitiveArray(), startPos,
-                dst.getPrimitiveArray(), startPos, dstLength);
-        assertIntArrayEquals("appended values after append", src.getPrimitiveArray(), startPos,
-                dst.getPrimitiveArray(), dstLength, srcLength);
-
-        dst.append(src, startPos, srcLength);
-        assertEquals("length after 2nd append", dstLength + srcLength * 2, dst.getLength());
-        assertNotSame("array after 2nd append", array, dst.getPrimitiveArray());
-        assertTrue("primitive length after 2nd append",
-                dst.getPrimitiveArray().length >= dstLength + srcLength * 2);
-        assertIntArrayEquals("original values after 2nd append",
-                dstCopy.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), startPos,
-                dstLength);
-        assertIntArrayEquals("appended values after 2nd append",
-                src.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), dstLength,
-                srcLength);
-        assertIntArrayEquals("appended values after 2nd append",
-                src.getPrimitiveArray(), startPos, dst.getPrimitiveArray(), dstLength + srcLength,
-                srcLength);
-    }
-
-    public void testFill() {
-        final int srcLength = DEFAULT_CAPACITY;
-        final ResizableIntArray src = new ResizableIntArray(srcLength);
-        for (int i = 0; i < srcLength; i++) {
-            final int value = i;
-            src.add(value);
-        }
-        final int[] array = src.getPrimitiveArray();
-
-        final int startPos = srcLength / 3;
-        final int length = srcLength / 3;
-        final int endPos = startPos + length;
-        assertTrue(startPos >= 1);
-        final int fillValue = 123;
-        try {
-            src.fill(fillValue, -1 /* startPos */, length);
-            fail("fill from -1 shouldn't succeed");
-        } catch (IllegalArgumentException e) {
-            // success
-        }
-        try {
-            src.fill(fillValue, startPos, -1 /* length */);
-            fail("fill negative length shouldn't succeed");
-        } catch (IllegalArgumentException e) {
-            // success
-        }
-
-        src.fill(fillValue, startPos, length);
-        assertEquals("length after fill", srcLength, src.getLength());
-        assertSame("array after fill", array, src.getPrimitiveArray());
-        for (int i = 0; i < srcLength; i++) {
-            final int value = i;
-            if (i >= startPos && i < endPos) {
-                assertEquals("new values after fill at " + i, fillValue, src.get(i));
-            } else {
-                assertEquals("unmodified values after fill at " + i, value, src.get(i));
-            }
-        }
-
-        final int length2 = srcLength * 2 - startPos;
-        final int largeEnd = startPos + length2;
-        assertTrue(largeEnd > srcLength);
-        final int fillValue2 = 456;
-        src.fill(fillValue2, startPos, length2);
-        assertEquals("length after large fill", largeEnd, src.getLength());
-        assertNotSame("array after large fill", array, src.getPrimitiveArray());
-        for (int i = 0; i < largeEnd; i++) {
-            final int value = i;
-            if (i >= startPos && i < largeEnd) {
-                assertEquals("new values after large fill at " + i, fillValue2, src.get(i));
-            } else {
-                assertEquals("unmodified values after large fill at " + i, value, src.get(i));
-            }
-        }
-
-        final int startPos2 = largeEnd + length2;
-        final int endPos2 = startPos2 + length2;
-        final int fillValue3 = 789;
-        src.fill(fillValue3, startPos2, length2);
-        assertEquals("length after disjoint fill", endPos2, src.getLength());
-        for (int i = 0; i < endPos2; i++) {
-            final int value = i;
-            if (i >= startPos2 && i < endPos2) {
-                assertEquals("new values after disjoint fill at " + i, fillValue3, src.get(i));
-            } else if (i >= startPos && i < largeEnd) {
-                assertEquals("unmodified values after disjoint fill at " + i,
-                        fillValue2, src.get(i));
-            } else if (i < startPos) {
-                assertEquals("unmodified values after disjoint fill at " + i, value, src.get(i));
-            } else {
-                assertEquals("gap values after disjoint fill at " + i, 0, src.get(i));
-            }
-        }
-    }
-
-    private static void assertIntArrayEquals(final String message, final int[] expecteds,
-            final int expectedPos, final int[] actuals, final int actualPos, final int length) {
-        if (expecteds == actuals) {
-            return;
-        }
-        if (expecteds == null || actuals == null) {
-            assertEquals(message, Arrays.toString(expecteds), Arrays.toString(actuals));
-            return;
-        }
-        if (expecteds.length < expectedPos + length || actuals.length < actualPos + length) {
-            fail(message + ": insufficient length: expecteds=" + Arrays.toString(expecteds)
-                    + " actuals=" + Arrays.toString(actuals));
-            return;
-        }
-        for (int i = 0; i < length; i++) {
-            assertEquals(message + " [" + i + "]",
-                    expecteds[i + expectedPos], actuals[i + actualPos]);
-        }
-    }
-
-    public void testShift() {
-        final ResizableIntArray src = new ResizableIntArray(DEFAULT_CAPACITY);
-        final int limit = DEFAULT_CAPACITY * 10;
-        final int shiftAmount = 20;
-        for (int i = 0; i < limit; ++i) {
-            final int value = i;
-            src.addAt(i, value);
-            assertEquals("length after add at " + i, i + 1, src.getLength());
-        }
-        src.shift(shiftAmount);
-        for (int i = 0; i < limit - shiftAmount; ++i) {
-            final int oldValue = i + shiftAmount;
-            assertEquals("value at " + i, oldValue, src.get(i));
-        }
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
deleted file mode 100644
index fdde342..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/SpacebarLanguagetUtilsTests.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2011 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.utils;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import com.android.inputmethod.latin.RichInputMethodManager;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-@SmallTest
-public class SpacebarLanguagetUtilsTests extends AndroidTestCase {
-    // All input method subtypes of LatinIME.
-    private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<>();
-
-    private RichInputMethodManager mRichImm;
-    private Resources mRes;
-
-    InputMethodSubtype EN_US;
-    InputMethodSubtype EN_GB;
-    InputMethodSubtype ES_US;
-    InputMethodSubtype FR;
-    InputMethodSubtype FR_CA;
-    InputMethodSubtype FR_CH;
-    InputMethodSubtype DE;
-    InputMethodSubtype DE_CH;
-    InputMethodSubtype ZZ;
-    InputMethodSubtype DE_QWERTY;
-    InputMethodSubtype FR_QWERTZ;
-    InputMethodSubtype EN_US_AZERTY;
-    InputMethodSubtype EN_UK_DVORAK;
-    InputMethodSubtype ES_US_COLEMAK;
-    InputMethodSubtype ZZ_AZERTY;
-    InputMethodSubtype ZZ_PC;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        final Context context = getContext();
-        RichInputMethodManager.init(context);
-        mRichImm = RichInputMethodManager.getInstance();
-        mRes = context.getResources();
-        SubtypeLocaleUtils.init(context);
-
-        final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
-        final int subtypeCount = imi.getSubtypeCount();
-        for (int index = 0; index < subtypeCount; index++) {
-            final InputMethodSubtype subtype = imi.getSubtypeAt(index);
-            mSubtypesList.add(subtype);
-        }
-
-        EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.US.toString(), "qwerty");
-        EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.UK.toString(), "qwerty");
-        ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                "es_US", "spanish");
-        FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.FRENCH.toString(), "azerty");
-        FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.CANADA_FRENCH.toString(), "qwerty");
-        FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                "fr_CH", "swiss");
-        DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                Locale.GERMAN.toString(), "qwertz");
-        DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                "de_CH", "swiss");
-        ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
-                SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
-        DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                Locale.GERMAN.toString(), "qwerty");
-        FR_QWERTZ = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                Locale.FRENCH.toString(), "qwertz");
-        EN_US_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                Locale.US.toString(), "azerty");
-        EN_UK_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                Locale.UK.toString(), "dvorak");
-        ES_US_COLEMAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                "es_US", "colemak");
-        ZZ_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
-        ZZ_PC = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
-                SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty");
-    }
-
-    public void testAllFullDisplayNameForSpacebar() {
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final String subtypeName = SubtypeLocaleUtils
-                    .getSubtypeDisplayNameInSystemLocale(subtype);
-            final String spacebarText = SpacebarLanguageUtils.getFullDisplayName(subtype);
-            final String languageName = SubtypeLocaleUtils
-                    .getSubtypeLocaleDisplayName(subtype.getLocale());
-            if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
-                assertFalse(subtypeName, spacebarText.contains(languageName));
-            } else {
-                assertTrue(subtypeName, spacebarText.contains(languageName));
-            }
-        }
-    }
-
-   public void testAllMiddleDisplayNameForSpacebar() {
-        for (final InputMethodSubtype subtype : mSubtypesList) {
-            final String subtypeName = SubtypeLocaleUtils
-                    .getSubtypeDisplayNameInSystemLocale(subtype);
-            final String spacebarText = SpacebarLanguageUtils.getMiddleDisplayName(subtype);
-            if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
-                assertEquals(subtypeName,
-                        SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype), spacebarText);
-            } else {
-                final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
-                assertEquals(subtypeName,
-                        SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()),
-                        spacebarText);
-            }
-        }
-    }
-
-    // InputMethodSubtype's display name for spacebar text in its locale.
-    //        isAdditionalSubtype (T=true, F=false)
-    // locale layout  |  Middle     Full
-    // ------ ------- - --------- ----------------------
-    //  en_US qwerty  F  English   English (US)           exception
-    //  en_GB qwerty  F  English   English (UK)           exception
-    //  es_US spanish F  Español   Español (EE.UU.)       exception
-    //  fr    azerty  F  Français  Français
-    //  fr_CA qwerty  F  Français  Français (Canada)
-    //  fr_CH swiss   F  Français  Français (Suisse)
-    //  de    qwertz  F  Deutsch   Deutsch
-    //  de_CH swiss   F  Deutsch   Deutsch (Schweiz)
-    //  zz    qwerty  F  QWERTY    QWERTY
-    //  fr    qwertz  T  Français  Français
-    //  de    qwerty  T  Deutsch   Deutsch
-    //  en_US azerty  T  English   English (US)
-    //  zz    azerty  T  AZERTY    AZERTY
-
-    private final RunInLocale<Void> testsPredefinedSubtypesForSpacebar = new RunInLocale<Void>() {
-        @Override
-        protected Void job(final Resources res) {
-            assertEquals("en_US", "English (US)",
-                    SpacebarLanguageUtils.getFullDisplayName(EN_US));
-            assertEquals("en_GB", "English (UK)",
-                    SpacebarLanguageUtils.getFullDisplayName(EN_GB));
-            assertEquals("es_US", "Español (EE.UU.)",
-                    SpacebarLanguageUtils.getFullDisplayName(ES_US));
-            assertEquals("fr", "Français",
-                    SpacebarLanguageUtils.getFullDisplayName(FR));
-            assertEquals("fr_CA", "Français (Canada)",
-                    SpacebarLanguageUtils.getFullDisplayName(FR_CA));
-            assertEquals("fr_CH", "Français (Suisse)",
-                    SpacebarLanguageUtils.getFullDisplayName(FR_CH));
-            assertEquals("de", "Deutsch",
-                    SpacebarLanguageUtils.getFullDisplayName(DE));
-            assertEquals("de_CH", "Deutsch (Schweiz)",
-                    SpacebarLanguageUtils.getFullDisplayName(DE_CH));
-            assertEquals("zz", "QWERTY",
-                    SpacebarLanguageUtils.getFullDisplayName(ZZ));
-
-            assertEquals("en_US", "English",
-                    SpacebarLanguageUtils.getMiddleDisplayName(EN_US));
-            assertEquals("en_GB", "English",
-                    SpacebarLanguageUtils.getMiddleDisplayName(EN_GB));
-            assertEquals("es_US", "Español",
-                    SpacebarLanguageUtils.getMiddleDisplayName(ES_US));
-            assertEquals("fr", "Français",
-                    SpacebarLanguageUtils.getMiddleDisplayName(FR));
-            assertEquals("fr_CA", "Français",
-                    SpacebarLanguageUtils.getMiddleDisplayName(FR_CA));
-            assertEquals("fr_CH", "Français",
-                    SpacebarLanguageUtils.getMiddleDisplayName(FR_CH));
-            assertEquals("de", "Deutsch",
-                    SpacebarLanguageUtils.getMiddleDisplayName(DE));
-            assertEquals("de_CH", "Deutsch",
-                    SpacebarLanguageUtils.getMiddleDisplayName(DE_CH));
-            assertEquals("zz", "QWERTY",
-                    SpacebarLanguageUtils.getMiddleDisplayName(ZZ));
-            return null;
-        }
-    };
-
-    private final RunInLocale<Void> testsAdditionalSubtypesForSpacebar = new RunInLocale<Void>() {
-        @Override
-        protected Void job(final Resources res) {
-            assertEquals("fr qwertz", "Français",
-                    SpacebarLanguageUtils.getFullDisplayName(FR_QWERTZ));
-            assertEquals("de qwerty", "Deutsch",
-                    SpacebarLanguageUtils.getFullDisplayName(DE_QWERTY));
-            assertEquals("en_US azerty", "English (US)",
-                    SpacebarLanguageUtils.getFullDisplayName(EN_US_AZERTY));
-            assertEquals("en_UK dvorak", "English (UK)",
-                    SpacebarLanguageUtils.getFullDisplayName(EN_UK_DVORAK));
-            assertEquals("es_US colemak", "Español (EE.UU.)",
-                    SpacebarLanguageUtils.getFullDisplayName(ES_US_COLEMAK));
-            assertEquals("zz azerty", "AZERTY",
-                    SpacebarLanguageUtils.getFullDisplayName(ZZ_AZERTY));
-            assertEquals("zz pc", "PC",
-                    SpacebarLanguageUtils.getFullDisplayName(ZZ_PC));
-
-            assertEquals("fr qwertz", "Français",
-                    SpacebarLanguageUtils.getMiddleDisplayName(FR_QWERTZ));
-            assertEquals("de qwerty", "Deutsch",
-                    SpacebarLanguageUtils.getMiddleDisplayName(DE_QWERTY));
-            assertEquals("en_US azerty", "English",
-                    SpacebarLanguageUtils.getMiddleDisplayName(EN_US_AZERTY));
-            assertEquals("en_UK dvorak", "English",
-                    SpacebarLanguageUtils.getMiddleDisplayName(EN_UK_DVORAK));
-            assertEquals("es_US colemak", "Español",
-                    SpacebarLanguageUtils.getMiddleDisplayName(ES_US_COLEMAK));
-            assertEquals("zz azerty", "AZERTY",
-                    SpacebarLanguageUtils.getMiddleDisplayName(ZZ_AZERTY));
-            assertEquals("zz pc", "PC",
-                    SpacebarLanguageUtils.getMiddleDisplayName(ZZ_PC));
-            return null;
-        }
-    };
-
-    public void testPredefinedSubtypesForSpacebarInEnglish() {
-        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testAdditionalSubtypeForSpacebarInEnglish() {
-        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.ENGLISH);
-    }
-
-    public void testPredefinedSubtypesForSpacebarInFrench() {
-        testsPredefinedSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
-    }
-
-    public void testAdditionalSubtypeForSpacebarInFrench() {
-        testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
index fa6ad16..665d81c 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SpannableStringUtilsTests.java
@@ -20,9 +20,10 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.style.SuggestionSpan;
 import android.text.style.URLSpan;
+import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
-import android.text.Spannable;
 import android.text.Spanned;
+import android.text.SpannedString;
 
 @SmallTest
 public class SpannableStringUtilsTests extends AndroidTestCase {
@@ -34,8 +35,8 @@
         for (int i = 0; i < N; ++i) {
             // Put a PARAGRAPH-flagged span that should not be found in the result.
             s.setSpan(new SuggestionSpan(getContext(),
-                    new String[] {"" + i}, Spannable.SPAN_PARAGRAPH),
-                    i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH);
+                    new String[] {"" + i}, Spanned.SPAN_PARAGRAPH),
+                    i * 12, i * 12 + 12, Spanned.SPAN_PARAGRAPH);
             // Put a normal suggestion span that should be found in the result.
             s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0);
             // Put a URL span than should not be found in the result.
@@ -51,8 +52,175 @@
         for (int i = 0; i < spans.length; i++) {
             final int flags = result.getSpanFlags(spans[i]);
             assertEquals("Should not find a span with PARAGRAPH flag",
-                    flags & Spannable.SPAN_PARAGRAPH, 0);
+                    flags & Spanned.SPAN_PARAGRAPH, 0);
             assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
         }
     }
+
+    private static void assertSpanCount(final int expectedCount, final CharSequence cs) {
+        final int actualCount;
+        if (cs instanceof Spanned) {
+            final Spanned spanned = (Spanned) cs;
+            actualCount = spanned.getSpans(0, spanned.length(), Object.class).length;
+        } else {
+            actualCount = 0;
+        }
+        assertEquals(expectedCount, actualCount);
+    }
+
+    private static void assertSpan(final CharSequence cs, final Object expectedSpan,
+            final int expectedStart, final int expectedEnd, final int expectedFlags) {
+        assertTrue(cs instanceof Spanned);
+        final Spanned spanned = (Spanned) cs;
+        final Object[] actualSpans = spanned.getSpans(0, spanned.length(), Object.class);
+        for (Object actualSpan : actualSpans) {
+            if (actualSpan == expectedSpan) {
+                final int actualStart = spanned.getSpanStart(actualSpan);
+                final int actualEnd = spanned.getSpanEnd(actualSpan);
+                final int actualFlags = spanned.getSpanFlags(actualSpan);
+                assertEquals(expectedStart, actualStart);
+                assertEquals(expectedEnd, actualEnd);
+                assertEquals(expectedFlags, actualFlags);
+                return;
+            }
+        }
+        assertTrue(false);
+    }
+
+    public void testSplitCharSequenceWithSpan() {
+        // text:  " a bcd efg hij  "
+        // span1:  ^^^^^^^
+        // span2:  ^^^^^
+        // span3:              ^
+        final SpannableString spannableString = new SpannableString(" a bcd efg hij  ");
+        final Object span1 = new Object();
+        final Object span2 = new Object();
+        final Object span3 = new Object();
+        final int SPAN1_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
+        final int SPAN2_FLAGS = Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
+        final int SPAN3_FLAGS = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
+        spannableString.setSpan(span1, 0, 7, SPAN1_FLAGS);
+        spannableString.setSpan(span2, 0, 5, SPAN2_FLAGS);
+        spannableString.setSpan(span3, 12, 13, SPAN3_FLAGS);
+        final CharSequence[] charSequencesFromSpanned = SpannableStringUtils.split(
+                spannableString, " ", true /* preserveTrailingEmptySegmengs */);
+        final CharSequence[] charSequencesFromString = SpannableStringUtils.split(
+                spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */);
+
+
+        assertEquals(7, charSequencesFromString.length);
+        assertEquals(7, charSequencesFromSpanned.length);
+
+        // text:  ""
+        // span1: ^
+        // span2: ^
+        // span3:
+        assertEquals("", charSequencesFromString[0].toString());
+        assertSpanCount(0, charSequencesFromString[0]);
+        assertEquals("", charSequencesFromSpanned[0].toString());
+        assertSpanCount(2, charSequencesFromSpanned[0]);
+        assertSpan(charSequencesFromSpanned[0], span1, 0, 0, SPAN1_FLAGS);
+        assertSpan(charSequencesFromSpanned[0], span2, 0, 0, SPAN2_FLAGS);
+
+        // text:  "a"
+        // span1:  ^
+        // span2:  ^
+        // span3:
+        assertEquals("a", charSequencesFromString[1].toString());
+        assertSpanCount(0, charSequencesFromString[1]);
+        assertEquals("a", charSequencesFromSpanned[1].toString());
+        assertSpanCount(2, charSequencesFromSpanned[1]);
+        assertSpan(charSequencesFromSpanned[1], span1, 0, 1, SPAN1_FLAGS);
+        assertSpan(charSequencesFromSpanned[1], span2, 0, 1, SPAN2_FLAGS);
+
+        // text:  "bcd"
+        // span1:  ^^^
+        // span2:  ^^
+        // span3:
+        assertEquals("bcd", charSequencesFromString[2].toString());
+        assertSpanCount(0, charSequencesFromString[2]);
+        assertEquals("bcd", charSequencesFromSpanned[2].toString());
+        assertSpanCount(2, charSequencesFromSpanned[2]);
+        assertSpan(charSequencesFromSpanned[2], span1, 0, 3, SPAN1_FLAGS);
+        assertSpan(charSequencesFromSpanned[2], span2, 0, 2, SPAN2_FLAGS);
+
+        // text:  "efg"
+        // span1:
+        // span2:
+        // span3:
+        assertEquals("efg", charSequencesFromString[3].toString());
+        assertSpanCount(0, charSequencesFromString[3]);
+        assertEquals("efg", charSequencesFromSpanned[3].toString());
+        assertSpanCount(0, charSequencesFromSpanned[3]);
+
+        // text:  "hij"
+        // span1:
+        // span2:
+        // span3:   ^
+        assertEquals("hij", charSequencesFromString[4].toString());
+        assertSpanCount(0, charSequencesFromString[4]);
+        assertEquals("hij", charSequencesFromSpanned[4].toString());
+        assertSpanCount(1, charSequencesFromSpanned[4]);
+        assertSpan(charSequencesFromSpanned[4], span3, 1, 2, SPAN3_FLAGS);
+
+        // text:  ""
+        // span1:
+        // span2:
+        // span3:
+        assertEquals("", charSequencesFromString[5].toString());
+        assertSpanCount(0, charSequencesFromString[5]);
+        assertEquals("", charSequencesFromSpanned[5].toString());
+        assertSpanCount(0, charSequencesFromSpanned[5]);
+
+        // text:  ""
+        // span1:
+        // span2:
+        // span3:
+        assertEquals("", charSequencesFromString[6].toString());
+        assertSpanCount(0, charSequencesFromString[6]);
+        assertEquals("", charSequencesFromSpanned[6].toString());
+        assertSpanCount(0, charSequencesFromSpanned[6]);
+    }
+
+    public void testSplitCharSequencePreserveTrailingEmptySegmengs() {
+        assertEquals(1, SpannableStringUtils.split("", " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(1, SpannableStringUtils.split("", " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(0, SpannableStringUtils.split(" ", " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(0, SpannableStringUtils.split(new SpannedString(" "), " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(2, SpannableStringUtils.split(" ", " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(2, SpannableStringUtils.split(new SpannedString(" "), " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(3, SpannableStringUtils.split("a b c  ", " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(3, SpannableStringUtils.split(new SpannedString("a b c  "), " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(5, SpannableStringUtils.split("a b c  ", " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(5, SpannableStringUtils.split(new SpannedString("a b c  "), " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(6, SpannableStringUtils.split("a     b ", " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(6, SpannableStringUtils.split(new SpannedString("a     b "), " ",
+                false /* preserveTrailingEmptySegmengs */).length);
+
+        assertEquals(7, SpannableStringUtils.split("a     b ", " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+        assertEquals(7, SpannableStringUtils.split(new SpannedString("a     b "), " ",
+                true /* preserveTrailingEmptySegmengs */).length);
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
deleted file mode 100644
index 637ae10..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (C) 2012 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.SpannedString;
-
-import com.android.inputmethod.latin.Constants;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-@SmallTest
-public class StringAndJsonUtilsTests extends AndroidTestCase {
-    public void testContainsInArray() {
-        assertFalse("empty array", StringUtils.containsInArray("key", new String[0]));
-        assertFalse("not in 1 element", StringUtils.containsInArray("key", new String[] {
-                "key1"
-        }));
-        assertFalse("not in 2 elements", StringUtils.containsInArray("key", new String[] {
-                "key1", "key2"
-        }));
-
-        assertTrue("in 1 element", StringUtils.containsInArray("key", new String[] {
-                "key"
-        }));
-        assertTrue("in 2 elements", StringUtils.containsInArray("key", new String[] {
-                "key1", "key"
-        }));
-    }
-
-    public void testContainsInCommaSplittableText() {
-        assertFalse("null", StringUtils.containsInCommaSplittableText("key", null));
-        assertFalse("empty", StringUtils.containsInCommaSplittableText("key", ""));
-        assertFalse("not in 1 element",
-                StringUtils.containsInCommaSplittableText("key", "key1"));
-        assertFalse("not in 2 elements",
-                StringUtils.containsInCommaSplittableText("key", "key1,key2"));
-
-        assertTrue("in 1 element", StringUtils.containsInCommaSplittableText("key", "key"));
-        assertTrue("in 2 elements", StringUtils.containsInCommaSplittableText("key", "key1,key"));
-    }
-
-    public void testRemoveFromCommaSplittableTextIfExists() {
-        assertEquals("null", "", StringUtils.removeFromCommaSplittableTextIfExists("key", null));
-        assertEquals("empty", "", StringUtils.removeFromCommaSplittableTextIfExists("key", ""));
-
-        assertEquals("not in 1 element", "key1",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1"));
-        assertEquals("not in 2 elements", "key1,key2",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key2"));
-
-        assertEquals("in 1 element", "",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key"));
-        assertEquals("in 2 elements at position 1", "key2",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key,key2"));
-        assertEquals("in 2 elements at position 2", "key1",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key"));
-        assertEquals("in 3 elements at position 2", "key1,key3",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key1,key,key3"));
-
-        assertEquals("in 3 elements at position 1,2,3", "",
-                StringUtils.removeFromCommaSplittableTextIfExists("key", "key,key,key"));
-        assertEquals("in 5 elements at position 2,4", "key1,key3,key5",
-                StringUtils.removeFromCommaSplittableTextIfExists(
-                        "key", "key1,key,key3,key,key5"));
-    }
-
-
-    public void testCapitalizeFirstCodePoint() {
-        assertEquals("SSaa",
-                StringUtils.capitalizeFirstCodePoint("ßaa", Locale.GERMAN));
-        assertEquals("Aßa",
-                StringUtils.capitalizeFirstCodePoint("aßa", Locale.GERMAN));
-        assertEquals("Iab",
-                StringUtils.capitalizeFirstCodePoint("iab", Locale.ENGLISH));
-        assertEquals("CAmElCaSe",
-                StringUtils.capitalizeFirstCodePoint("cAmElCaSe", Locale.ENGLISH));
-        assertEquals("İab",
-                StringUtils.capitalizeFirstCodePoint("iab", new Locale("tr")));
-        assertEquals("AİB",
-                StringUtils.capitalizeFirstCodePoint("AİB", new Locale("tr")));
-        assertEquals("A",
-                StringUtils.capitalizeFirstCodePoint("a", Locale.ENGLISH));
-        assertEquals("A",
-                StringUtils.capitalizeFirstCodePoint("A", Locale.ENGLISH));
-    }
-
-    public void testCapitalizeFirstAndDowncaseRest() {
-        assertEquals("SSaa",
-                StringUtils.capitalizeFirstAndDowncaseRest("ßaa", Locale.GERMAN));
-        assertEquals("Aßa",
-                StringUtils.capitalizeFirstAndDowncaseRest("aßa", Locale.GERMAN));
-        assertEquals("Iab",
-                StringUtils.capitalizeFirstAndDowncaseRest("iab", Locale.ENGLISH));
-        assertEquals("Camelcase",
-                StringUtils.capitalizeFirstAndDowncaseRest("cAmElCaSe", Locale.ENGLISH));
-        assertEquals("İab",
-                StringUtils.capitalizeFirstAndDowncaseRest("iab", new Locale("tr")));
-        assertEquals("Aib",
-                StringUtils.capitalizeFirstAndDowncaseRest("AİB", new Locale("tr")));
-        assertEquals("A",
-                StringUtils.capitalizeFirstAndDowncaseRest("a", Locale.ENGLISH));
-        assertEquals("A",
-                StringUtils.capitalizeFirstAndDowncaseRest("A", Locale.ENGLISH));
-    }
-
-    public void testGetCapitalizationType() {
-        assertEquals(StringUtils.CAPITALIZE_NONE,
-                StringUtils.getCapitalizationType("capitalize"));
-        assertEquals(StringUtils.CAPITALIZE_NONE,
-                StringUtils.getCapitalizationType("cApITalize"));
-        assertEquals(StringUtils.CAPITALIZE_NONE,
-                StringUtils.getCapitalizationType("capitalizE"));
-        assertEquals(StringUtils.CAPITALIZE_NONE,
-                StringUtils.getCapitalizationType("__c a piu$@tali56ze"));
-        assertEquals(StringUtils.CAPITALIZE_FIRST,
-                StringUtils.getCapitalizationType("A__c a piu$@tali56ze"));
-        assertEquals(StringUtils.CAPITALIZE_FIRST,
-                StringUtils.getCapitalizationType("Capitalize"));
-        assertEquals(StringUtils.CAPITALIZE_FIRST,
-                StringUtils.getCapitalizationType("     Capitalize"));
-        assertEquals(StringUtils.CAPITALIZE_ALL,
-                StringUtils.getCapitalizationType("CAPITALIZE"));
-        assertEquals(StringUtils.CAPITALIZE_ALL,
-                StringUtils.getCapitalizationType("  PI26LIE"));
-        assertEquals(StringUtils.CAPITALIZE_NONE,
-                StringUtils.getCapitalizationType(""));
-    }
-
-    public void testIsIdenticalAfterUpcaseIsIdenticalAfterDowncase() {
-        assertFalse(StringUtils.isIdenticalAfterUpcase("capitalize"));
-        assertTrue(StringUtils.isIdenticalAfterDowncase("capitalize"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("cApITalize"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("cApITalize"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("capitalizE"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("capitalizE"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("__c a piu$@tali56ze"));
-        assertTrue(StringUtils.isIdenticalAfterDowncase("__c a piu$@tali56ze"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("A__c a piu$@tali56ze"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("A__c a piu$@tali56ze"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("Capitalize"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("Capitalize"));
-        assertFalse(StringUtils.isIdenticalAfterUpcase("     Capitalize"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("     Capitalize"));
-        assertTrue(StringUtils.isIdenticalAfterUpcase("CAPITALIZE"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("CAPITALIZE"));
-        assertTrue(StringUtils.isIdenticalAfterUpcase("  PI26LIE"));
-        assertFalse(StringUtils.isIdenticalAfterDowncase("  PI26LIE"));
-        assertTrue(StringUtils.isIdenticalAfterUpcase(""));
-        assertTrue(StringUtils.isIdenticalAfterDowncase(""));
-    }
-
-    private static void checkCapitalize(final String src, final String dst,
-            final int[] sortedSeparators, final Locale locale) {
-        assertEquals(dst, StringUtils.capitalizeEachWord(src, sortedSeparators, locale));
-        assert(src.equals(dst)
-                == StringUtils.isIdenticalAfterCapitalizeEachWord(src, sortedSeparators));
-    }
-
-    private static final int[] SPACE = { Constants.CODE_SPACE };
-    private static final int[] SPACE_PERIOD = StringUtils.toSortedCodePointArray(" .");
-    private static final int[] SENTENCE_SEPARATORS =
-            StringUtils.toSortedCodePointArray(" \n.!?*()&");
-    private static final int[] WORD_SEPARATORS = StringUtils.toSortedCodePointArray(" \n.!?*,();&");
-
-    public void testCapitalizeEachWord() {
-        checkCapitalize("", "", SPACE, Locale.ENGLISH);
-        checkCapitalize("test", "Test", SPACE, Locale.ENGLISH);
-        checkCapitalize("    test", "    Test", SPACE, Locale.ENGLISH);
-        checkCapitalize("Test", "Test", SPACE, Locale.ENGLISH);
-        checkCapitalize("    Test", "    Test", SPACE, Locale.ENGLISH);
-        checkCapitalize(".Test", ".test", SPACE, Locale.ENGLISH);
-        checkCapitalize(".Test", ".Test", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test And Retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test And.Retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test And.retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test And.retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
-        checkCapitalize("Test And.Retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
-        checkCapitalize("test and ietest", "Test And İetest", SPACE_PERIOD, new Locale("tr"));
-        checkCapitalize("test and ietest", "Test And Ietest", SPACE_PERIOD, Locale.ENGLISH);
-        checkCapitalize("Test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("Test&retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("rest\nrecreation! And in the end...",
-                "Rest\nRecreation! And In The End...", WORD_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("lorem ipsum dolor sit amet", "Lorem Ipsum Dolor Sit Amet",
-                WORD_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("Lorem!Ipsum (Dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
-                WORD_SEPARATORS, Locale.ENGLISH);
-        checkCapitalize("Lorem!Ipsum (dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
-                WORD_SEPARATORS, Locale.ENGLISH);
-    }
-
-    public void testLooksLikeURL() {
-        assertTrue(StringUtils.lastPartLooksLikeURL("http://www.google."));
-        assertFalse(StringUtils.lastPartLooksLikeURL("word wo"));
-        assertTrue(StringUtils.lastPartLooksLikeURL("/etc/foo"));
-        assertFalse(StringUtils.lastPartLooksLikeURL("left/right"));
-        assertTrue(StringUtils.lastPartLooksLikeURL("www.goo"));
-        assertTrue(StringUtils.lastPartLooksLikeURL("www."));
-        assertFalse(StringUtils.lastPartLooksLikeURL("U.S.A"));
-        assertFalse(StringUtils.lastPartLooksLikeURL("U.S.A."));
-        assertTrue(StringUtils.lastPartLooksLikeURL("rtsp://foo."));
-        assertTrue(StringUtils.lastPartLooksLikeURL("://"));
-        assertFalse(StringUtils.lastPartLooksLikeURL("abc/"));
-        assertTrue(StringUtils.lastPartLooksLikeURL("abc.def/ghi"));
-        assertFalse(StringUtils.lastPartLooksLikeURL("abc.def"));
-        // TODO: ideally this would not look like a URL, but to keep down the complexity of the
-        // code for now True is acceptable.
-        assertTrue(StringUtils.lastPartLooksLikeURL("abc./def"));
-        // TODO: ideally this would not look like a URL, but to keep down the complexity of the
-        // code for now True is acceptable.
-        assertTrue(StringUtils.lastPartLooksLikeURL(".abc/def"));
-    }
-
-    public void testHexStringUtils() {
-        final byte[] bytes = new byte[] { (byte)0x01, (byte)0x11, (byte)0x22, (byte)0x33,
-                (byte)0x55, (byte)0x88, (byte)0xEE };
-        final String bytesStr = StringUtils.byteArrayToHexString(bytes);
-        final byte[] bytes2 = StringUtils.hexStringToByteArray(bytesStr);
-        for (int i = 0; i < bytes.length; ++i) {
-            assertTrue(bytes[i] == bytes2[i]);
-        }
-        final String bytesStr2 = StringUtils.byteArrayToHexString(bytes2);
-        assertTrue(bytesStr.equals(bytesStr2));
-    }
-
-    public void testJsonUtils() {
-        final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 };
-        final List<Object> objArray = Arrays.asList(objs);
-        final String str = JsonUtils.listToJsonStr(objArray);
-        final List<Object> newObjArray = JsonUtils.jsonStrToList(str);
-        for (int i = 0; i < objs.length; ++i) {
-            assertEquals(objs[i], newObjArray.get(i));
-        }
-    }
-
-    public void testToCodePointArray() {
-        final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh\u0000\u2002\u2003\u3000xx";
-        final int[] EXPECTED_RESULT = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7, 'f', 'g', 'h',
-                0, 0x2002, 0x2003, 0x3000, 'x', 'x'};
-        final int[] codePointArray = StringUtils.toCodePointArray(STR_WITH_SUPPLEMENTARY_CHAR, 0,
-                STR_WITH_SUPPLEMENTARY_CHAR.length());
-        assertEquals("toCodePointArray, size matches", codePointArray.length,
-                EXPECTED_RESULT.length);
-        for (int i = 0; i < EXPECTED_RESULT.length; ++i) {
-            assertEquals("toCodePointArray position " + i, codePointArray[i], EXPECTED_RESULT[i]);
-        }
-    }
-
-    public void testCopyCodePointsAndReturnCodePointCount() {
-        final String STR_WITH_SUPPLEMENTARY_CHAR = "AbcDE\uD861\uDED7fGh\u0000\u2002\u3000あx";
-        final int[] EXPECTED_RESULT = new int[] { 'A', 'b', 'c', 'D', 'E', 0x286D7,
-                'f', 'G', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
-        final int[] EXPECTED_RESULT_DOWNCASE = new int[] { 'a', 'b', 'c', 'd', 'e', 0x286D7,
-                'f', 'g', 'h', 0, 0x2002, 0x3000, 'あ', 'x'};
-
-        int[] codePointArray = new int[50];
-        int codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
-                STR_WITH_SUPPLEMENTARY_CHAR, 0,
-                STR_WITH_SUPPLEMENTARY_CHAR.length(), false /* downCase */);
-        assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
-                EXPECTED_RESULT.length);
-        for (int i = 0; i < codePointCount; ++i) {
-            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
-                    EXPECTED_RESULT[i]);
-        }
-
-        codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
-                STR_WITH_SUPPLEMENTARY_CHAR, 0,
-                STR_WITH_SUPPLEMENTARY_CHAR.length(), true /* downCase */);
-        assertEquals("copyCodePointsAndReturnCodePointCount downcase, size matches", codePointCount,
-                EXPECTED_RESULT_DOWNCASE.length);
-        for (int i = 0; i < codePointCount; ++i) {
-            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
-                    EXPECTED_RESULT_DOWNCASE[i]);
-        }
-
-        final int JAVA_CHAR_COUNT = 8;
-        final int CODEPOINT_COUNT = 7;
-        codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
-                STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
-        assertEquals("copyCodePointsAndReturnCodePointCount, size matches", codePointCount,
-                CODEPOINT_COUNT);
-        for (int i = 0; i < codePointCount; ++i) {
-            assertEquals("copyCodePointsAndReturnCodePointCount position " + i, codePointArray[i],
-                    EXPECTED_RESULT[i]);
-        }
-
-        boolean exceptionHappened = false;
-        codePointArray = new int[5];
-        try {
-            codePointCount = StringUtils.copyCodePointsAndReturnCodePointCount(codePointArray,
-                    STR_WITH_SUPPLEMENTARY_CHAR, 0, JAVA_CHAR_COUNT, false /* downCase */);
-        } catch (ArrayIndexOutOfBoundsException e) {
-            exceptionHappened = true;
-        }
-        assertTrue("copyCodePointsAndReturnCodePointCount throws when array is too small",
-                exceptionHappened);
-    }
-
-    public void testGetTrailingSingleQuotesCount() {
-        assertEquals(0, StringUtils.getTrailingSingleQuotesCount(""));
-        assertEquals(1, StringUtils.getTrailingSingleQuotesCount("'"));
-        assertEquals(5, StringUtils.getTrailingSingleQuotesCount("'''''"));
-        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("a"));
-        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("'this"));
-        assertEquals(1, StringUtils.getTrailingSingleQuotesCount("'word'"));
-        assertEquals(0, StringUtils.getTrailingSingleQuotesCount("I'm"));
-    }
-
-    private static void assertSpanCount(final int expectedCount, final CharSequence cs) {
-        final int actualCount;
-        if (cs instanceof Spanned) {
-            final Spanned spanned = (Spanned) cs;
-            actualCount = spanned.getSpans(0, spanned.length(), Object.class).length;
-        } else {
-            actualCount = 0;
-        }
-        assertEquals(expectedCount, actualCount);
-    }
-
-    private static void assertSpan(final CharSequence cs, final Object expectedSpan,
-            final int expectedStart, final int expectedEnd, final int expectedFlags) {
-        assertTrue(cs instanceof Spanned);
-        final Spanned spanned = (Spanned) cs;
-        final Object[] actualSpans = spanned.getSpans(0, spanned.length(), Object.class);
-        for (Object actualSpan : actualSpans) {
-            if (actualSpan == expectedSpan) {
-                final int actualStart = spanned.getSpanStart(actualSpan);
-                final int actualEnd = spanned.getSpanEnd(actualSpan);
-                final int actualFlags = spanned.getSpanFlags(actualSpan);
-                assertEquals(expectedStart, actualStart);
-                assertEquals(expectedEnd, actualEnd);
-                assertEquals(expectedFlags, actualFlags);
-                return;
-            }
-        }
-        assertTrue(false);
-    }
-
-    public void testSplitCharSequenceWithSpan() {
-        // text:  " a bcd efg hij  "
-        // span1:  ^^^^^^^
-        // span2:  ^^^^^
-        // span3:              ^
-        final SpannableString spannableString = new SpannableString(" a bcd efg hij  ");
-        final Object span1 = new Object();
-        final Object span2 = new Object();
-        final Object span3 = new Object();
-        final int SPAN1_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
-        final int SPAN2_FLAGS = Spanned.SPAN_EXCLUSIVE_INCLUSIVE;
-        final int SPAN3_FLAGS = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
-        spannableString.setSpan(span1, 0, 7, SPAN1_FLAGS);
-        spannableString.setSpan(span2, 0, 5, SPAN2_FLAGS);
-        spannableString.setSpan(span3, 12, 13, SPAN3_FLAGS);
-        final CharSequence[] charSequencesFromSpanned = StringUtils.split(
-                spannableString, " ", true /* preserveTrailingEmptySegmengs */);
-        final CharSequence[] charSequencesFromString = StringUtils.split(
-                spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */);
-
-
-        assertEquals(7, charSequencesFromString.length);
-        assertEquals(7, charSequencesFromSpanned.length);
-
-        // text:  ""
-        // span1: ^
-        // span2: ^
-        // span3:
-        assertEquals("", charSequencesFromString[0].toString());
-        assertSpanCount(0, charSequencesFromString[0]);
-        assertEquals("", charSequencesFromSpanned[0].toString());
-        assertSpanCount(2, charSequencesFromSpanned[0]);
-        assertSpan(charSequencesFromSpanned[0], span1, 0, 0, SPAN1_FLAGS);
-        assertSpan(charSequencesFromSpanned[0], span2, 0, 0, SPAN2_FLAGS);
-
-        // text:  "a"
-        // span1:  ^
-        // span2:  ^
-        // span3:
-        assertEquals("a", charSequencesFromString[1].toString());
-        assertSpanCount(0, charSequencesFromString[1]);
-        assertEquals("a", charSequencesFromSpanned[1].toString());
-        assertSpanCount(2, charSequencesFromSpanned[1]);
-        assertSpan(charSequencesFromSpanned[1], span1, 0, 1, SPAN1_FLAGS);
-        assertSpan(charSequencesFromSpanned[1], span2, 0, 1, SPAN2_FLAGS);
-
-        // text:  "bcd"
-        // span1:  ^^^
-        // span2:  ^^
-        // span3:
-        assertEquals("bcd", charSequencesFromString[2].toString());
-        assertSpanCount(0, charSequencesFromString[2]);
-        assertEquals("bcd", charSequencesFromSpanned[2].toString());
-        assertSpanCount(2, charSequencesFromSpanned[2]);
-        assertSpan(charSequencesFromSpanned[2], span1, 0, 3, SPAN1_FLAGS);
-        assertSpan(charSequencesFromSpanned[2], span2, 0, 2, SPAN2_FLAGS);
-
-        // text:  "efg"
-        // span1:
-        // span2:
-        // span3:
-        assertEquals("efg", charSequencesFromString[3].toString());
-        assertSpanCount(0, charSequencesFromString[3]);
-        assertEquals("efg", charSequencesFromSpanned[3].toString());
-        assertSpanCount(0, charSequencesFromSpanned[3]);
-
-        // text:  "hij"
-        // span1:
-        // span2:
-        // span3:   ^
-        assertEquals("hij", charSequencesFromString[4].toString());
-        assertSpanCount(0, charSequencesFromString[4]);
-        assertEquals("hij", charSequencesFromSpanned[4].toString());
-        assertSpanCount(1, charSequencesFromSpanned[4]);
-        assertSpan(charSequencesFromSpanned[4], span3, 1, 2, SPAN3_FLAGS);
-
-        // text:  ""
-        // span1:
-        // span2:
-        // span3:
-        assertEquals("", charSequencesFromString[5].toString());
-        assertSpanCount(0, charSequencesFromString[5]);
-        assertEquals("", charSequencesFromSpanned[5].toString());
-        assertSpanCount(0, charSequencesFromSpanned[5]);
-
-        // text:  ""
-        // span1:
-        // span2:
-        // span3:
-        assertEquals("", charSequencesFromString[6].toString());
-        assertSpanCount(0, charSequencesFromString[6]);
-        assertEquals("", charSequencesFromSpanned[6].toString());
-        assertSpanCount(0, charSequencesFromSpanned[6]);
-    }
-
-    public void testSplitCharSequencePreserveTrailingEmptySegmengs() {
-        assertEquals(1, StringUtils.split("", " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(1, StringUtils.split(new SpannedString(""), " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(1, StringUtils.split("", " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(1, StringUtils.split(new SpannedString(""), " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(0, StringUtils.split(" ", " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(0, StringUtils.split(new SpannedString(" "), " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(2, StringUtils.split(" ", " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(2, StringUtils.split(new SpannedString(" "), " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(3, StringUtils.split("a b c  ", " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(3, StringUtils.split(new SpannedString("a b c  "), " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(5, StringUtils.split("a b c  ", " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(5, StringUtils.split(new SpannedString("a b c  "), " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(6, StringUtils.split("a     b ", " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(6, StringUtils.split(new SpannedString("a     b "), " ",
-                false /* preserveTrailingEmptySegmengs */).length);
-
-        assertEquals(7, StringUtils.split("a     b ", " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-        assertEquals(7, StringUtils.split(new SpannedString("a     b "), " ",
-                true /* preserveTrailingEmptySegmengs */).length);
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
deleted file mode 100644
index ba2e998..0000000
--- a/tests/src/com/android/inputmethod/latin/utils/StringUtilsTests.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.utils.StringUtils;
-
-import java.util.Locale;
-
-@SmallTest
-public class StringUtilsTests extends AndroidTestCase {
-    private static final Locale US = Locale.US;
-    private static final Locale GERMAN = Locale.GERMAN;
-    private static final Locale TURKEY = new Locale("tr", "TR");
-    private static final Locale GREECE = new Locale("el", "GR");
-
-    private static void assert_toUpperCaseOfStringForLocale(final Locale locale,
-            final String lowerCase, final String expected) {
-        assertEquals(lowerCase + " in " + locale, expected,
-                StringUtils.toUpperCaseOfStringForLocale(
-                        lowerCase, true /* needsToUpperCase */, locale));
-    }
-
-    public void test_toUpperCaseOfStringForLocale() {
-        assert_toUpperCaseOfStringForLocale(US, null, null);
-        assert_toUpperCaseOfStringForLocale(US, "", "");
-        assert_toUpperCaseOfStringForLocale(US, "aeiou", "AEIOU");
-        // U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
-        // U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
-        // U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
-        // U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
-        // U+016B: "ū" LATIN SMALL LETTER U WITH MACRON
-        // U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
-        // U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
-        // U+00C0: "À" LATIN CAPITAL LETTER A WITH GRAVE
-        // U+00C8: "È" LATIN CAPITAL LETTER E WITH GRAVE
-        // U+00CE: "Î" LATIN CAPITAL LETTER I WITH CIRCUMFLEX
-        // U+00D6: "Ö" LATIN CAPITAL LETTER O WITH DIAERESIS
-        // U+016A: "Ū" LATIN CAPITAL LETTER U WITH MACRON
-        // U+00D1: "Ñ" LATIN CAPITAL LETTER N WITH TILDE
-        // U+00C7: "Ç" LATIN CAPITAL LETTER C WITH CEDILLA
-        assert_toUpperCaseOfStringForLocale(US,
-                "\u00E0\u00E8\u00EE\u00F6\u016B\u00F1\u00E7",
-                "\u00C0\u00C8\u00CE\u00D6\u016A\u00D1\u00C7");
-        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-        // U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
-        // U+0161: "š" LATIN SMALL LETTER S WITH CARON
-        // U+015A: "Ś" LATIN CAPITAL LETTER S WITH ACUTE
-        // U+0160: "Š" LATIN CAPITAL LETTER S WITH CARONZ
-        assert_toUpperCaseOfStringForLocale(GERMAN,
-                "\u00DF\u015B\u0161",
-                "SS\u015A\u0160");
-        // U+0259: "ə" LATIN SMALL LETTER SCHWA
-        // U+0069: "i" LATIN SMALL LETTER I
-        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-        // U+018F: "Ə" LATIN SMALL LETTER SCHWA
-        // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
-        // U+0049: "I" LATIN SMALL LETTER I
-        assert_toUpperCaseOfStringForLocale(TURKEY,
-                "\u0259\u0069\u0131",
-                "\u018F\u0130\u0049");
-        // U+03C3: "σ" GREEK SMALL LETTER SIGMA
-        // U+03C2: "ς" GREEK SMALL LETTER FINAL SIGMA
-        // U+03A3: "Σ" GREEK CAPITAL LETTER SIGMA
-        assert_toUpperCaseOfStringForLocale(GREECE,
-                "\u03C3\u03C2",
-                "\u03A3\u03A3");
-        // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
-        // U+03AD: "έ" GREEK SMALL LETTER EPSILON WITH TONOS
-        // U+03AE: "ή" GREEK SMALL LETTER ETA WITH TONOS
-        // U+03AF: "ί" GREEK SMALL LETTER IOTA WITH TONOS
-        // U+03CC: "ό" GREEK SMALL LETTER OMICRON WITH TONOS
-        // U+03CD: "ύ" GREEK SMALL LETTER UPSILON WITH TONOS
-        // U+03CE: "ώ" GREEK SMALL LETTER OMEGA WITH TONOS
-        // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
-        // U+0388: "Έ" GREEK CAPITAL LETTER EPSILON WITH TONOS
-        // U+0389: "Ή" GREEK CAPITAL LETTER ETA WITH TONOS
-        // U+038A: "Ί" GREEK CAPITAL LETTER IOTA WITH TONOS
-        // U+038C: "Ό" GREEK CAPITAL LETTER OMICRON WITH TONOS
-        // U+038E: "Ύ" GREEK CAPITAL LETTER UPSILON WITH TONOS
-        // U+038F: "Ώ" GREEK CAPITAL LETTER OMEGA WITH TONOS
-        assert_toUpperCaseOfStringForLocale(GREECE,
-                "\u03AC\u03AD\u03AE\u03AF\u03CC\u03CD\u03CE",
-                "\u0386\u0388\u0389\u038A\u038C\u038E\u038F");
-        // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
-        // U+03CB: "ϋ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA
-        // U+0390: "ΐ" GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-        // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-        // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
-        // U+03AB: "Ϋ" GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
-        // U+0399: "Ι" GREEK CAPITAL LETTER IOTA
-        // U+03A5: "Υ" GREEK CAPITAL LETTER UPSILON
-        // U+0308: COMBINING DIAERESIS
-        // U+0301: COMBINING GRAVE ACCENT
-        assert_toUpperCaseOfStringForLocale(GREECE,
-                "\u03CA\u03CB\u0390\u03B0",
-                "\u03AA\u03AB\u0399\u0308\u0301\u03A5\u0308\u0301");
-    }
-
-    private static void assert_toUpperCaseOfCodeForLocale(final Locale locale, final int lowerCase,
-            final int expected) {
-        assertEquals(lowerCase + " in " + locale, expected,
-                StringUtils.toUpperCaseOfCodeForLocale(
-                        lowerCase, true /* needsToUpperCase */, locale));
-    }
-
-    public void test_toUpperCaseOfCodeForLocale() {
-        assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_ENTER, Constants.CODE_ENTER);
-        assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_SPACE, Constants.CODE_SPACE);
-        assert_toUpperCaseOfCodeForLocale(US, Constants.CODE_COMMA, Constants.CODE_COMMA);
-        // U+0069: "i" LATIN SMALL LETTER I
-        // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
-        // U+0130: "İ" LATIN SMALL LETTER I WITH DOT ABOVE
-        // U+0049: "I" LATIN SMALL LETTER I
-        assert_toUpperCaseOfCodeForLocale(US, 0x0069, 0x0049); // i -> I
-        assert_toUpperCaseOfCodeForLocale(US, 0x0131, 0x0049); // ı -> I
-        assert_toUpperCaseOfCodeForLocale(TURKEY, 0x0069, 0x0130); // i -> İ
-        assert_toUpperCaseOfCodeForLocale(TURKEY, 0x0131, 0x0049); // ı -> I
-        // U+00DF: "ß" LATIN SMALL LETTER SHARP S
-        // The title case of "ß" is "SS".
-        assert_toUpperCaseOfCodeForLocale(US, 0x00DF, Constants.CODE_UNSPECIFIED);
-        // U+03AC: "ά" GREEK SMALL LETTER ALPHA WITH TONOS
-        // U+0386: "Ά" GREEK CAPITAL LETTER ALPHA WITH TONOS
-        assert_toUpperCaseOfCodeForLocale(GREECE, 0x03AC, 0x0386);
-        // U+03CA: "ϊ" GREEK SMALL LETTER IOTA WITH DIALYTIKA
-        // U+03AA: "Ϊ" GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
-        assert_toUpperCaseOfCodeForLocale(GREECE, 0x03CA, 0x03AA);
-        // U+03B0: "ΰ" GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-        // The title case of "ΰ" is "\u03A5\u0308\u0301".
-        assert_toUpperCaseOfCodeForLocale(GREECE, 0x03B0, Constants.CODE_UNSPECIFIED);
-    }
-
-    private static void assert_capitalizeFirstCodePoint(final Locale locale, final String text,
-            final String expected) {
-        assertEquals(text + " in " + locale, expected,
-                StringUtils.capitalizeFirstCodePoint(text, locale));
-    }
-
-    public void test_capitalizeFirstCodePoint() {
-        assert_capitalizeFirstCodePoint(US, "", "");
-        assert_capitalizeFirstCodePoint(US, "a", "A");
-        assert_capitalizeFirstCodePoint(US, "à", "À");
-        assert_capitalizeFirstCodePoint(US, "ß", "SS");
-        assert_capitalizeFirstCodePoint(US, "text", "Text");
-        assert_capitalizeFirstCodePoint(US, "iGoogle", "IGoogle");
-        assert_capitalizeFirstCodePoint(TURKEY, "iyi", "İyi");
-        assert_capitalizeFirstCodePoint(TURKEY, "ısırdı", "Isırdı");
-        assert_capitalizeFirstCodePoint(GREECE, "ά", "Ά");
-        assert_capitalizeFirstCodePoint(GREECE, "άνεση", "Άνεση");
-    }
-
-    private static void assert_capitalizeFirstAndDowncaseRest(final Locale locale,
-            final String text, final String expected) {
-        assertEquals(text + " in " + locale, expected,
-                StringUtils.capitalizeFirstAndDowncaseRest(text, locale));
-    }
-
-    public void test_capitalizeFirstAndDowncaseRest() {
-        assert_capitalizeFirstAndDowncaseRest(US, "", "");
-        assert_capitalizeFirstAndDowncaseRest(US, "a", "A");
-        assert_capitalizeFirstAndDowncaseRest(US, "à", "À");
-        assert_capitalizeFirstAndDowncaseRest(US, "ß", "SS");
-        assert_capitalizeFirstAndDowncaseRest(US, "text", "Text");
-        assert_capitalizeFirstAndDowncaseRest(US, "iGoogle", "Igoogle");
-        assert_capitalizeFirstAndDowncaseRest(US, "invite", "Invite");
-        assert_capitalizeFirstAndDowncaseRest(US, "INVITE", "Invite");
-        assert_capitalizeFirstAndDowncaseRest(TURKEY, "iyi", "İyi");
-        assert_capitalizeFirstAndDowncaseRest(TURKEY, "İYİ", "İyi");
-        assert_capitalizeFirstAndDowncaseRest(TURKEY, "ısırdı", "Isırdı");
-        assert_capitalizeFirstAndDowncaseRest(TURKEY, "ISIRDI", "Isırdı");
-        assert_capitalizeFirstAndDowncaseRest(GREECE, "ά", "Ά");
-        assert_capitalizeFirstAndDowncaseRest(GREECE, "άνεση", "Άνεση");
-        assert_capitalizeFirstAndDowncaseRest(GREECE, "ΆΝΕΣΗ", "Άνεση");
-    }
-}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index ce3df7d..2297cac 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -23,7 +23,9 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.RichInputMethodSubtype;
 
 import java.util.ArrayList;
 import java.util.Locale;
@@ -31,10 +33,11 @@
 @SmallTest
 public class SubtypeLocaleUtilsTests extends AndroidTestCase {
     // All input method subtypes of LatinIME.
-    private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<>();
+    private final ArrayList<RichInputMethodSubtype> mSubtypesList = new ArrayList<>();
 
     private RichInputMethodManager mRichImm;
     private Resources mRes;
+    private InputMethodSubtype mSavedAddtionalSubtypes[];
 
     InputMethodSubtype EN_US;
     InputMethodSubtype EN_GB;
@@ -44,6 +47,8 @@
     InputMethodSubtype FR_CH;
     InputMethodSubtype DE;
     InputMethodSubtype DE_CH;
+    InputMethodSubtype HI;
+    InputMethodSubtype SR;
     InputMethodSubtype ZZ;
     InputMethodSubtype DE_QWERTY;
     InputMethodSubtype FR_QWERTZ;
@@ -53,20 +58,33 @@
     InputMethodSubtype ZZ_AZERTY;
     InputMethodSubtype ZZ_PC;
 
+    // These are preliminary subtypes and may not exist.
+    InputMethodSubtype HI_LATN; // Hinglish
+    InputMethodSubtype SR_LATN; // Serbian Latin
+    InputMethodSubtype HI_LATN_DVORAK; // Hinglis Dvorak
+    InputMethodSubtype SR_LATN_QWERTY; // Serbian Latin Qwerty
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         final Context context = getContext();
+        mRes = context.getResources();
         RichInputMethodManager.init(context);
         mRichImm = RichInputMethodManager.getInstance();
-        mRes = context.getResources();
-        SubtypeLocaleUtils.init(context);
+
+        // Save and reset additional subtypes
+        mSavedAddtionalSubtypes = mRichImm.getAdditionalSubtypes();
+        final InputMethodSubtype[] predefinedAddtionalSubtypes =
+                AdditionalSubtypeUtils.createAdditionalSubtypesArray(
+                        AdditionalSubtypeUtils.createPrefSubtypes(
+                                mRes.getStringArray(R.array.predefined_subtypes)));
+        mRichImm.setAdditionalInputMethodSubtypes(predefinedAddtionalSubtypes);
 
         final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme();
         final int subtypeCount = imi.getSubtypeCount();
         for (int index = 0; index < subtypeCount; index++) {
             final InputMethodSubtype subtype = imi.getSubtypeAt(index);
-            mSubtypesList.add(subtype);
+            mSubtypesList.add(new RichInputMethodSubtype(subtype));
         }
 
         EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
@@ -85,6 +103,10 @@
                 Locale.GERMAN.toString(), "qwertz");
         DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                 "de_CH", "swiss");
+        HI = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "hi", "hindi");
+        SR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
+                "sr", "south_slavic");
         ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                 SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
         DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
@@ -101,19 +123,37 @@
                 SubtypeLocaleUtils.NO_LANGUAGE, "azerty");
         ZZ_PC = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
                 SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty");
+
+        HI_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("hi_ZZ", "qwerty");
+        if (HI_LATN != null) {
+            HI_LATN_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    "hi_ZZ", "dvorak");
+        }
+        SR_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("sr_ZZ", "serbian_qwertz");
+        if (SR_LATN != null) {
+            SR_LATN_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(
+                    "sr_ZZ", "qwerty");
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Restore additional subtypes.
+        mRichImm.setAdditionalInputMethodSubtypes(mSavedAddtionalSubtypes);
+        super.tearDown();
     }
 
     public void testAllFullDisplayName() {
-        for (final InputMethodSubtype subtype : mSubtypesList) {
+        for (final RichInputMethodSubtype subtype : mSubtypesList) {
             final String subtypeName = SubtypeLocaleUtils
-                    .getSubtypeDisplayNameInSystemLocale(subtype);
-            if (SubtypeLocaleUtils.isNoLanguage(subtype)) {
+                    .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
+            if (subtype.isNoLanguage()) {
                 final String layoutName = SubtypeLocaleUtils
-                        .getKeyboardLayoutSetDisplayName(subtype);
+                        .getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
                 assertTrue(subtypeName, subtypeName.contains(layoutName));
             } else {
                 final String languageName = SubtypeLocaleUtils
-                        .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale());
+                        .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale().toString());
                 assertTrue(subtypeName, subtypeName.contains(languageName));
             }
         }
@@ -128,6 +168,8 @@
         assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH));
         assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE));
         assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH));
+        assertEquals("hi", "hindi", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI));
+        assertEquals("sr", "south_slavic", SubtypeLocaleUtils.getKeyboardLayoutSetName(SR));
         assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ));
 
         assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY));
@@ -140,27 +182,46 @@
                 SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US_COLEMAK));
         assertEquals("zz azerty", "azerty",
                 SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ_AZERTY));
+
+        // These are preliminary subtypes and may not exist.
+        if (HI_LATN != null) {
+            assertEquals("hi_ZZ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN));
+            assertEquals("hi_ZZ dvorak", "dvorak",
+                    SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN_DVORAK));
+        }
+        if (SR_LATN != null) {
+            assertEquals("sr_ZZ", "serbian_qwertz",
+                    SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN));
+            assertEquals("sr_ZZ qwerty", "qwerty",
+                    SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN_QWERTY));
+        }
     }
 
     // InputMethodSubtype's display name in system locale (en_US).
-    //        isAdditionalSubtype (T=true, F=false)
-    // locale layout  |  display name
-    // ------ ------- - ----------------------
-    //  en_US qwerty  F  English (US)            exception
-    //  en_GB qwerty  F  English (UK)            exception
-    //  es_US spanish F  Spanish (US)            exception
-    //  fr    azerty  F  French
-    //  fr_CA qwerty  F  French (Canada)
-    //  fr_CH swiss   F  French (Switzerland)
-    //  de    qwertz  F  German
-    //  de_CH swiss   F  German (Switzerland)
-    //  zz    qwerty  F  Alphabet (QWERTY)
-    //  fr    qwertz  T  French (QWERTZ)
-    //  de    qwerty  T  German (QWERTY)
-    //  en_US azerty  T  English (US) (AZERTY)   exception
-    //  en_UK dvorak  T  English (UK) (Dvorak)   exception
-    //  es_US colemak T  Spanish (US) (Colemak)  exception
-    //  zz    pc      T  Alphabet (PC)
+    //               isAdditionalSubtype (T=true, F=false)
+    // locale layout         |  display name
+    // ------ -------------- - ----------------------
+    //  en_US qwerty         F  English (US)            exception
+    //  en_GB qwerty         F  English (UK)            exception
+    //  es_US spanish        F  Spanish (US)            exception
+    //  fr    azerty         F  French
+    //  fr_CA qwerty         F  French (Canada)
+    //  fr_CH swiss          F  French (Switzerland)
+    //  de    qwertz         F  German
+    //  de_CH swiss          F  German (Switzerland)
+    //  hi    hindi          F  Hindi
+    //  hi_ZZ qwerty         F  Hinglish                exception
+    //  sr    south_slavic   F  Serbian
+    //  sr_ZZ serbian_qwertz F  Serbian (Latin)         exception
+    //  zz    qwerty         F  Alphabet (QWERTY)
+    //  fr    qwertz         T  French (QWERTZ)
+    //  de    qwerty         T  German (QWERTY)
+    //  en_US azerty         T  English (US) (AZERTY)   exception
+    //  en_UK dvorak         T  English (UK) (Dvorak)   exception
+    //  es_US colemak        T  Spanish (US) (Colemak)  exception
+    //  hi_ZZ dvorak         T  Hinglish (Dvorka)       exception
+    //  sr_ZZ qwerty         T  Serbian (QWERTY)        exception
+    //  zz    pc             T  Alphabet (PC)
 
     public void testPredefinedSubtypesInEnglishSystemLocale() {
         final RunInLocale<Void> tests = new RunInLocale<Void>() {
@@ -182,8 +243,21 @@
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
                 assertEquals("de_CH", "German (Switzerland)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
+                assertEquals("hi", "Hindi",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+                assertEquals("sr", "Serbian",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
                 assertEquals("zz", "Alphabet (QWERTY)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+                // These are preliminary subtypes and may not exist.
+                if (HI_LATN != null) {
+                    assertEquals("hi_ZZ", "Hinglish",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+                }
+                if (SR_LATN != null) {
+                    assertEquals("sr_ZZ", "Serbian (Latin)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+                }
                 return null;
             }
         };
@@ -208,6 +282,15 @@
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
                 assertEquals("zz pc", "Alphabet (PC)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+                // These are preliminary subtypes and may not exist.
+                if (HI_LATN_DVORAK != null) {
+                    assertEquals("hi_ZZ", "Hinglish (Dvorak)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+                }
+                if (SR_LATN_QWERTY != null) {
+                    assertEquals("sr_ZZ", "Serbian (QWERTY)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+                }
                 return null;
             }
         };
@@ -218,21 +301,27 @@
     //        isAdditionalSubtype (T=true, F=false)
     // locale layout  |  display name
     // ------ ------- - ----------------------
-    //  en_US qwerty  F  Anglais (États-Unis)            exception
-    //  en_GB qwerty  F  Anglais (Royaume-Uni)            exception
-    //  es_US spanish F  Espagnol (États-Unis)            exception
-    //  fr    azerty  F  Français
-    //  fr_CA qwerty  F  Français (Canada)
-    //  fr_CH swiss   F  Français (Suisse)
-    //  de    qwertz  F  Allemand
-    //  de_CH swiss   F  Allemand (Suisse)
-    //  zz    qwerty  F  Alphabet latin (QWERTY)
-    //  fr    qwertz  T  Français (QWERTZ)
-    //  de    qwerty  T  Allemand (QWERTY)
-    //  en_US azerty  T  Anglais (États-Unis) (AZERTY)   exception
-    //  en_UK dvorak  T  Anglais (Royaume-Uni) (Dvorak)   exception
-    //  es_US colemak T  Espagnol (États-Unis) (Colemak)  exception
-    //  zz    pc      T  Alphabet latin (PC)
+    //  en_US qwerty         F  Anglais (États-Unis)             exception
+    //  en_GB qwerty         F  Anglais (Royaume-Uni)            exception
+    //  es_US spanish        F  Espagnol (États-Unis)            exception
+    //  fr    azerty         F  Français
+    //  fr_CA qwerty         F  Français (Canada)
+    //  fr_CH swiss          F  Français (Suisse)
+    //  de    qwertz         F  Allemand
+    //  de_CH swiss          F  Allemand (Suisse)
+    //  hi    hindi          F  Hindi                            exception
+    //  hi_ZZ qwerty         F  Hindi/Anglais                    exception
+    //  sr    south_slavic   F  Serbe                            exception
+    //  sr_ZZ serbian_qwertz F  Serbe (latin)                    exception
+    //  zz    qwerty         F  Alphabet latin (QWERTY)
+    //  fr    qwertz         T  Français (QWERTZ)
+    //  de    qwerty         T  Allemand (QWERTY)
+    //  en_US azerty         T  Anglais (États-Unis) (AZERTY)    exception
+    //  en_UK dvorak         T  Anglais (Royaume-Uni) (Dvorak)   exception
+    //  es_US colemak        T  Espagnol (États-Unis) (Colemak)  exception
+    //  hi_ZZ dvorak         T  Hindi/Anglais (Dvorka)           exception
+    //  sr_ZZ qwerty         T  Serbe (QWERTY)                   exception
+    //  zz    pc             T  Alphabet latin (PC)
 
     public void testPredefinedSubtypesInFrenchSystemLocale() {
         final RunInLocale<Void> tests = new RunInLocale<Void>() {
@@ -254,8 +343,21 @@
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE));
                 assertEquals("de_CH", "Allemand (Suisse)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH));
+                assertEquals("hi", "Hindi",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+                assertEquals("sr", "Serbe",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
                 assertEquals("zz", "Alphabet latin (QWERTY)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ));
+                // These are preliminary subtypes and may not exist.
+                if (HI_LATN != null) {
+                    assertEquals("hi_ZZ", "Hindi/Anglais",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+                }
+                if (SR_LATN != null) {
+                    assertEquals("sr_ZZ", "Serbe (latin)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+                }
                 return null;
             }
         };
@@ -280,12 +382,75 @@
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY));
                 assertEquals("zz pc", "Alphabet latin (PC)",
                         SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC));
+                // These are preliminary subtypes and may not exist.
+                if (HI_LATN_DVORAK != null) {
+                    assertEquals("hi_ZZ", "Hindi/Anglais (Dvorak)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+                }
+                if (SR_LATN_QWERTY != null) {
+                    assertEquals("sr_ZZ", "Serbe (QWERTY)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+                }
                 return null;
             }
         };
         tests.runInLocale(mRes, Locale.FRENCH);
     }
 
+    // InputMethodSubtype's display name in system locale (hi).
+    //        isAdditionalSubtype (T=true, F=false)
+    // locale layout  |  display name
+    // ------ ------- - ----------------------
+    //  hi    hindi   F  हिन्दी
+    //  hi_ZZ qwerty  F  हिंग्लिश
+    //  hi_ZZ dvorak  T  हिंग्लिश (Dvorak)
+
+    public void testHinglishSubtypesInHindiSystemLocale() {
+        final RunInLocale<Void> tests = new RunInLocale<Void>() {
+            @Override
+            protected Void job (final Resources res) {
+                assertEquals("hi", "हिन्दी",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI));
+                // These are preliminary subtypes and may not exist.
+                if (HI_LATN != null) {
+                    assertEquals("hi_ZZ", "हिंग्लिश",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN));
+                    assertEquals("hi_ZZ", "हिंग्लिश (Dvorak)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK));
+                }
+                return null;
+            }
+        };
+        tests.runInLocale(mRes, new Locale("hi"));
+    }
+
+    // InputMethodSubtype's display name in system locale (sr).
+    //               isAdditionalSubtype (T=true, F=false)
+    // locale layout         |  display name
+    // ------ -------------- - ----------------------
+    //  sr    south_slavic   F  Српски
+    //  sr_ZZ serbian_qwertz F  Српски (латиница)
+    //  sr_ZZ qwerty         T  Српски (QWERTY)
+
+    public void testSerbianLatinSubtypesInSerbianSystemLocale() {
+        final RunInLocale<Void> tests = new RunInLocale<Void>() {
+            @Override
+            protected Void job (final Resources res) {
+                assertEquals("sr", "Српски",
+                        SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR));
+                // These are preliminary subtypes and may not exist.
+                if (SR_LATN != null) {
+                    assertEquals("sr_ZZ", "Српски (латиница)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN));
+                    assertEquals("sr_ZZ", "Српски (QWERTY)",
+                            SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY));
+                }
+                return null;
+            }
+        };
+        tests.runInLocale(mRes, new Locale("sr"));
+    }
+
     public void testIsRtlLanguage() {
         // Known Right-to-Left language subtypes.
         final InputMethodSubtype ARABIC = mRichImm
@@ -298,13 +463,15 @@
                 .findSubtypeByLocaleAndKeyboardLayoutSet("iw", "hebrew");
         assertNotNull("Hebrew", HEBREW);
 
-        for (final InputMethodSubtype subtype : mSubtypesList) {
+        for (final RichInputMethodSubtype subtype : mSubtypesList) {
+            final InputMethodSubtype rawSubtype = subtype.getRawSubtype();
             final String subtypeName = SubtypeLocaleUtils
-                    .getSubtypeDisplayNameInSystemLocale(subtype);
-            if (subtype.equals(ARABIC) || subtype.equals(FARSI) || subtype.equals(HEBREW)) {
-                assertTrue(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+                    .getSubtypeDisplayNameInSystemLocale(rawSubtype);
+            if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI)
+                    || rawSubtype.equals(HEBREW)) {
+                assertTrue(subtypeName, subtype.isRtlSubtype());
             } else {
-                assertFalse(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+                assertFalse(subtypeName, subtype.isRtlSubtype());
             }
         }
     }
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index 3e3d419..1a9f029 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -35,7 +35,6 @@
 LATINIME_BASE_SRC_DIR := $(LATINIME_LOCAL_DIR)/java/src/com/android/inputmethod
 LATINIME_BASE_OVERRIDABLE_SRC_DIR := \
         $(LATINIME_LOCAL_DIR)/java-overridable/src/com/android/inputmethod
-LATINIME_ANNOTATIONS_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/annotations
 MAKEDICT_CORE_SRC_DIR := $(LATINIME_BASE_SRC_DIR)/latin/makedict
 LATINIME_TESTS_SRC_DIR := $(LATINIME_LOCAL_DIR)/tests/src/com/android/inputmethod/latin
 
@@ -43,26 +42,15 @@
 # a significant part of the dependencies are mocked in the compat/ directory, with empty or
 # nearly-empty implementations, for parts that we don't use in Dicttool.
 LATINIME_SRC_FILES_FOR_DICTTOOL := \
-        event/Combiner.java \
-        event/Event.java \
         latin/BinaryDictionary.java \
         latin/DicTraverseSession.java \
         latin/Dictionary.java \
-        latin/InputPointers.java \
-        latin/LastComposedWord.java \
-        latin/PrevWordsInfo.java \
+        latin/NgramContext.java \
         latin/SuggestedWords.java \
-        latin/WordComposer.java \
-        latin/settings/NativeSuggestOptions.java \
         latin/settings/SettingsValuesForSuggestion.java \
         latin/utils/BinaryDictionaryUtils.java \
         latin/utils/CombinedFormatUtils.java \
-        latin/utils/CoordinateUtils.java \
-        latin/utils/FileUtils.java \
-        latin/utils/JniUtils.java \
-        latin/utils/LocaleUtils.java \
-        latin/utils/ResizableIntArray.java \
-        latin/utils/StringUtils.java
+        latin/utils/JniUtils.java
 
 LATINIME_OVERRIDABLE_SRC_FILES_FOR_DICTTOOL := \
         latin/define/DebugFlags.java
@@ -82,18 +70,15 @@
 
 LOCAL_MAIN_SRC_FILES := $(call all-java-files-under, $(MAKEDICT_CORE_SRC_DIR))
 LOCAL_TOOL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_ANNOTATIONS_SRC_FILES := $(call all-java-files-under, $(LATINIME_ANNOTATIONS_SRC_DIR))
 
 LOCAL_SRC_FILES := $(LOCAL_TOOL_SRC_FILES) \
         $(filter-out $(addprefix %/, $(notdir $(LOCAL_TOOL_SRC_FILES))), $(LOCAL_MAIN_SRC_FILES)) \
-        $(call all-java-files-under, $(DICTTOOL_COMPAT_TESTS_DIR)) \
-        $(LOCAL_ANNOTATIONS_SRC_FILES) $(USED_TARGETED_SRC_FILES) \
-        $(LATINIME_BASE_SRC_DIR)/latin/Constants.java \
-        $(call all-java-files-under, tests) \
-        $(call all-java-files-under, $(DICTTOOL_ONDEVICE_TESTS_DIR))
+        $(USED_TARGETED_SRC_FILES) \
+        $(call all-java-files-under, \
+                tests $(DICTTOOL_COMPAT_TESTS_DIR) $(DICTTOOL_ONDEVICE_TESTS_DIR))
 
 LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib
+LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib latinime-common-host
 LOCAL_REQUIRED_MODULES := $(LATINIME_HOST_NATIVE_LIBNAME)
 LOCAL_JAR_MANIFEST := etc/manifest.txt
 LOCAL_MODULE := dicttool_aosp
diff --git a/tools/dicttool/compat/android/test/MoreAsserts.java b/tools/dicttool/compat/android/test/MoreAsserts.java
deleted file mode 100644
index f56420b..0000000
--- a/tools/dicttool/compat/android/test/MoreAsserts.java
+++ /dev/null
@@ -1,35 +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 android.test;
-
-import junit.framework.Assert;
-
-/**
- * This is a compatibility class that aims at emulating android.test.MoreAsserts from the
- * Android library as simply as possible, and only to the extent that is used by the client classes.
- * Its purpose is to provide compatibility without having to pull the whole Android library.
- */
-public class MoreAsserts {
-    public static void assertNotEqual(Object unexpected, Object actual) {
-        if (equal(unexpected, actual)) {
-            Assert.fail("expected not to be:<" + unexpected + ">");
-        }
-    }
-    private static boolean equal(Object a, Object b) {
-        return a == b || (a != null && a.equals(b));
-    }
-}
diff --git a/tools/dicttool/compat/android/text/TextUtils.java b/tools/dicttool/compat/android/text/TextUtils.java
index 5a94b7d..8248331 100644
--- a/tools/dicttool/compat/android/text/TextUtils.java
+++ b/tools/dicttool/compat/android/text/TextUtils.java
@@ -25,10 +25,7 @@
      * @return true if str is null or zero length
      */
     public static boolean isEmpty(CharSequence str) {
-        if (str == null || str.length() == 0)
-            return true;
-        else
-            return false;
+        return (str == null || str.length() == 0);
     }
 
     /**
@@ -45,12 +42,11 @@
         if (a != null && b != null && (length = a.length()) == b.length()) {
             if (a instanceof String && b instanceof String) {
                 return a.equals(b);
-            } else {
-                for (int i = 0; i < length; i++) {
-                    if (a.charAt(i) != b.charAt(i)) return false;
-                }
-                return true;
             }
+            for (int i = 0; i < length; i++) {
+                if (a.charAt(i) != b.charAt(i)) return false;
+            }
+            return true;
         }
         return false;
     }
@@ -90,7 +86,7 @@
      * @param tokens an array objects to be joined. Strings will be formed from
      *     the objects by calling object.toString().
      */
-    public static String join(CharSequence delimiter, Iterable tokens) {
+    public static String join(CharSequence delimiter, Iterable<?> tokens) {
         StringBuilder sb = new StringBuilder();
         boolean firstTime = true;
         for (Object token: tokens) {
diff --git a/tools/dicttool/compat/android/util/Pair.java b/tools/dicttool/compat/android/util/Pair.java
index 5bf3484..e61e896 100644
--- a/tools/dicttool/compat/android/util/Pair.java
+++ b/tools/dicttool/compat/android/util/Pair.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import java.util.Arrays;
+import java.util.Objects;
 
 public class Pair<T1, T2> {
     public final T1 mFirst;
@@ -29,7 +29,8 @@
 
     @Override
     public int hashCode() {
-        return Arrays.hashCode(new Object[] { mFirst, mSecond });
+        return (mFirst == null ? 0 : mFirst.hashCode())
+                ^ (mSecond == null ? 0 : mSecond.hashCode());
     }
 
     @Override
@@ -37,7 +38,6 @@
         if (o == this) return true;
         if (!(o instanceof Pair)) return false;
         Pair<?, ?> p = (Pair<?, ?>)o;
-        return ((mFirst == null && p.mFirst == null) || mFirst.equals(p.mFirst))
-                && ((mSecond == null && p.mSecond == null) || mSecond.equals(p.mSecond));
+        return Objects.equals(mFirst, p.mFirst) && Objects.equals(mSecond, p.mSecond);
     }
 }
diff --git a/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java b/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
index fbce725..e2f769e 100644
--- a/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
+++ b/tools/dicttool/compat/android/view/inputmethod/CompletionInfo.java
@@ -16,6 +16,7 @@
 
 package android.view.inputmethod;
 
+@SuppressWarnings("static-method")
 public class CompletionInfo {
     public final String getText() { return ""; }
 }
diff --git a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java b/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
deleted file mode 100644
index c4457a1..0000000
--- a/tools/dicttool/compat/com/android/inputmethod/event/CombinerChain.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014 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.event;
-
-import java.util.ArrayList;
-
-/**
- * Compatibility class that stands in for the combiner chain in LatinIME.
- *
- * This is not used by dicttool, it's just needed by the dependency chain.
- */
-// TODO: there should not be a dependency to this in dicttool, so there
-// should be a sensible way to separate them cleanly.
-public class CombinerChain {
-    private StringBuilder mComposingWord;
-    public CombinerChain(final String initialText, final Combiner... combinerList) {
-        mComposingWord = new StringBuilder(initialText);
-    }
-
-    public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
-        return newEvent;
-    }
-
-    public void applyProcessedEvent(final Event event) {
-        mComposingWord.append(event.getTextToCommit());
-    }
-
-    public CharSequence getComposingWordWithCombiningFeedback() {
-        return mComposingWord;
-    }
-
-    public void reset() {
-        mComposingWord.setLength(0);
-    }
-
-    public static Combiner[] createCombiners(final String spec) {
-        // Dicttool never uses a combiner at all, so we just return a zero-sized array.
-        return new Combiner[0];
-    }
-}
diff --git a/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java b/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
index 1e63bb5..9259406 100644
--- a/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
+++ b/tools/dicttool/compat/com/android/inputmethod/keyboard/Key.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard;
 
+@SuppressWarnings("static-method")
 public class Key {
     public final int getX() { return 0; }
     public final int getY() { return 0; }
diff --git a/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java b/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
index 61b209f..3d6bfd0 100644
--- a/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
+++ b/tools/dicttool/compat/com/android/inputmethod/keyboard/Keyboard.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.keyboard;
 
+@SuppressWarnings("unused")
 public class Keyboard {
     private final Key KEY = new Key();
     public final Key getKey(final int i) { return KEY; }
diff --git a/tools/dicttool/compat/com/android/inputmethod/keyboard/ProximityInfo.java b/tools/dicttool/compat/com/android/inputmethod/keyboard/ProximityInfo.java
index 561b663..3a068bd 100644
--- a/tools/dicttool/compat/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/tools/dicttool/compat/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -18,11 +18,10 @@
 
 public class ProximityInfo {
     public long getNativeProximityInfo() { return 0l; }
-    private static native long setProximityInfoNative(String locale,
-            int displayWidth, int displayHeight, int gridWidth, int gridHeight,
-            int mostCommonKeyWidth, int mostCommonKeyHeight, int[] proximityCharsArray,
-            int keyCount, int[] keyXCoordinates, int[] keyYCoordinates, int[] keyWidths,
-            int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterXs,
+    private static native long setProximityInfoNative(int displayWidth, int displayHeight,
+            int gridWidth, int gridHeight, int mostCommonKeyWidth, int mostCommonKeyHeight,
+            int[] proximityCharsArray, int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
+            int[] keyWidths, int[] keyHeights, int[] keyCharCodes, float[] sweetSpotCenterXs,
             float[] sweetSpotCenterYs, float[] sweetSpotRadii);
     private static native void releaseProximityInfoNative(long nativeProximityInfo);
 }
diff --git a/tools/dicttool/compat/com/android/inputmethod/latin/utils/LanguageModelParam.java b/tools/dicttool/compat/com/android/inputmethod/latin/utils/LanguageModelParam.java
deleted file mode 100644
index f4ca94a..0000000
--- a/tools/dicttool/compat/com/android/inputmethod/latin/utils/LanguageModelParam.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2014 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.utils;
-
-public final class LanguageModelParam {
-}
diff --git a/tools/dicttool/compat/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java b/tools/dicttool/compat/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
new file mode 100644
index 0000000..b5a7294
--- /dev/null
+++ b/tools/dicttool/compat/com/android/inputmethod/latin/utils/WordInputEventForPersonalization.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+public final class WordInputEventForPersonalization {
+}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
index 3ef03f4..b5ed94c 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtils.java
@@ -19,24 +19,28 @@
 import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils;
 import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
 import com.android.inputmethod.latin.makedict.DictDecoder;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
+import com.android.inputmethod.latin.makedict.FormatSpec;
+import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
+import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 import com.android.inputmethod.latin.makedict.FusionDictionary;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 
-import org.xml.sax.SAXException;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.util.ArrayList;
+import java.util.HashMap;
 
-import javax.xml.parsers.ParserConfigurationException;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * Class grouping utilities for offline dictionary making.
@@ -48,30 +52,158 @@
     // Prefix and suffix are arbitrary, the values do not really matter
     private final static String PREFIX = "dicttool";
     private final static String SUFFIX = ".tmp";
-
-    public final static String COMPRESSION = "compressed";
-    public final static String ENCRYPTION = "encrypted";
-
-    private final static int MAX_DECODE_DEPTH = 8;
     private final static int COPY_BUFFER_SIZE = 8192;
 
-    public static class DecoderChainSpec {
-        ArrayList<String> mDecoderSpec = new ArrayList<>();
-        File mFile;
+    public static class DecoderChainSpec<T> {
+        public final static int COMPRESSION = 1;
+        public final static int ENCRYPTION = 2;
 
-        public DecoderChainSpec addStep(final String stepDescription) {
-            mDecoderSpec.add(stepDescription);
-            return this;
+        private final static int[][] VALID_DECODER_CHAINS = {
+            { }, { COMPRESSION }, { ENCRYPTION, COMPRESSION }
+        };
+
+        private final int mDecoderSpecIndex;
+        public T mResult;
+
+        public DecoderChainSpec() {
+            mDecoderSpecIndex = 0;
+            mResult = null;
+        }
+
+        private DecoderChainSpec(final DecoderChainSpec<T> src) {
+            mDecoderSpecIndex = src.mDecoderSpecIndex + 1;
+            mResult = src.mResult;
+        }
+
+        private String getStepDescription(final int step) {
+            switch (step) {
+            case COMPRESSION:
+                return "compression";
+            case ENCRYPTION:
+                return "encryption";
+            default:
+                return "unknown";
+            }
         }
 
         public String describeChain() {
             final StringBuilder s = new StringBuilder("raw");
-            for (final String step : mDecoderSpec) {
+            for (final int step : VALID_DECODER_CHAINS[mDecoderSpecIndex]) {
                 s.append(" > ");
-                s.append(step);
+                s.append(getStepDescription(step));
             }
             return s.toString();
         }
+
+        /**
+         * Returns the next sequential spec. If exhausted, return null.
+         */
+        public DecoderChainSpec next() {
+            if (mDecoderSpecIndex + 1 >= VALID_DECODER_CHAINS.length) {
+                return null;
+            }
+            return new DecoderChainSpec(this);
+        }
+
+        public InputStream getStream(final File src) throws FileNotFoundException, IOException {
+            InputStream input = new BufferedInputStream(new FileInputStream(src));
+            for (final int step : VALID_DECODER_CHAINS[mDecoderSpecIndex]) {
+                switch (step) {
+                case COMPRESSION:
+                    input = Compress.getUncompressedStream(input);
+                    break;
+                case ENCRYPTION:
+                    input = Crypt.getDecryptedStream(input);
+                    break;
+                }
+            }
+            return input;
+        }
+    }
+
+    public interface InputProcessor<T> {
+        @Nonnull
+        public T process(@Nonnull final InputStream input)
+                throws IOException, UnsupportedFormatException;
+    }
+
+    public static class CopyProcessor implements InputProcessor<File> {
+        @Override @Nonnull
+        public File process(@Nonnull final InputStream input) throws IOException,
+                UnsupportedFormatException {
+            final File dst = File.createTempFile(PREFIX, SUFFIX);
+            dst.deleteOnExit();
+            try (final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))) {
+                copy(input, output);
+                output.flush();
+                output.close();
+                if (BinaryDictDecoderUtils.isBinaryDictionary(dst)
+                        || CombinedInputOutput.isCombinedDictionary(dst.getAbsolutePath())) {
+                    return dst;
+                }
+            }
+            throw new UnsupportedFormatException("Input stream not at the expected format");
+        }
+    }
+
+    public static class HeaderReaderProcessor implements InputProcessor<DictionaryHeader> {
+        // Arbitrarily limit the header length to 32k. Sounds like it would never be larger
+        // than this. Revisit this if needed later.
+        private final int MAX_HEADER_LENGTH = 32 * 1024;
+        @Override @Nonnull
+        public DictionaryHeader process(final InputStream input) throws IOException,
+                UnsupportedFormatException {
+            // Do everything as curtly and ad-hoc as possible for performance.
+            final byte[] tmpBuffer = new byte[12];
+            if (tmpBuffer.length != input.read(tmpBuffer)) {
+                throw new UnsupportedFormatException("File too short, not a dictionary");
+            }
+            // Ad-hoc check for the magic number. See FormatSpec.java as well as
+            // byte_array_utils.h and BinaryDictEncoderUtils#writeDictionaryHeader().
+            final int MAGIC_NUMBER_START_OFFSET = 0;
+            final int VERSION_START_OFFSET = 4;
+            final int HEADER_SIZE_OFFSET = 8;
+            final int magicNumber = ((tmpBuffer[MAGIC_NUMBER_START_OFFSET] & 0xFF) << 24)
+                    + ((tmpBuffer[MAGIC_NUMBER_START_OFFSET + 1] & 0xFF) << 16)
+                    + ((tmpBuffer[MAGIC_NUMBER_START_OFFSET + 2] & 0xFF) << 8)
+                    + (tmpBuffer[MAGIC_NUMBER_START_OFFSET + 3] & 0xFF);
+            if (magicNumber != FormatSpec.MAGIC_NUMBER) {
+                throw new UnsupportedFormatException("Wrong magic number");
+            }
+            final int version = ((tmpBuffer[VERSION_START_OFFSET] & 0xFF) << 8)
+                    + (tmpBuffer[VERSION_START_OFFSET + 1] & 0xFF);
+            if (version != FormatSpec.VERSION2 && version != FormatSpec.VERSION201
+                    && version != FormatSpec.VERSION202) {
+                throw new UnsupportedFormatException("Only versions 2, 201, 202 are supported");
+            }
+            final int totalHeaderSize = ((tmpBuffer[HEADER_SIZE_OFFSET] & 0xFF) << 24)
+                    + ((tmpBuffer[HEADER_SIZE_OFFSET + 1] & 0xFF) << 16)
+                    + ((tmpBuffer[HEADER_SIZE_OFFSET + 2] & 0xFF) << 8)
+                    + (tmpBuffer[HEADER_SIZE_OFFSET + 3] & 0xFF);
+            if (totalHeaderSize > MAX_HEADER_LENGTH) {
+                throw new UnsupportedFormatException("Header too large");
+            }
+            final byte[] headerBuffer = new byte[totalHeaderSize - tmpBuffer.length];
+            readStreamExhaustively(input, headerBuffer);
+            final HashMap<String, String> attributes =
+                    BinaryDictDecoderUtils.decodeHeaderAttributes(headerBuffer);
+            return new DictionaryHeader(totalHeaderSize, new DictionaryOptions(attributes),
+                    new FormatOptions(version, false /* hasTimestamp */));
+        }
+    }
+
+    private static void readStreamExhaustively(final InputStream inputStream,
+            final byte[] outBuffer) throws IOException, UnsupportedFormatException {
+        int readBytes = 0;
+        int readBytesLastCycle = -1;
+        while (readBytes != outBuffer.length) {
+            readBytesLastCycle = inputStream.read(outBuffer, readBytes,
+                    outBuffer.length - readBytes);
+            if (readBytesLastCycle == -1)
+                throw new UnsupportedFormatException("File shorter than specified in the header"
+                        + " (expected " + outBuffer.length + ", read " + readBytes + ")");
+            readBytes += readBytesLastCycle;
+        }
     }
 
     public static void copy(final InputStream input, final OutputStream output) throws IOException {
@@ -82,92 +214,51 @@
     }
 
     /**
-     * Returns a decrypted/uncompressed dictionary.
+     * Process a dictionary, decrypting/uncompressing it on the fly as necessary.
      *
-     * This will decrypt/uncompress any number of times as necessary until it finds the
-     * dictionary signature, and copy the decoded file to a temporary place.
-     * If this is not a dictionary, the method returns null.
+     * This will execute the given processor repeatedly with the possible alternatives
+     * for dictionary format until the processor does not throw an exception.
+     * If the processor succeeds for none of the possible formats, the method returns null.
      */
-    public static DecoderChainSpec getRawDictionaryOrNull(final File src) {
-        return getRawDictionaryOrNullInternal(new DecoderChainSpec(), src, 0);
-    }
-
-    private static DecoderChainSpec getRawDictionaryOrNullInternal(
-            final DecoderChainSpec spec, final File src, final int depth) {
-        // Unfortunately the decoding scheme we use can consider any data to be encrypted
-        // and will product some output, meaning it's not possible to reliably detect encrypted
-        // data. Thus, some non-dictionary files (especially small) ones may successfully decrypt
-        // over and over, ending in a stack overflow. Hence we limit the depth at which we try
-        // decoding the file.
-        if (depth > MAX_DECODE_DEPTH) return null;
-        if (BinaryDictDecoderUtils.isBinaryDictionary(src)
-                || CombinedInputOutput.isCombinedDictionary(src.getAbsolutePath())) {
-            spec.mFile = src;
-            return spec;
-        }
-        // It's not a raw dictionary - try to see if it's compressed.
-        final File uncompressedFile = tryGetUncompressedFile(src);
-        if (null != uncompressedFile) {
-            final DecoderChainSpec newSpec =
-                    getRawDictionaryOrNullInternal(spec, uncompressedFile, depth + 1);
-            if (null == newSpec) return null;
-            return newSpec.addStep(COMPRESSION);
-        }
-        // It's not a compressed either - try to see if it's crypted.
-        final File decryptedFile = tryGetDecryptedFile(src);
-        if (null != decryptedFile) {
-            final DecoderChainSpec newSpec =
-                    getRawDictionaryOrNullInternal(spec, decryptedFile, depth + 1);
-            if (null == newSpec) return null;
-            return newSpec.addStep(ENCRYPTION);
+    @Nullable
+    public static <T> DecoderChainSpec<T> decodeDictionaryForProcess(@Nonnull final File src,
+            @Nonnull final InputProcessor<T> processor) {
+        @Nonnull DecoderChainSpec spec = new DecoderChainSpec();
+        while (null != spec) {
+            try {
+                final InputStream input = spec.getStream(src);
+                spec.mResult = processor.process(input);
+                try {
+                    input.close();
+                } catch (IOException e) {
+                    // CipherInputStream doesn't like being closed without having read the
+                    // entire stream, for some reason. But we don't want to because it's a waste
+                    // of resources. We really, really don't care about this.
+                    // However on close() CipherInputStream does throw this exception, wrapped
+                    // in an IOException so we need to catch it.
+                    if (!(e.getCause() instanceof javax.crypto.BadPaddingException)) {
+                        throw e;
+                    }
+                }
+                return spec;
+            } catch (IOException | UnsupportedFormatException | ArrayIndexOutOfBoundsException e) {
+                // If the format is not the right one for this file, the processor will throw one
+                // of these exceptions. In our case, that means we should try the next spec,
+                // since it may still be at another format we haven't tried yet.
+                // TODO: stop using exceptions for this non-exceptional case.
+            }
+            spec = spec.next();
         }
         return null;
     }
 
-    /* Try to uncompress the file passed as an argument.
-     *
-     * If the file can be uncompressed, the uncompressed version is returned. Otherwise, null
-     * is returned.
+    /**
+     * Get a decoder chain spec with a raw dictionary file. This makes a new file on the
+     * disk ready for any treatment the client wants.
      */
-    private static File tryGetUncompressedFile(final File src) {
-        try {
-            final File dst = File.createTempFile(PREFIX, SUFFIX);
-            dst.deleteOnExit();
-            try (
-                final InputStream input = Compress.getUncompressedStream(
-                        new BufferedInputStream(new FileInputStream(src)));
-                final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
-            ) {
-                copy(input, output);
-                return dst;
-            }
-        } catch (final IOException e) {
-            // Could not uncompress the file: presumably the file is simply not a compressed file
-            return null;
-        }
-    }
-
-    /* Try to decrypt the file passed as an argument.
-     *
-     * If the file can be decrypted, the decrypted version is returned. Otherwise, null
-     * is returned.
-     */
-    private static File tryGetDecryptedFile(final File src) {
-        try {
-            final File dst = File.createTempFile(PREFIX, SUFFIX);
-            dst.deleteOnExit();
-            try (
-                final InputStream input = Crypt.getDecryptedStream(
-                        new BufferedInputStream(new FileInputStream(src)));
-                final OutputStream output = new BufferedOutputStream(new FileOutputStream(dst))
-            ) {
-                copy(input, output);
-                return dst;
-            }
-        } catch (final IOException e) {
-            // Could not decrypt the file: presumably the file is simply not a crypted file
-            return null;
-        }
+    @Nullable
+    public static DecoderChainSpec<File> getRawDictionaryOrNull(@Nonnull final File src) {
+        return decodeDictionaryForProcess(src, new CopyProcessor());
     }
 
     static FusionDictionary getDictionary(final String filename, final boolean report) {
@@ -177,40 +268,31 @@
             System.out.println("Size : " + file.length() + " bytes");
         }
         try {
-            if (XmlDictInputOutput.isXmlUnigramDictionary(filename)) {
-                if (report) {
-                    System.out.println("Format : XML unigram list");
-                }
-                return XmlDictInputOutput.readDictionaryXml(
-                        new BufferedInputStream(new FileInputStream(file)),
-                        null /* shortcuts */, null /* bigrams */);
-            }
-            final DecoderChainSpec decodedSpec = getRawDictionaryOrNull(file);
+            final DecoderChainSpec<File> decodedSpec = getRawDictionaryOrNull(file);
             if (null == decodedSpec) {
                 throw new RuntimeException("Does not seem to be a dictionary file " + filename);
             }
-            if (CombinedInputOutput.isCombinedDictionary(decodedSpec.mFile.getAbsolutePath())) {
+            if (CombinedInputOutput.isCombinedDictionary(decodedSpec.mResult.getAbsolutePath())) {
                 if (report) {
                     System.out.println("Format : Combined format");
                     System.out.println("Packaging : " + decodedSpec.describeChain());
-                    System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
+                    System.out.println("Uncompressed size : " + decodedSpec.mResult.length());
                 }
                 try (final BufferedReader reader = new BufferedReader(
-                        new InputStreamReader(new FileInputStream(decodedSpec.mFile), "UTF-8"))) {
+                        new InputStreamReader(new FileInputStream(decodedSpec.mResult), "UTF-8"))) {
                     return CombinedInputOutput.readDictionaryCombined(reader);
                 }
             }
             final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(
-                    decodedSpec.mFile, 0, decodedSpec.mFile.length(),
+                    decodedSpec.mResult, 0, decodedSpec.mResult.length(),
                     DictDecoder.USE_BYTEARRAY);
             if (report) {
                 System.out.println("Format : Binary dictionary format");
                 System.out.println("Packaging : " + decodedSpec.describeChain());
-                System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
+                System.out.println("Uncompressed size : " + decodedSpec.mResult.length());
             }
             return dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
-        } catch (final IOException | SAXException | ParserConfigurationException |
-                UnsupportedFormatException e) {
+        } catch (final IOException | UnsupportedFormatException e) {
             throw new RuntimeException("Can't read file " + filename, e);
         }
     }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
index 23cbee8..955c572 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CombinedInputOutput.java
@@ -98,6 +98,7 @@
         String word = null;
         ProbabilityInfo probabilityInfo = new ProbabilityInfo(0);
         boolean isNotAWord = false;
+        boolean isPossiblyOffensive = false;
         ArrayList<WeightedString> bigrams = new ArrayList<>();
         ArrayList<WeightedString> shortcuts = new ArrayList<>();
         while (null != (line = reader.readLine())) {
@@ -106,7 +107,7 @@
             if (args[0].matches(CombinedFormatUtils.WORD_TAG + "=.*")) {
                 if (null != word) {
                     dict.add(word, probabilityInfo, shortcuts.isEmpty() ? null : shortcuts,
-                            isNotAWord);
+                            isNotAWord, isPossiblyOffensive);
                     for (WeightedString s : bigrams) {
                         dict.setBigram(word, s.mWord, s.mProbabilityInfo);
                     }
@@ -114,27 +115,37 @@
                 if (!shortcuts.isEmpty()) shortcuts = new ArrayList<>();
                 if (!bigrams.isEmpty()) bigrams = new ArrayList<>();
                 isNotAWord = false;
+                isPossiblyOffensive = false;
                 for (String param : args) {
                     final String params[] = param.split("=", 2);
                     if (2 != params.length) throw new RuntimeException("Wrong format : " + line);
-                    if (CombinedFormatUtils.WORD_TAG.equals(params[0])) {
-                        word = params[1];
-                    } else if (CombinedFormatUtils.PROBABILITY_TAG.equals(params[0])) {
-                        probabilityInfo = new ProbabilityInfo(Integer.parseInt(params[1]),
-                                probabilityInfo.mTimestamp, probabilityInfo.mLevel,
-                                probabilityInfo.mCount);
-                    } else if (CombinedFormatUtils.HISTORICAL_INFO_TAG.equals(params[0])) {
-                        final String[] historicalInfoParams =
-                                params[1].split(CombinedFormatUtils.HISTORICAL_INFO_SEPARATOR);
-                        if (historicalInfoParams.length != HISTORICAL_INFO_ELEMENT_COUNT) {
-                            throw new RuntimeException("Wrong format (historical info) : " + line);
-                        }
-                        probabilityInfo = new ProbabilityInfo(probabilityInfo.mProbability,
-                                Integer.parseInt(historicalInfoParams[0]),
-                                Integer.parseInt(historicalInfoParams[1]),
-                                Integer.parseInt(historicalInfoParams[2]));
-                    } else if (CombinedFormatUtils.NOT_A_WORD_TAG.equals(params[0])) {
-                        isNotAWord = "true".equals(params[1]);
+                    switch (params[0]) {
+                        case CombinedFormatUtils.WORD_TAG:
+                            word = params[1];
+                            break;
+                        case CombinedFormatUtils.PROBABILITY_TAG:
+                            probabilityInfo = new ProbabilityInfo(Integer.parseInt(params[1]),
+                                    probabilityInfo.mTimestamp, probabilityInfo.mLevel,
+                                    probabilityInfo.mCount);
+                            break;
+                        case CombinedFormatUtils.HISTORICAL_INFO_TAG:
+                            final String[] historicalInfoParams = params[1].split(
+                                    CombinedFormatUtils.HISTORICAL_INFO_SEPARATOR);
+                            if (historicalInfoParams.length != HISTORICAL_INFO_ELEMENT_COUNT) {
+                                throw new RuntimeException("Wrong format (historical info) : "
+                                        + line);
+                            }
+                            probabilityInfo = new ProbabilityInfo(probabilityInfo.mProbability,
+                                    Integer.parseInt(historicalInfoParams[0]),
+                                    Integer.parseInt(historicalInfoParams[1]),
+                                    Integer.parseInt(historicalInfoParams[2]));
+                            break;
+                        case CombinedFormatUtils.NOT_A_WORD_TAG:
+                            isNotAWord = CombinedFormatUtils.isLiteralTrue(params[1]);
+                            break;
+                        case CombinedFormatUtils.POSSIBLY_OFFENSIVE_TAG:
+                            isPossiblyOffensive = CombinedFormatUtils.isLiteralTrue(params[1]);
+                            break;
                     }
                 }
             } else if (args[0].matches(CombinedFormatUtils.SHORTCUT_TAG + "=.*")) {
@@ -189,7 +200,8 @@
             }
         }
         if (null != word) {
-            dict.add(word, probabilityInfo, shortcuts.isEmpty() ? null : shortcuts, isNotAWord);
+            dict.add(word, probabilityInfo, shortcuts.isEmpty() ? null : shortcuts, isNotAWord,
+                    isPossiblyOffensive);
             for (WeightedString s : bigrams) {
                 dict.setBigram(word, s.mWord, s.mProbabilityInfo);
             }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java
index 0d93c7f..8fdf763 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java
@@ -18,7 +18,9 @@
 
 public class CommandList {
     public static void populate() {
+        // TODO: Move some commands to native code.
         Dicttool.addCommand("info", Info.class);
+        Dicttool.addCommand("header", Header.class);
         Dicttool.addCommand("diff", Diff.class);
         Dicttool.addCommand("compress", Compress.Compressor.class);
         Dicttool.addCommand("uncompress", Compress.Uncompressor.class);
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 3d0557b..6187853 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/DictionaryMaker.java
@@ -27,9 +27,6 @@
 import com.android.inputmethod.latin.makedict.Ver2DictEncoder;
 import com.android.inputmethod.latin.makedict.Ver4DictEncoder;
 
-import org.xml.sax.SAXException;
-
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -37,13 +34,10 @@
 import java.io.FileNotFoundException;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Arrays;
 import java.util.LinkedList;
 
-import javax.xml.parsers.ParserConfigurationException;
-
 /**
  * Main class/method for DictionaryMaker.
  */
@@ -53,59 +47,37 @@
         private static final String OPTION_VERSION_2 = "-2";
         private static final String OPTION_VERSION_4 = "-4";
         private static final String OPTION_INPUT_SOURCE = "-s";
-        private static final String OPTION_INPUT_BIGRAM_XML = "-b";
-        private static final String OPTION_INPUT_SHORTCUT_XML = "-c";
         private static final String OPTION_OUTPUT_BINARY = "-d";
-        private static final String OPTION_OUTPUT_XML = "-x";
         private static final String OPTION_OUTPUT_COMBINED = "-o";
         private static final String OPTION_HELP = "-h";
+        private static final String OPTION_CODE_POINT_TABLE = "-t";
+        private static final String OPTION_CODE_POINT_TABLE_OFF = "off";
+        private static final String OPTION_CODE_POINT_TABLE_ON = "on";
         public final String mInputBinary;
         public final String mInputCombined;
-        public final String mInputUnigramXml;
-        public final String mInputShortcutXml;
-        public final String mInputBigramXml;
         public final String mOutputBinary;
-        public final String mOutputXml;
         public final String mOutputCombined;
         public final int mOutputBinaryFormatVersion;
+        public final int mCodePointTableMode;
 
         private void checkIntegrity() throws IOException {
             checkHasExactlyOneInput();
             checkHasAtLeastOneOutput();
             checkNotSameFile(mInputBinary, mOutputBinary);
-            checkNotSameFile(mInputBinary, mOutputXml);
             checkNotSameFile(mInputCombined, mOutputBinary);
-            checkNotSameFile(mInputCombined, mOutputXml);
-            checkNotSameFile(mInputUnigramXml, mOutputBinary);
-            checkNotSameFile(mInputUnigramXml, mOutputXml);
-            checkNotSameFile(mInputUnigramXml, mOutputCombined);
-            checkNotSameFile(mInputShortcutXml, mOutputBinary);
-            checkNotSameFile(mInputShortcutXml, mOutputXml);
-            checkNotSameFile(mInputShortcutXml, mOutputCombined);
-            checkNotSameFile(mInputBigramXml, mOutputBinary);
-            checkNotSameFile(mInputBigramXml, mOutputXml);
-            checkNotSameFile(mInputBigramXml, mOutputCombined);
-            checkNotSameFile(mOutputBinary, mOutputXml);
             checkNotSameFile(mOutputBinary, mOutputCombined);
-            checkNotSameFile(mOutputXml, mOutputCombined);
         }
 
         private void checkHasExactlyOneInput() {
-            if (null == mInputUnigramXml && null == mInputBinary && null == mInputCombined) {
+            if (null == mInputBinary && null == mInputCombined) {
                 throw new RuntimeException("No input file specified");
-            } else if ((null != mInputUnigramXml && null != mInputBinary)
-                    || (null != mInputUnigramXml && null != mInputCombined)
-                    || (null != mInputBinary && null != mInputCombined)) {
+            } else if (null != mInputBinary && null != mInputCombined) {
                 throw new RuntimeException("Several input files specified");
-            } else if ((null != mInputBinary || null != mInputCombined)
-                    && (null != mInputBigramXml || null != mInputShortcutXml)) {
-                throw new RuntimeException("Separate bigrams/shortcut files are only supported"
-                        + " with XML input (other formats include bigrams and shortcuts already)");
             }
         }
 
         private void checkHasAtLeastOneOutput() {
-            if (null == mOutputBinary && null == mOutputXml && null == mOutputCombined) {
+            if (null == mOutputBinary && null == mOutputCombined) {
                 throw new RuntimeException("No output specified");
             }
         }
@@ -122,22 +94,20 @@
             }
         }
 
-        private void displayHelp() {
+        private static void displayHelp() {
             MakedictLog.i(getHelp());
         }
 
         public static String getHelp() {
             return "Usage: makedict "
-                    + "[-s <unigrams.xml> [-b <bigrams.xml>] [-c <shortcuts_and_whitelist.xml>] "
                     + "| [-s <combined format input]"
-                    + "| [-s <binary input>] [-d <binary output>] [-x <xml output>] "
-                    + " [-o <combined output>]"
+                    + "| [-s <binary input>] [-d <binary output>]"
+                    + " [-o <combined output>] [-t <code point table switch: on/off/auto>]"
                     + "[-2] [-3] [-4]\n"
                     + "\n"
                     + "  Converts a source dictionary file to one or several outputs.\n"
-                    + "  Source can be an XML file, with an optional XML bigrams file, or a\n"
-                    + "  binary dictionary file.\n"
-                    + "  Binary version 2 (Jelly Bean), 3, 4, XML and\n"
+                    + "  Source can be a binary dictionary file or a combined format file.\n"
+                    + "  Binary version 2 (Jelly Bean), 3, 4, and\n"
                     + "  combined format outputs are supported.";
         }
 
@@ -148,13 +118,11 @@
             }
             String inputBinary = null;
             String inputCombined = null;
-            String inputUnigramXml = null;
-            String inputShortcutXml = null;
-            String inputBigramXml = null;
             String outputBinary = null;
-            String outputXml = null;
             String outputCombined = null;
-            int outputBinaryFormatVersion = 2; // the default version is 2.
+            int outputBinaryFormatVersion = FormatSpec.VERSION202; // the default version is 202.
+            // Don't use code point table by default.
+            int codePointTableMode = Ver2DictEncoder.CODE_POINT_TABLE_OFF;
 
             while (!args.isEmpty()) {
                 final String arg = args.get(0);
@@ -172,41 +140,42 @@
                             throw new IllegalArgumentException("Option " + arg + " is unknown or "
                                     + "requires an argument");
                         }
-                        String filename = args.get(0);
+                        String argValue = args.get(0);
                         args.remove(0);
                         if (OPTION_INPUT_SOURCE.equals(arg)) {
-                            if (XmlDictInputOutput.isXmlUnigramDictionary(filename)) {
-                                inputUnigramXml = filename;
-                            } else if (CombinedInputOutput.isCombinedDictionary(filename)) {
-                                inputCombined = filename;
-                            } else if (BinaryDictDecoderUtils.isBinaryDictionary(filename)) {
-                                inputBinary = filename;
+                            if (CombinedInputOutput.isCombinedDictionary(argValue)) {
+                                inputCombined = argValue;
+                            } else if (BinaryDictDecoderUtils.isBinaryDictionary(argValue)) {
+                                inputBinary = argValue;
                             } else {
                                 throw new IllegalArgumentException(
-                                        "Unknown format for file " + filename);
+                                        "Unknown format for file " + argValue);
                             }
-                        } else if (OPTION_INPUT_SHORTCUT_XML.equals(arg)) {
-                            inputShortcutXml = filename;
-                        } else if (OPTION_INPUT_BIGRAM_XML.equals(arg)) {
-                            inputBigramXml = filename;
                         } else if (OPTION_OUTPUT_BINARY.equals(arg)) {
-                            outputBinary = filename;
-                        } else if (OPTION_OUTPUT_XML.equals(arg)) {
-                            outputXml = filename;
+                            outputBinary = argValue;
                         } else if (OPTION_OUTPUT_COMBINED.equals(arg)) {
-                            outputCombined = filename;
+                            outputCombined = argValue;
+                        } else if (OPTION_CODE_POINT_TABLE.equals(arg)) {
+                            if (OPTION_CODE_POINT_TABLE_OFF.equals(argValue)) {
+                                codePointTableMode = Ver2DictEncoder.CODE_POINT_TABLE_OFF;
+                            } else if (OPTION_CODE_POINT_TABLE_ON.equals(argValue)) {
+                                codePointTableMode = Ver2DictEncoder.CODE_POINT_TABLE_ON;
+                            } else {
+                                throw new IllegalArgumentException(
+                                        "Unknown argument to -t option : " + argValue);
+                            }
                         } else {
                             throw new IllegalArgumentException("Unknown option : " + arg);
                         }
                     }
                 } else {
-                    if (null == inputBinary && null == inputUnigramXml) {
+                    if (null == inputBinary) {
                         if (BinaryDictDecoderUtils.isBinaryDictionary(arg)) {
                             inputBinary = arg;
                         } else if (CombinedInputOutput.isCombinedDictionary(arg)) {
                             inputCombined = arg;
                         } else {
-                            inputUnigramXml = arg;
+                            throw new IllegalArgumentException("Unknown format for file " + arg);
                         }
                     } else if (null == outputBinary) {
                         outputBinary = arg;
@@ -218,20 +187,16 @@
 
             mInputBinary = inputBinary;
             mInputCombined = inputCombined;
-            mInputUnigramXml = inputUnigramXml;
-            mInputShortcutXml = inputShortcutXml;
-            mInputBigramXml = inputBigramXml;
             mOutputBinary = outputBinary;
-            mOutputXml = outputXml;
             mOutputCombined = outputCombined;
             mOutputBinaryFormatVersion = outputBinaryFormatVersion;
+            mCodePointTableMode = codePointTableMode;
             checkIntegrity();
         }
     }
 
     public static void main(String[] args)
-            throws FileNotFoundException, ParserConfigurationException, SAXException, IOException,
-            UnsupportedFormatException {
+            throws FileNotFoundException, IOException, UnsupportedFormatException {
         final Arguments parsedArgs = new Arguments(args);
         FusionDictionary dictionary = readInputFromParsedArgs(parsedArgs);
         writeOutputToParsedArgs(parsedArgs, dictionary);
@@ -244,14 +209,11 @@
      * @return the read dictionary.
      */
     private static FusionDictionary readInputFromParsedArgs(final Arguments args)
-            throws IOException, UnsupportedFormatException, ParserConfigurationException,
-            SAXException, FileNotFoundException {
+            throws IOException, UnsupportedFormatException, FileNotFoundException {
         if (null != args.mInputBinary) {
             return readBinaryFile(args.mInputBinary);
         } else if (null != args.mInputCombined) {
             return readCombinedFile(args.mInputCombined);
-        } else if (null != args.mInputUnigramXml) {
-            return readXmlFile(args.mInputUnigramXml, args.mInputShortcutXml, args.mInputBigramXml);
         } else {
             throw new RuntimeException("No input file specified");
         }
@@ -290,38 +252,6 @@
         }
     }
 
-    private static BufferedInputStream getBufferedFileInputStream(final String filename)
-            throws FileNotFoundException {
-        if (filename == null) {
-            return null;
-        }
-        return new BufferedInputStream(new FileInputStream(filename));
-    }
-
-    /**
-     * Read a dictionary from a unigram XML file, and optionally a bigram XML file.
-     *
-     * @param unigramXmlFilename the name of the unigram XML file. May not be null.
-     * @param shortcutXmlFilename the name of the shortcut/whitelist XML file, or null if none.
-     * @param bigramXmlFilename the name of the bigram XML file. Pass null if there are no bigrams.
-     * @return the read dictionary.
-     * @throws FileNotFoundException if one of the files can't be found
-     * @throws SAXException if one or more of the XML files is not well-formed
-     * @throws IOException if one the input files can't be read
-     * @throws ParserConfigurationException if the system can't create a SAX parser
-     */
-    private static FusionDictionary readXmlFile(final String unigramXmlFilename,
-            final String shortcutXmlFilename, final String bigramXmlFilename)
-            throws FileNotFoundException, SAXException, IOException, ParserConfigurationException {
-        try (
-            final BufferedInputStream unigrams = getBufferedFileInputStream(unigramXmlFilename);
-            final BufferedInputStream shortcuts = getBufferedFileInputStream(shortcutXmlFilename);
-            final BufferedInputStream bigrams = getBufferedFileInputStream(bigramXmlFilename);
-        ) {
-            return XmlDictInputOutput.readDictionaryXml(unigrams, shortcuts, bigrams);
-        }
-    }
-
     /**
      * Invoke the right output method according to args.
      *
@@ -335,10 +265,8 @@
             throws FileNotFoundException, IOException, UnsupportedFormatException,
             IllegalArgumentException {
         if (null != args.mOutputBinary) {
-            writeBinaryDictionary(args.mOutputBinary, dict, args.mOutputBinaryFormatVersion);
-        }
-        if (null != args.mOutputXml) {
-            writeXmlDictionary(args.mOutputXml, dict);
+            writeBinaryDictionary(args.mOutputBinary, dict, args.mOutputBinaryFormatVersion,
+                    args.mCodePointTableMode);
         }
         if (null != args.mOutputCombined) {
             writeCombinedDictionary(args.mOutputCombined, dict);
@@ -351,39 +279,26 @@
      * @param outputFilename the name of the file to write to.
      * @param dict the dictionary to write.
      * @param version the binary format version to use.
+     * @param codePointTableMode the value to decide how we treat the code point table.
      * @throws FileNotFoundException if the output file can't be created.
      * @throws IOException if the output file can't be written to.
      */
     private static void writeBinaryDictionary(final String outputFilename,
-            final FusionDictionary dict, final int version)
+            final FusionDictionary dict, final int version, final int codePointTableMode)
             throws FileNotFoundException, IOException, UnsupportedFormatException {
         final File outputFile = new File(outputFilename);
         final FormatSpec.FormatOptions formatOptions = new FormatSpec.FormatOptions(version);
         final DictEncoder dictEncoder;
         if (version == FormatSpec.VERSION4) {
+            // VERSION4 doesn't use the code point table.
             dictEncoder = new Ver4DictEncoder(outputFile);
         } else {
-            dictEncoder = new Ver2DictEncoder(outputFile);
+            dictEncoder = new Ver2DictEncoder(outputFile, codePointTableMode);
         }
         dictEncoder.writeDictionary(dict, formatOptions);
     }
 
     /**
-     * Write the dictionary in XML format to the specified filename.
-     *
-     * @param outputFilename the name of the file to write to.
-     * @param dict the dictionary to write.
-     * @throws FileNotFoundException if the output file can't be created.
-     * @throws IOException if the output file can't be written to.
-     */
-    private static void writeXmlDictionary(final String outputFilename,
-            final FusionDictionary dict) throws FileNotFoundException, IOException {
-        try (final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
-            XmlDictInputOutput.writeDictionaryXml(writer, dict);
-        }
-    }
-
-    /**
      * Write the dictionary in the combined format to the specified filename.
      *
      * @param outputFilename the name of the file to write to.
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
index 94d1ae8..f97fbef 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java
@@ -128,14 +128,14 @@
                             + word0Property.mIsNotAWord + " -> " + word1PtNode.getIsNotAWord());
                     hasDifferences = true;
                 }
-                if (word0Property.mIsBlacklistEntry != word1PtNode.getIsBlacklistEntry()) {
-                    System.out.println("Blacklist: " + word0Property.mWord + " "
-                            + word0Property.mIsBlacklistEntry + " -> "
-                            + word1PtNode.getIsBlacklistEntry());
+                if (word0Property.mIsPossiblyOffensive != word1PtNode.getIsPossiblyOffensive()) {
+                    System.out.println("Possibly-offensive: " + word0Property.mWord + " "
+                            + word0Property.mIsPossiblyOffensive + " -> "
+                            + word1PtNode.getIsPossiblyOffensive());
                     hasDifferences = true;
                 }
                 hasDifferences |= hasAttributesDifferencesAndPrintThemIfAny(word0Property.mWord,
-                        "Bigram", word0Property.mBigrams, word1PtNode.getBigrams());
+                        "Bigram", word0Property.getBigrams(), word1PtNode.getBigrams());
                 hasDifferences |= hasAttributesDifferencesAndPrintThemIfAny(word0Property.mWord,
                         "Shortcut", word0Property.mShortcutTargets,
                         word1PtNode.getShortcutTargets());
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Header.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Header.java
new file mode 100644
index 0000000..aa1762f
--- /dev/null
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Header.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2014 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.dicttool;
+
+import com.android.inputmethod.latin.dicttool.BinaryDictOffdeviceUtils.DecoderChainSpec;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
+
+import java.io.File;
+import java.util.Arrays;
+
+public class Header extends Dicttool.Command {
+    public static final String COMMAND = "header";
+
+    public Header() {
+    }
+
+    @Override
+    public String getHelp() {
+        return COMMAND + " <filename>: prints the header contents of a dictionary file";
+    }
+
+    @Override
+    public void run() throws UnsupportedFormatException {
+        final boolean plumbing;
+        if (mArgs.length > 0 && "-p".equals(mArgs[0])) {
+            plumbing = true;
+            mArgs = Arrays.copyOfRange(mArgs, 1, mArgs.length);
+        } else {
+            plumbing = false;
+        }
+        if (mArgs.length < 1) {
+            throw new RuntimeException("Not enough arguments for command " + COMMAND);
+        }
+        final String filename = mArgs[0];
+        final File dictFile = new File(filename);
+        final DecoderChainSpec<DictionaryHeader> spec =
+                BinaryDictOffdeviceUtils.decodeDictionaryForProcess(dictFile,
+                        new BinaryDictOffdeviceUtils.HeaderReaderProcessor());
+        if (null == spec) {
+            throw new UnsupportedFormatException(filename
+                    + " doesn't seem to be a valid version 2 dictionary file");
+        }
+
+        final DictionaryHeader header = spec.mResult;
+        System.out.println("Dictionary : " + dictFile.getAbsolutePath());
+        System.out.println("Size : " + dictFile.length() + " bytes");
+        System.out.println("Format : Binary dictionary format");
+        System.out.println("Format version : " + header.mFormatOptions.mVersion);
+        System.out.println("Packaging : " + spec.describeChain());
+        System.out.println("Header attributes :");
+        System.out.print(header.mDictionaryOptions.toString(2 /* indentCount */, plumbing));
+    }
+}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
index 9b2567f..b8a64e3 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Info.java
@@ -45,8 +45,8 @@
         int whitelistCount = 0;
         for (final WordProperty wordProperty : dict) {
             ++wordCount;
-            if (null != wordProperty.mBigrams) {
-                bigramCount += wordProperty.mBigrams.size();
+            if (wordProperty.mHasNgrams) {
+                bigramCount += wordProperty.mNgrams.size();
             }
             if (null != wordProperty.mShortcutTargets) {
                 shortcutCount += wordProperty.mShortcutTargets.size();
@@ -64,8 +64,7 @@
                 + " whitelist entries)");
     }
 
-    private static void showWordInfo(final FusionDictionary dict, final String word,
-            final boolean plumbing) {
+    private static void showWordInfo(final FusionDictionary dict, final String word) {
         final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
         if (null == ptNode) {
             System.out.println(word + " is not in the dictionary");
@@ -76,8 +75,8 @@
         if (ptNode.getIsNotAWord()) {
             System.out.println("  Is not a word");
         }
-        if (ptNode.getIsBlacklistEntry()) {
-            System.out.println("  Is a blacklist entry");
+        if (ptNode.getIsPossiblyOffensive()) {
+            System.out.println("  Is possibly offensive");
         }
         final ArrayList<WeightedString> shortcutTargets = ptNode.getShortcutTargets();
         if (null == shortcutTargets || shortcutTargets.isEmpty()) {
@@ -124,7 +123,7 @@
             showInfo(dict, plumbing);
         } else {
             for (int i = 1; i < mArgs.length; ++i) {
-                showWordInfo(dict, mArgs[i], plumbing);
+                showWordInfo(dict, mArgs[i]);
             }
         }
     }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Makedict.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Makedict.java
index 808e1d4..0b1fb88 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Makedict.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Makedict.java
@@ -20,8 +20,6 @@
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.SAXException;
 
 public class Makedict extends Dicttool.Command {
     public static final String COMMAND = "makedict";
@@ -35,8 +33,7 @@
     }
 
     @Override
-    public void run() throws FileNotFoundException, IOException, ParserConfigurationException,
-            SAXException, UnsupportedFormatException {
+    public void run() throws FileNotFoundException, IOException, UnsupportedFormatException {
         DictionaryMaker.main(mArgs);
     }
 }
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
index 1f67982..3efa10a 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Package.java
@@ -16,10 +16,10 @@
 
 package com.android.inputmethod.latin.dicttool;
 
-import java.io.BufferedInputStream;
+import com.android.inputmethod.latin.makedict.DictionaryHeader;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -79,16 +79,16 @@
             if (mArgs.length != 2) {
                 throw new RuntimeException("Too many/too few arguments for command " + COMMAND);
             }
-            final BinaryDictOffdeviceUtils.DecoderChainSpec decodedSpec =
-                    BinaryDictOffdeviceUtils.getRawDictionaryOrNull(new File(mArgs[0]));
+            final BinaryDictOffdeviceUtils.DecoderChainSpec<DictionaryHeader> decodedSpec =
+                    BinaryDictOffdeviceUtils.decodeDictionaryForProcess(new File(mArgs[0]),
+                            new BinaryDictOffdeviceUtils.HeaderReaderProcessor());
             if (null == decodedSpec) {
                 System.out.println(mArgs[0] + " does not seem to be a dictionary");
                 return;
             }
             System.out.println("Packaging : " + decodedSpec.describeChain());
-            System.out.println("Uncompressed size : " + decodedSpec.mFile.length());
             try (
-                final InputStream input = getFileInputStream(decodedSpec.mFile);
+                final InputStream input = decodedSpec.getStream(new File(mArgs[0]));
                 final OutputStream output = new BufferedOutputStream(
                         getFileOutputStreamOrStdOut(mArgs[1]))
             ) {
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
index b6383d7..e2dd519 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
@@ -16,10 +16,10 @@
 
 package com.android.inputmethod.latin.dicttool;
 
+import com.android.inputmethod.latin.common.FileUtils;
 import com.android.inputmethod.latin.makedict.BinaryDictDecoderEncoderTests;
 import com.android.inputmethod.latin.makedict.BinaryDictEncoderFlattenTreeTests;
 import com.android.inputmethod.latin.makedict.FusionDictionaryTest;
-import com.android.inputmethod.latin.utils.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
deleted file mode 100644
index bdec447..0000000
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/XmlDictInputOutput.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2011 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.dicttool;
-
-import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
-import com.android.inputmethod.latin.makedict.FusionDictionary;
-import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
-import com.android.inputmethod.latin.makedict.ProbabilityInfo;
-import com.android.inputmethod.latin.makedict.WeightedString;
-import com.android.inputmethod.latin.makedict.WordProperty;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.TreeSet;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-/**
- * Reads and writes XML files for a FusionDictionary.
- *
- * All functions in this class are static.
- */
-public class XmlDictInputOutput {
-
-    private static final String ROOT_TAG = "wordlist";
-    private static final String WORD_TAG = "w";
-    private static final String BIGRAM_TAG = "bigram";
-    private static final String SHORTCUT_TAG = "shortcut";
-    private static final String PROBABILITY_ATTR = "f";
-    private static final String WORD_ATTR = "word";
-    private static final String NOT_A_WORD_ATTR = "not_a_word";
-
-    /**
-     * SAX handler for a unigram XML file.
-     */
-    static private class UnigramHandler extends DefaultHandler {
-        // Parser states
-        private static final int START = 1;
-        private static final int WORD = 2;
-        private static final int UNKNOWN = 3;
-        private static final int SHORTCUT_ONLY_WORD_PROBABILITY = 1;
-
-        FusionDictionary mDictionary;
-        int mState; // the state of the parser
-        int mFreq; // the currently read freq
-        String mWord; // the current word
-        final HashMap<String, ArrayList<WeightedString>> mShortcutsMap;
-
-        /**
-         * Create the handler.
-         *
-         * @param shortcuts the shortcuts as a map. This may be empty, but may not be null.
-         */
-        public UnigramHandler(final HashMap<String, ArrayList<WeightedString>> shortcuts) {
-            mDictionary = null;
-            mShortcutsMap = shortcuts;
-            mWord = "";
-            mState = START;
-            mFreq = 0;
-        }
-
-        public FusionDictionary getFinalDictionary() {
-            final FusionDictionary dict = mDictionary;
-            for (final String shortcutOnly : mShortcutsMap.keySet()) {
-                if (dict.hasWord(shortcutOnly)) continue;
-                dict.add(shortcutOnly, new ProbabilityInfo(SHORTCUT_ONLY_WORD_PROBABILITY),
-                        mShortcutsMap.get(shortcutOnly), true /* isNotAWord */);
-            }
-            mDictionary = null;
-            mShortcutsMap.clear();
-            mWord = "";
-            mState = START;
-            mFreq = 0;
-            return dict;
-        }
-
-        @Override
-        public void startElement(String uri, String localName, String qName, Attributes attrs) {
-            if (WORD_TAG.equals(localName)) {
-                mState = WORD;
-                mWord = "";
-                for (int attrIndex = 0; attrIndex < attrs.getLength(); ++attrIndex) {
-                    final String attrName = attrs.getLocalName(attrIndex);
-                    if (PROBABILITY_ATTR.equals(attrName)) {
-                        mFreq = Integer.parseInt(attrs.getValue(attrIndex));
-                    }
-                }
-            } else if (ROOT_TAG.equals(localName)) {
-                final HashMap<String, String> attributes = new HashMap<>();
-                for (int attrIndex = 0; attrIndex < attrs.getLength(); ++attrIndex) {
-                    final String attrName = attrs.getLocalName(attrIndex);
-                    attributes.put(attrName, attrs.getValue(attrIndex));
-                }
-                mDictionary = new FusionDictionary(new PtNodeArray(),
-                        new DictionaryOptions(attributes));
-            } else {
-                mState = UNKNOWN;
-            }
-        }
-
-        @Override
-        public void characters(char[] ch, int start, int length) {
-            if (WORD == mState) {
-                // The XML parser is free to return text in arbitrary chunks one after the
-                // other. In particular, this happens in some implementations when it finds
-                // an escape code like "&amp;".
-                mWord += String.copyValueOf(ch, start, length);
-            }
-        }
-
-        @Override
-        public void endElement(String uri, String localName, String qName) {
-            if (WORD == mState) {
-                mDictionary.add(mWord, new ProbabilityInfo(mFreq), mShortcutsMap.get(mWord),
-                        false /* isNotAWord */);
-                mState = START;
-            }
-        }
-    }
-
-    static private class AssociativeListHandler extends DefaultHandler {
-        private final String SRC_TAG;
-        private final String SRC_ATTRIBUTE;
-        private final String DST_TAG;
-        private final String DST_ATTRIBUTE;
-        private final String DST_FREQ;
-
-        // In this version of the XML file, the bigram frequency is given as an int 0..XML_MAX
-        private final static int XML_MAX = 256;
-        // In memory and in the binary dictionary the bigram frequency is 0..MEMORY_MAX
-        private final static int MEMORY_MAX = 256;
-        private final static int XML_TO_MEMORY_RATIO = XML_MAX / MEMORY_MAX;
-
-        private String mSrc;
-        private final HashMap<String, ArrayList<WeightedString>> mAssocMap;
-
-        public AssociativeListHandler(final String srcTag, final String srcAttribute,
-                final String dstTag, final String dstAttribute, final String dstFreq) {
-            SRC_TAG = srcTag;
-            SRC_ATTRIBUTE = srcAttribute;
-            DST_TAG = dstTag;
-            DST_ATTRIBUTE = dstAttribute;
-            DST_FREQ = dstFreq;
-            mSrc = null;
-            mAssocMap = new HashMap<>();
-        }
-
-        @Override
-        public void startElement(String uri, String localName, String qName, Attributes attrs) {
-            if (SRC_TAG.equals(localName)) {
-                mSrc = attrs.getValue(uri, SRC_ATTRIBUTE);
-            } else if (DST_TAG.equals(localName)) {
-                String dst = attrs.getValue(uri, DST_ATTRIBUTE);
-                int freq = getValueFromFreqString(attrs.getValue(uri, DST_FREQ));
-                WeightedString bigram = new WeightedString(dst, freq / XML_TO_MEMORY_RATIO);
-                ArrayList<WeightedString> bigramList = mAssocMap.get(mSrc);
-                if (null == bigramList) bigramList = new ArrayList<>();
-                bigramList.add(bigram);
-                mAssocMap.put(mSrc, bigramList);
-            }
-        }
-
-        protected int getValueFromFreqString(final String freqString) {
-            return Integer.parseInt(freqString);
-        }
-
-        // This may return an empty map, but will never return null.
-        public HashMap<String, ArrayList<WeightedString>> getAssocMap() {
-            return mAssocMap;
-        }
-    }
-
-    /**
-     * SAX handler for a bigram XML file.
-     */
-    static private class BigramHandler extends AssociativeListHandler {
-        private final static String BIGRAM_W1_TAG = "bi";
-        private final static String BIGRAM_W2_TAG = "w";
-        private final static String BIGRAM_W1_ATTRIBUTE = "w1";
-        private final static String BIGRAM_W2_ATTRIBUTE = "w2";
-        private final static String BIGRAM_FREQ_ATTRIBUTE = "p";
-
-        public BigramHandler() {
-            super(BIGRAM_W1_TAG, BIGRAM_W1_ATTRIBUTE, BIGRAM_W2_TAG, BIGRAM_W2_ATTRIBUTE,
-                    BIGRAM_FREQ_ATTRIBUTE);
-        }
-
-        // As per getAssocMap(), this never returns null.
-        public HashMap<String, ArrayList<WeightedString>> getBigramMap() {
-            return getAssocMap();
-        }
-    }
-
-    /**
-     * SAX handler for a shortcut & whitelist XML file.
-     */
-    static private class ShortcutAndWhitelistHandler extends AssociativeListHandler {
-        private final static String ENTRY_TAG = "entry";
-        private final static String ENTRY_ATTRIBUTE = "shortcut";
-        private final static String TARGET_TAG = "target";
-        private final static String REPLACEMENT_ATTRIBUTE = "replacement";
-        private final static String TARGET_PRIORITY_ATTRIBUTE = "priority";
-        private final static String WHITELIST_MARKER = "whitelist";
-        private final static int WHITELIST_FREQ_VALUE = 15;
-        private final static int MIN_FREQ = 0;
-        private final static int MAX_FREQ = 14;
-
-        public ShortcutAndWhitelistHandler() {
-            super(ENTRY_TAG, ENTRY_ATTRIBUTE, TARGET_TAG, REPLACEMENT_ATTRIBUTE,
-                    TARGET_PRIORITY_ATTRIBUTE);
-        }
-
-        @Override
-        protected int getValueFromFreqString(final String freqString) {
-            if (WHITELIST_MARKER.equals(freqString)) {
-                return WHITELIST_FREQ_VALUE;
-            }
-            final int intValue = super.getValueFromFreqString(freqString);
-            if (intValue < MIN_FREQ || intValue > MAX_FREQ) {
-                throw new RuntimeException("Shortcut freq out of range. Accepted range is "
-                        + MIN_FREQ + ".." + MAX_FREQ);
-            }
-            return intValue;
-        }
-
-        // As per getAssocMap(), this never returns null.
-        public HashMap<String, ArrayList<WeightedString>> getShortcutAndWhitelistMap() {
-            return getAssocMap();
-        }
-    }
-
-    /**
-     * Basic test to find out whether the file is in the unigram XML format or not.
-     *
-     * Concretely this only tests the header line.
-     *
-     * @param filename The name of the file to test.
-     * @return true if the file is in the unigram XML format, false otherwise
-     */
-    public static boolean isXmlUnigramDictionary(final String filename) {
-        try (final BufferedReader reader = new BufferedReader(
-                new InputStreamReader(new FileInputStream(filename), "UTF-8"))) {
-            final String firstLine = reader.readLine();
-            return firstLine.matches("^\\s*<wordlist .*>\\s*$");
-        } catch (final IOException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Reads a dictionary from an XML file.
-     *
-     * This is the public method that will parse an XML file and return the corresponding memory
-     * representation.
-     *
-     * @param unigrams the file to read the data from.
-     * @param shortcuts the file to read the shortcuts & whitelist from, or null.
-     * @param bigrams the file to read the bigrams from, or null.
-     * @return the in-memory representation of the dictionary.
-     */
-    public static FusionDictionary readDictionaryXml(final BufferedInputStream unigrams,
-            final BufferedInputStream shortcuts, final BufferedInputStream bigrams)
-            throws SAXException, IOException, ParserConfigurationException {
-        final SAXParserFactory factory = SAXParserFactory.newInstance();
-        factory.setNamespaceAware(true);
-        final SAXParser parser = factory.newSAXParser();
-        final BigramHandler bigramHandler = new BigramHandler();
-        if (null != bigrams) parser.parse(bigrams, bigramHandler);
-
-        final ShortcutAndWhitelistHandler shortcutAndWhitelistHandler =
-                new ShortcutAndWhitelistHandler();
-        if (null != shortcuts) parser.parse(shortcuts, shortcutAndWhitelistHandler);
-
-        final UnigramHandler unigramHandler =
-                new UnigramHandler(shortcutAndWhitelistHandler.getShortcutAndWhitelistMap());
-        parser.parse(unigrams, unigramHandler);
-        final FusionDictionary dict = unigramHandler.getFinalDictionary();
-        final HashMap<String, ArrayList<WeightedString>> bigramMap = bigramHandler.getBigramMap();
-        for (final String firstWord : bigramMap.keySet()) {
-            if (!dict.hasWord(firstWord)) continue;
-            final ArrayList<WeightedString> bigramList = bigramMap.get(firstWord);
-            for (final WeightedString bigram : bigramList) {
-                if (!dict.hasWord(bigram.mWord)) continue;
-                dict.setBigram(firstWord, bigram.mWord, bigram.mProbabilityInfo);
-            }
-        }
-        return dict;
-    }
-
-    /**
-     * Reads a dictionary in the first, legacy XML format
-     *
-     * This method reads data from the parser and creates a new FusionDictionary with it.
-     * The format parsed by this method is the format used before Ice Cream Sandwich,
-     * which has no support for bigrams or shortcuts/whitelist.
-     * It is important to note that this method expects the parser to have already eaten
-     * the first, all-encompassing tag.
-     *
-     * @param xpp the parser to read the data from.
-     * @return the parsed dictionary.
-     */
-
-    /**
-     * Writes a dictionary to an XML file.
-     *
-     * The output format is the "second" format, which supports bigrams and shortcuts/whitelist.
-     *
-     * @param destination a destination stream to write to.
-     * @param dict the dictionary to write.
-     */
-    public static void writeDictionaryXml(final BufferedWriter destination,
-            final FusionDictionary dict) throws IOException {
-        final TreeSet<WordProperty> wordPropertiesInDict = new TreeSet<>();
-        for (WordProperty wordProperty : dict) {
-            wordPropertiesInDict.add(wordProperty);
-        }
-        // TODO: use an XMLSerializer if this gets big
-        destination.write("<wordlist format=\"2\"");
-        for (final String key : dict.mOptions.mAttributes.keySet()) {
-            final String value = dict.mOptions.mAttributes.get(key);
-            destination.write(" " + key + "=\"" + value + "\"");
-        }
-        destination.write(">\n");
-        destination.write("<!-- Warning: there is no code to read this format yet. -->\n");
-        for (WordProperty wordProperty : wordPropertiesInDict) {
-            destination.write("  <" + WORD_TAG + " " + WORD_ATTR + "=\"" + wordProperty.mWord
-                    + "\" " + PROBABILITY_ATTR + "=\"" + wordProperty.getProbability()
-                    + (wordProperty.mIsNotAWord ? "\" " + NOT_A_WORD_ATTR + "=\"true" : "")
-                    + "\">");
-            if (null != wordProperty.mShortcutTargets) {
-                destination.write("\n");
-                for (WeightedString target : wordProperty.mShortcutTargets) {
-                    destination.write("    <" + SHORTCUT_TAG + " " + PROBABILITY_ATTR + "=\""
-                            + target.getProbability() + "\">" + target.mWord + "</" + SHORTCUT_TAG
-                            + ">\n");
-                }
-                destination.write("  ");
-            }
-            if (null != wordProperty.mBigrams) {
-                destination.write("\n");
-                for (WeightedString bigram : wordProperty.mBigrams) {
-                    destination.write("    <" + BIGRAM_TAG + " " + PROBABILITY_ATTR + "=\""
-                            + bigram.getProbability() + "\">" + bigram.mWord
-                            + "</" + BIGRAM_TAG + ">\n");
-                }
-                destination.write("  ");
-            }
-            destination.write("</" + WORD_TAG + ">\n");
-        }
-        destination.write("</wordlist>\n");
-        destination.close();
-    }
-}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index a4ad6b5..dcc4e19 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.personalization;
 
+@SuppressWarnings("unused")
 public class PersonalizationHelper {
     public static void currentTimeChangedForTesting(final int currentTimestamp) {
     }
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
index 0236a44..e68aeb0 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/dicttool/BinaryDictOffdeviceUtilsTests.java
@@ -16,10 +16,17 @@
 
 package com.android.inputmethod.latin.dicttool;
 
+import com.android.inputmethod.latin.common.CodePointUtils;
+import com.android.inputmethod.latin.dicttool.BinaryDictOffdeviceUtils;
+import com.android.inputmethod.latin.dicttool.Compress;
+import com.android.inputmethod.latin.dicttool.Crypt;
+import com.android.inputmethod.latin.dicttool.BinaryDictOffdeviceUtils.DecoderChainSpec;
 import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
+import com.android.inputmethod.latin.makedict.BinaryDictUtils;
 import com.android.inputmethod.latin.makedict.DictDecoder;
 import com.android.inputmethod.latin.makedict.DictEncoder;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
+import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 import com.android.inputmethod.latin.makedict.FusionDictionary;
@@ -35,13 +42,37 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
 
 /**
  * Unit tests for BinaryDictOffdeviceUtils
  */
 public class BinaryDictOffdeviceUtilsTests extends TestCase {
     private static final int TEST_FREQ = 37; // Some arbitrary value unlikely to happen by chance
+    private static final int CODE_POINT_SET_SIZE = 300;
+    final Random mRandom;
+    private static final ArrayList<String> sWords = new ArrayList<>();
+
+    public BinaryDictOffdeviceUtilsTests(final long seed, final int maxUnigrams) {
+        super();
+        mRandom = new Random(seed);
+        sWords.clear();
+        generateWords(maxUnigrams, mRandom);
+    }
+
+    private static void generateWords(final int maxUnigrams, final Random random) {
+        final int[] codePointSet = CodePointUtils.generateCodePointSet(
+                CODE_POINT_SET_SIZE, random);
+        final Set<String> wordSet = new HashSet<>();
+        while (wordSet.size() < maxUnigrams) {
+            wordSet.add(CodePointUtils.generateWord(random, codePointSet));
+        }
+        sWords.addAll(wordSet);
+    }
 
     public void testGetRawDictWorks() throws IOException, UnsupportedFormatException {
         final String VERSION = "1";
@@ -54,31 +85,31 @@
         testOptions.mAttributes.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, LOCALE);
         testOptions.mAttributes.put(DictionaryHeader.DICTIONARY_ID_KEY, ID);
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(), testOptions);
-        dict.add("foo", new ProbabilityInfo(TEST_FREQ), null, false /* isNotAWord */);
-        dict.add("fta", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("ftb", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("bar", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("fool", new ProbabilityInfo(1), null, false /* isNotAWord */);
+        dict.add("foo", new ProbabilityInfo(TEST_FREQ), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("fta", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("ftb", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("bar", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("fool", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
 
         final File dst = File.createTempFile("testGetRawDict", ".tmp");
         dst.deleteOnExit();
         try (final OutputStream out = Compress.getCompressedStream(
-                Compress.getCompressedStream(
-                        Compress.getCompressedStream(
-                                new BufferedOutputStream(new FileOutputStream(dst)))))) {
+                new BufferedOutputStream(new FileOutputStream(dst)))) {
             final DictEncoder dictEncoder = new Ver2DictEncoder(out);
-            dictEncoder.writeDictionary(dict, new FormatOptions(2, false));
+            dictEncoder.writeDictionary(dict, new FormatOptions(FormatSpec.VERSION202, false));
         }
 
         // Test for an actually compressed dictionary and its contents
-        final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec =
+        final BinaryDictOffdeviceUtils.DecoderChainSpec<File> decodeSpec =
                 BinaryDictOffdeviceUtils.getRawDictionaryOrNull(dst);
-        for (final String step : decodeSpec.mDecoderSpec) {
-            assertEquals("Wrong decode spec", BinaryDictOffdeviceUtils.COMPRESSION, step);
-        }
-        assertEquals("Wrong decode spec", 3, decodeSpec.mDecoderSpec.size());
-        final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(decodeSpec.mFile, 0,
-                decodeSpec.mFile.length());
+        assertEquals("Wrong decode spec", "raw > compression", decodeSpec.describeChain());
+        final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(decodeSpec.mResult, 0,
+                decodeSpec.mResult.length());
         final FusionDictionary resultDict =
                 dictDecoder.readDictionaryBinary(false /* deleteDictIfBroken */);
         assertEquals("Wrong version attribute", VERSION, resultDict.mOptions.mAttributes.get(
@@ -119,4 +150,63 @@
         assertNull("Wrongly identified data file",
                 BinaryDictOffdeviceUtils.getRawDictionaryOrNull(gzDst));
     }
+
+    public void runTestHeaderReaderProcessorWithOneSpec(final boolean compress, final boolean crypt)
+            throws IOException, UnsupportedFormatException {
+        final String dictName = "testHeaderReaderProcessor";
+        final FormatOptions formatOptions = BinaryDictUtils.STATIC_OPTIONS;
+        final int MAX_NUMBER_OF_OPTIONS_TO_ADD = 5;
+        final HashMap<String, String> options = new HashMap<>();
+        // Required attributes
+        options.put("dictionary", "main:en_US");
+        options.put("locale", "en_US");
+        options.put("version", Integer.toString(mRandom.nextInt()));
+        // Add some random options for test
+        final int numberOfOptionsToAdd = mRandom.nextInt() % (MAX_NUMBER_OF_OPTIONS_TO_ADD + 1);
+        for (int i = 0; i < numberOfOptionsToAdd; ++i) {
+            options.put(sWords.get(2 * i), sWords.get(2 * 1 + 1));
+        }
+        final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
+                new DictionaryOptions(options));
+
+        for (int i = 0; i < sWords.size(); ++i) {
+            final String word = sWords.get(i);
+            dict.add(word, new ProbabilityInfo(TEST_FREQ), null /* shortcuts */,
+                    false /* isNotAWord */, false /* isPossiblyOffensive */);
+        }
+
+        File file = File.createTempFile(dictName, ".tmp");
+        final DictEncoder dictEncoder = BinaryDictUtils.getDictEncoder(file, formatOptions);
+        dictEncoder.writeDictionary(dict, formatOptions);
+
+        if (compress) {
+            final File rawFile = file;
+            file = File.createTempFile(dictName + ".compress", ".tmp");
+            final Compress.Compressor compressCommand = new Compress.Compressor();
+            compressCommand.setArgs(new String[] { rawFile.getPath(), file.getPath() });
+            compressCommand.run();
+        }
+        if (crypt) {
+            final File rawFile = file;
+            file = File.createTempFile(dictName + ".crypt", ".tmp");
+            final Crypt.Encrypter cryptCommand = new Crypt.Encrypter();
+            cryptCommand.setArgs(new String[] { rawFile.getPath(), file.getPath() });
+            cryptCommand.run();
+        }
+
+        final DecoderChainSpec<DictionaryHeader> spec =
+                BinaryDictOffdeviceUtils.decodeDictionaryForProcess(file,
+                        new BinaryDictOffdeviceUtils.HeaderReaderProcessor());
+        assertNotNull("Can't decode a dictionary we just wrote : " + file, spec);
+        final DictionaryHeader header = spec.mResult;
+        assertEquals("raw" + (crypt ? " > encryption" : "") + (compress ? " > compression" : ""),
+                spec.describeChain());
+        assertEquals(header.mDictionaryOptions.mAttributes, options);
+    }
+
+    public void testHeaderReaderProcessor() throws IOException, UnsupportedFormatException {
+        runTestHeaderReaderProcessorWithOneSpec(false /* compress */, false /* crypt */);
+        runTestHeaderReaderProcessorWithOneSpec(true /* compress */, false /* crypt */);
+        runTestHeaderReaderProcessorWithOneSpec(true /* compress */, true /* crypt */);
+    }
 }
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictEncoderFlattenTreeTests.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictEncoderFlattenTreeTests.java
index aa228e7..dc9981d 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictEncoderFlattenTreeTests.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/BinaryDictEncoderFlattenTreeTests.java
@@ -33,11 +33,16 @@
     public void testFlattenNodes() {
         final FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
                 new DictionaryOptions(new HashMap<String, String>()));
-        dict.add("foo", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("fta", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("ftb", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("bar", new ProbabilityInfo(1), null, false /* isNotAWord */);
-        dict.add("fool", new ProbabilityInfo(1), null, false /* isNotAWord */);
+        dict.add("foo", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("fta", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("ftb", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("bar", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
+        dict.add("fool", new ProbabilityInfo(1), null, false /* isNotAWord */,
+                false /* isPossiblyOffensive */);
         final ArrayList<PtNodeArray> result =
                 BinaryDictEncoderUtils.flattenTree(dict.mRootNodeArray);
         assertEquals(4, result.size());
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
index 71f8ac8..1a4f096 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
@@ -67,17 +67,18 @@
         }
     }
 
-    private void checkDictionary(final FusionDictionary dict, final ArrayList<String> words,
-            int limit) {
+    private static void checkDictionary(final FusionDictionary dict, final ArrayList<String> words,
+            final int limit) {
         assertNotNull(dict);
+        int count = limit;
         for (final String word : words) {
-            if (--limit < 0) return;
+            if (--count < 0) return;
             final PtNode ptNode = FusionDictionary.findWordInTree(dict.mRootNodeArray, word);
             assertNotNull(ptNode);
         }
     }
 
-    private String dumpWord(final String word) {
+    private static String dumpWord(final String word) {
         final StringBuilder sb = new StringBuilder("");
         for (int i = 0; i < word.length(); i = word.offsetByCodePoints(i, 1)) {
             sb.append(word.codePointAt(i));
@@ -86,7 +87,7 @@
         return sb.toString();
     }
 
-    private void dumpDict(final FusionDictionary dict) {
+    private static void dumpDict(final FusionDictionary dict) {
         for (WordProperty wordProperty : dict) {
             System.out.println("Word " + dumpWord(wordProperty.mWord));
         }
@@ -101,7 +102,8 @@
         prepare(time);
         for (int i = 0; i < sWords.size(); ++i) {
             System.out.println("Adding in pos " + i + " : " + dumpWord(sWords.get(i)));
-            dict.add(sWords.get(i), new ProbabilityInfo(180), null, false);
+            dict.add(sWords.get(i), new ProbabilityInfo(180), null, false,
+                    false /* isPossiblyOffensive */);
             dumpDict(dict);
             checkDictionary(dict, sWords, i);
         }
diff --git a/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
index 54aa570..52fe565 100644
--- a/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-az-rAZ/donottranslate-more-keys.xml
@@ -18,10 +18,14 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX -->
-    <string name="morekeys_a">&#x00E2;</string>
-    <!-- U+0259: "ə" LATIN SMALL LETTER SCHWA -->
-    <string name="morekeys_e">&#x0259;</string>
+    <!-- This is the same as Turkish -->
+    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE -->
+    <string name="morekeys_a">&#x00E2;,&#x00E4;,&#x00E1;</string>
+    <!-- U+0259: "ə" LATIN SMALL LETTER SCHWA
+         U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+    <string name="morekeys_e">&#x0259;,&#x00E9;</string>
     <!-- U+0131: "ı" LATIN SMALL LETTER DOTLESS I
          U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
          U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -52,8 +56,15 @@
     <string name="morekeys_s">&#x015F;,&#x00DF;,&#x015B;,&#x0161;</string>
     <!-- U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
     <string name="morekeys_g">&#x011F;</string>
+    <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+         U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+    <string name="morekeys_n">&#x0148;,&#x00F1;</string>
     <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
          U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
     <string name="morekeys_c">&#x00E7;,&#x0107;,&#x010D;</string>
+    <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE -->
+    <string name="morekeys_y">&#x00FD;</string>
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <string name="morekeys_z">&#x017E;</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml
new file mode 100644
index 0000000..4955cd4
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-bn-rBD/donottranslate-more-keys.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Label for "switch to alphabetic" key.
+         U+0995: "क" BENGALI LETTER KA
+         U+0996: "ख" BENGALI LETTER KHA
+         U+0997: "ग" BENGALI LETTER GA -->
+    <string name="keylabel_to_alpha">&#x0995;&#x0996;&#x0997;</string>
+    <!-- U+09F3: "৳" BENGALI RUPEE SIGN -->
+    <string name="keyspec_currency">&#x09F3;</string>
+</resources>
diff --git a/tools/make-keyboard-text/res/values-da/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-da/donottranslate-more-keys.xml
index c22e262..98abb05 100644
--- a/tools/make-keyboard-text/res/values-da/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-da/donottranslate-more-keys.xml
@@ -18,26 +18,30 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+    <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+         U+00E6: "æ" LATIN SMALL LETTER AE
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
          U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
          U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
          U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
-    <string name="morekeys_a">&#x00E1;,&#x00E4;,&#x00E0;,&#x00E2;,&#x00E3;,&#x0101;</string>
+    <string name="morekeys_a">&#x00E5;,&#x00E6;,&#x00E1;,&#x00E4;,&#x00E0;,&#x00E2;,&#x00E3;,&#x0101;</string>
     <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
          U+00EB: "ë" LATIN SMALL LETTER E WITH DIAERESIS -->
     <string name="morekeys_e">&#x00E9;,&#x00EB;</string>
     <!-- U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
          U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS -->
     <string name="morekeys_i">&#x00ED;,&#x00EF;</string>
-    <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+    <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
          U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
          U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
          U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
          U+0153: "œ" LATIN SMALL LIGATURE OE
          U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
-    <string name="morekeys_o">&#x00F3;,&#x00F4;,&#x00F2;,&#x00F5;,&#x0153;,&#x014D;</string>
+    <string name="morekeys_o">&#x00F8;,&#x00F6;,&#x00F3;,&#x00F4;,&#x00F2;,&#x00F5;,&#x0153;,&#x014D;</string>
     <!-- U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
          U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
          U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
diff --git a/tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml
index 9a8fa3c..79266e8 100644
--- a/tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-et-rEE/donottranslate-more-keys.xml
@@ -72,7 +72,6 @@
          U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
          U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE -->
     <string name="morekeys_n">&#x0146;,&#x00F1;,&#x0144;</string>
-
     <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON
          U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
diff --git a/tools/make-keyboard-text/res/values-fi/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-fi/donottranslate-more-keys.xml
index 82b8472..b06d9e4 100644
--- a/tools/make-keyboard-text/res/values-fi/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-fi/donottranslate-more-keys.xml
@@ -18,21 +18,24 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E6: "æ" LATIN SMALL LETTER AE
+    <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+         U+00E6: "æ" LATIN SMALL LETTER AE
          U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
          U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
          U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
-    <string name="morekeys_a">&#x00E6;,&#x00E0;,&#x00E1;,&#x00E2;,&#x00E3;,&#x0101;</string>
-    <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+    <string name="morekeys_a">&#x00E4;,&#x00E5;,&#x00E6;,&#x00E0;,&#x00E1;,&#x00E2;,&#x00E3;,&#x0101;</string>
+    <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
          U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
          U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
          U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
          U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
          U+0153: "œ" LATIN SMALL LIGATURE OE
          U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
-    <string name="morekeys_o">&#x00F8;,&#x00F4;,&#x00F2;,&#x00F3;,&#x00F5;,&#x0153;,&#x014D;</string>
+    <string name="morekeys_o">&#x00F6;,&#x00F8;,&#x00F4;,&#x00F2;,&#x00F3;,&#x00F5;,&#x0153;,&#x014D;</string>
     <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS -->
     <string name="morekeys_u">&#x00FC;</string>
     <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON
diff --git a/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml
new file mode 100644
index 0000000..50834e0
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-hi-rZZ/donottranslate-more-keys.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- U+20B9: "₹" INDIAN RUPEE SIGN -->
+    <string name="keyspec_currency">&#x20B9;</string>
+    <string name="label_go_key">Go</string>
+    <string name="label_send_key">Send</string>
+    <string name="label_next_key">Next</string>
+    <string name="label_done_key">Done</string>
+    <string name="label_search_key">Search</string>
+    <string name="label_previous_key">Prev</string>
+    <string name="label_pause_key">Pause</string>
+    <string name="label_wait_key">Wait</string>
+</resources>
diff --git a/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
index 55723cd..2a37d8b 100644
--- a/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-hi/donottranslate-more-keys.xml
@@ -57,4 +57,9 @@
     <string name="additional_morekeys_symbols_0">0</string>
     <!-- U+20B9: "₹" INDIAN RUPEE SIGN -->
     <string name="keyspec_currency">&#x20B9;</string>
+    <!-- U+0964: "।" DEVANAGARI DANDA -->
+    <string name="keyspec_period">&#x0964;</string>
+    <string name="keyspec_tablet_period">&#x0964;</string>
+    <string name="morekeys_period">"!autoColumnOrder!9,\\,,.,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&amp;"</string>
+    <string name="morekeys_tablet_period">"!autoColumnOrder!8,\\,,.,',#,),(,/,;,@,:,-,\",+,\\%,&amp;"</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-nb/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-nb/donottranslate-more-keys.xml
index c5307a9..37f9f8a 100644
--- a/tools/make-keyboard-text/res/values-nb/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-nb/donottranslate-more-keys.xml
@@ -18,13 +18,15 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
+    <!-- U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
+         U+00E6: "æ" LATIN SMALL LETTER AE
          U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
          U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
          U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
-    <string name="morekeys_a">&#x00E0;,&#x00E4;,&#x00E1;,&#x00E2;,&#x00E3;,&#x0101;</string>
+    <string name="morekeys_a">&#x00E5;,&#x00E6;,&#x00E4;,&#x00E0;,&#x00E1;,&#x00E2;,&#x00E3;,&#x0101;</string>
     <!-- U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE
          U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE
          U+00EA: "ê" LATIN SMALL LETTER E WITH CIRCUMFLEX
@@ -33,14 +35,15 @@
          U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE
          U+0113: "ē" LATIN SMALL LETTER E WITH MACRON -->
     <string name="morekeys_e">&#x00E9;,&#x00E8;,&#x00EA;,&#x00EB;,&#x0119;,&#x0117;,&#x0113;</string>
-    <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+    <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
          U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
          U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
-         U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
          U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
          U+0153: "œ" LATIN SMALL LIGATURE OE
          U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
-    <string name="morekeys_o">&#x00F4;,&#x00F2;,&#x00F3;,&#x00F6;,&#x00F5;,&#x0153;,&#x014D;</string>
+    <string name="morekeys_o">&#x00F8;,&#x00F6;,&#x00F4;,&#x00F2;,&#x00F3;,&#x00F5;,&#x0153;,&#x014D;</string>
     <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
          U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
          U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
diff --git a/tools/make-keyboard-text/res/values-ne-rNP/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-ne-rNP/donottranslate-more-keys.xml
index 97c50d1..56b594f 100644
--- a/tools/make-keyboard-text/res/values-ne-rNP/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-ne-rNP/donottranslate-more-keys.xml
@@ -57,4 +57,9 @@
     <string name="additional_morekeys_symbols_0">0</string>
     <!-- U+0930/U+0941/U+002E "रु." NEPALESE RUPEE SIGN -->
     <string name="keyspec_currency">&#x0930;&#x0941;&#x002E;</string>
+    <!-- U+0964: "।" DEVANAGARI DANDA -->
+    <string name="keyspec_period">&#x0964;</string>
+    <string name="keyspec_tablet_period">&#x0964;</string>
+    <string name="morekeys_period">"!autoColumnOrder!9,.,\\,,?,!,#,),(,/,;,',@,:,-,\",+,\\%,&amp;"</string>
+    <string name="morekeys_tablet_period">"!autoColumnOrder!8,.,\\,,',#,),(,/,;,@,:,-,\",+,\\%,&amp;"</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-ro/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-ro/donottranslate-more-keys.xml
index 6286c7b..834e039 100644
--- a/tools/make-keyboard-text/res/values-ro/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-ro/donottranslate-more-keys.xml
@@ -18,16 +18,16 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+    <!-- U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
+         U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE
-         U+0103: "ă" LATIN SMALL LETTER A WITH BREVE
          U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
          U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
          U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
          U+00E6: "æ" LATIN SMALL LETTER AE
          U+00E5: "å" LATIN SMALL LETTER A WITH RING ABOVE
          U+0101: "ā" LATIN SMALL LETTER A WITH MACRON -->
-    <string name="morekeys_a">&#x00E2;,&#x00E3;,&#x0103;,&#x00E0;,&#x00E1;,&#x00E4;,&#x00E6;,&#x00E5;,&#x0101;</string>
+    <string name="morekeys_a">&#x0103;,&#x00E2;,&#x00E3;,&#x00E0;,&#x00E1;,&#x00E4;,&#x00E6;,&#x00E5;,&#x0101;</string>
     <!-- U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
          U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
          U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
diff --git a/tools/make-keyboard-text/res/values-sr-rZZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-sr-rZZ/donottranslate-more-keys.xml
new file mode 100644
index 0000000..1168126
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-sr-rZZ/donottranslate-more-keys.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE -->
+    <string name="morekeys_e">&#x00E8;</string>
+    <!-- U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE -->
+    <string name="morekeys_i">&#x00EC;</string>
+    <!-- U+0161: "š" LATIN SMALL LETTER S WITH CARON -->
+    <string name="morekeys_s">&#x0161;,%</string>
+    <!-- U+010D: "č" LATIN SMALL LETTER C WITH CARON
+         U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE -->
+    <string name="morekeys_c">&#x010D;,&#x0107;,%</string>
+    <!-- U+0111: "đ" LATIN SMALL LETTER D WITH STROKE -->
+    <string name="morekeys_d">&#x0111;,%</string>
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <string name="morekeys_z">&#x017E;,%</string>
+    <string name="label_go_key">"Idi"</string>
+    <string name="label_send_key">"Šalji"</string>
+    <string name="label_next_key">"Sled"</string>
+    <string name="label_done_key">"Gotov"</string>
+    <string name="label_search_key">"Traži"</string>
+    <string name="label_previous_key">"Preth"</string>
+    <string name="label_pause_key">"Pauza"</string>
+    <string name="label_wait_key">"Čekaj"</string>
+</resources>
diff --git a/tools/make-keyboard-text/res/values-sv/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-sv/donottranslate-more-keys.xml
index ead5140..832e438 100644
--- a/tools/make-keyboard-text/res/values-sv/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-sv/donottranslate-more-keys.xml
@@ -18,12 +18,15 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
+    <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E5: "å" LATIN SMALL LETTER A WITH RING
+         U+00E6: "æ" LATIN SMALL LETTER AE
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE
          U+00E0: "à" LATIN SMALL LETTER A WITH GRAVE
          U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
          U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK
          U+00E3: "ã" LATIN SMALL LETTER A WITH TILDE -->
-    <string name="morekeys_a">&#x00E1;,&#x00E0;,&#x00E2;,&#x0105;,&#x00E3;</string>
+    <string name="morekeys_a">&#x00E4;,&#x00E5;,&#x00E6;,&#x00E1;,&#x00E0;,&#x00E2;,&#x0105;,&#x00E3;</string>
     <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
          U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
@@ -48,12 +51,15 @@
          U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE
          U+0148: "ň" LATIN SMALL LETTER N WITH CARON -->
     <string name="morekeys_n">&#x0144;,&#x00F1;,&#x0148;</string>
-    <!-- U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+    <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+0153: "œ" LATIN SMALL LIGATURE OE
+         U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
          U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
          U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
          U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
          U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
-    <string name="morekeys_o">&#x00F3;,&#x00F2;,&#x00F4;,&#x00F5;,&#x014D;</string>
+    <string name="morekeys_o">&#x00F6;,&#x00F8;,&#x0153;,&#x00F3;,&#x00F2;,&#x00F4;,&#x00F5;,&#x014D;</string>
     <!-- U+0159: "ř" LATIN SMALL LETTER R WITH CARON -->
     <string name="morekeys_r">&#x0159;</string>
     <!-- U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
diff --git a/tools/make-keyboard-text/res/values-tr/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-tr/donottranslate-more-keys.xml
index db1108f..2398430 100644
--- a/tools/make-keyboard-text/res/values-tr/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values-tr/donottranslate-more-keys.xml
@@ -18,8 +18,13 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX -->
-    <string name="morekeys_a">&#x00E2;</string>
+    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE -->
+    <string name="morekeys_a">&#x00E2;,&#x00E4;,&#x00E1;</string>
+    <!-- U+0259: "ə" LATIN SMALL LETTER SCHWA
+         U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+    <string name="morekeys_e">&#x0259;,&#x00E9;</string>
     <!-- U+0131: "ı" LATIN SMALL LETTER DOTLESS I
          U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
          U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
@@ -50,8 +55,15 @@
     <string name="morekeys_s">&#x015F;,&#x00DF;,&#x015B;,&#x0161;</string>
     <!-- U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
     <string name="morekeys_g">&#x011F;</string>
+    <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+         U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+    <string name="morekeys_n">&#x0148;,&#x00F1;</string>
     <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
          U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
          U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
     <string name="morekeys_c">&#x00E7;,&#x0107;,&#x010D;</string>
+    <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE -->
+    <string name="morekeys_y">&#x00FD;</string>
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <string name="morekeys_z">&#x017E;</string>
 </resources>
diff --git a/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml
new file mode 100644
index 0000000..24dd091
--- /dev/null
+++ b/tools/make-keyboard-text/res/values-uz-rUZ/donottranslate-more-keys.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2014, 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- This is the same as Turkish -->
+    <!-- U+00E2: "â" LATIN SMALL LETTER A WITH CIRCUMFLEX
+         U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS
+         U+00E1: "á" LATIN SMALL LETTER A WITH ACUTE -->
+    <string name="morekeys_a">&#x00E2;,&#x00E4;,&#x00E1;</string>
+    <!-- U+0259: "ə" LATIN SMALL LETTER SCHWA
+         U+00E9: "é" LATIN SMALL LETTER E WITH ACUTE -->
+    <string name="morekeys_e">&#x0259;,&#x00E9;</string>
+    <!-- U+0131: "ı" LATIN SMALL LETTER DOTLESS I
+         U+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX
+         U+00EF: "ï" LATIN SMALL LETTER I WITH DIAERESIS
+         U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE
+         U+00ED: "í" LATIN SMALL LETTER I WITH ACUTE
+         U+012F: "į" LATIN SMALL LETTER I WITH OGONEK
+         U+012B: "ī" LATIN SMALL LETTER I WITH MACRON -->
+    <string name="morekeys_i">&#x0131;,&#x00EE;,&#x00EF;,&#x00EC;,&#x00ED;,&#x012F;,&#x012B;</string>
+    <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS
+         U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX
+         U+0153: "œ" LATIN SMALL LIGATURE OE
+         U+00F2: "ò" LATIN SMALL LETTER O WITH GRAVE
+         U+00F3: "ó" LATIN SMALL LETTER O WITH ACUTE
+         U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE
+         U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE
+         U+014D: "ō" LATIN SMALL LETTER O WITH MACRON -->
+    <string name="morekeys_o">&#x00F6;,&#x00F4;,&#x0153;,&#x00F2;,&#x00F3;,&#x00F5;,&#x00F8;,&#x014D;</string>
+    <!-- U+00FC: "ü" LATIN SMALL LETTER U WITH DIAERESIS
+         U+00FB: "û" LATIN SMALL LETTER U WITH CIRCUMFLEX
+         U+00F9: "ù" LATIN SMALL LETTER U WITH GRAVE
+         U+00FA: "ú" LATIN SMALL LETTER U WITH ACUTE
+         U+016B: "ū" LATIN SMALL LETTER U WITH MACRON -->
+    <string name="morekeys_u">&#x00FC;,&#x00FB;,&#x00F9;,&#x00FA;,&#x016B;</string>
+    <!-- U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA
+         U+00DF: "ß" LATIN SMALL LETTER SHARP S
+         U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE
+         U+0161: "š" LATIN SMALL LETTER S WITH CARON -->
+    <string name="morekeys_s">&#x015F;,&#x00DF;,&#x015B;,&#x0161;</string>
+    <!-- U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE -->
+    <string name="morekeys_g">&#x011F;</string>
+    <!-- U+0148: "ň" LATIN SMALL LETTER N WITH CARON
+         U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE -->
+    <string name="morekeys_n">&#x0148;,&#x00F1;</string>
+    <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA
+         U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE
+         U+010D: "č" LATIN SMALL LETTER C WITH CARON -->
+    <string name="morekeys_c">&#x00E7;,&#x0107;,&#x010D;</string>
+    <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE -->
+    <string name="morekeys_y">&#x00FD;</string>
+    <!-- U+017E: "ž" LATIN SMALL LETTER Z WITH CARON -->
+    <string name="morekeys_z">&#x017E;</string>
+</resources>
diff --git a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
index c4a1b88..b6da7d1 100644
--- a/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
+++ b/tools/make-keyboard-text/res/values/donottranslate-more-keys.xml
@@ -259,4 +259,12 @@
     <string name="morekeys_double_quote">!fixedColumnOrder!5,!text/double_quotes,!text/double_angle_quotes</string>
     <string name="morekeys_tablet_double_quote">!fixedColumnOrder!6,!text/double_quotes,!text/single_quotes,!text/double_angle_quotes,!text/single_angle_quotes</string>
     <string name="keyspec_emoji_action_key">!icon/emoji_action_key|!code/key_emoji</string>
+    <string name="label_go_key">!string/label_go_key</string>
+    <string name="label_send_key">!string/label_send_key</string>
+    <string name="label_next_key">!string/label_next_key</string>
+    <string name="label_done_key">!string/label_done_key</string>
+    <string name="label_search_key">!string/label_search_key</string>
+    <string name="label_previous_key">!string/label_previous_key</string>
+    <string name="label_pause_key">!string/label_pause_key</string>
+    <string name="label_wait_key">!string/label_wait_key</string>
 </resources>